Public bug reported:

root@master:~/software/test# cat /etc/os-release 
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/";
SUPPORT_URL="https://help.ubuntu.com/";
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/";
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy";
UBUNTU_CODENAME=jammy

procps  2:3.3.17-6ubuntu2

root@master:~/software/test# strace -f  kill -15 -2345
execve("/usr/bin/kill", ["kill", "-15", "-2345"], 0x7ffc2eb1ba28 /* 34 vars */) 
= 0
brk(NULL)                               = 0x55ac1f787000
kill(0, SIGTERMstrace: Process 228286 detached
 <detached ...>
Terminated

when pid is not exist negative pid(-2345), then become 0

test code:
```c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>

void parentProcess();
void childProcess();

static struct sigaction siga;

static void signal_handler(int sig, siginfo_t *siginfo, void *context) {
    // get pid of sender,
    pid_t sender_pid = siginfo->si_pid;

    if(sig == SIGTERM) {
        printf("TERM, from [%d]\n", (int)sender_pid);
        return;
    }

    return;
}

int main(int argc, const char *argv[])
{
        int   status;
        // prepare sigaction
    siga.sa_sigaction = *signal_handler;
    siga.sa_flags |= SA_SIGINFO; // get detail info
        if(sigaction(SIGTERM, &siga, NULL) != 0) {
                printf("error sigaction()");
                return errno;
    }
        
        int pid = fork();
        
        if (pid != 0) {
                parentProcess();
                pid = wait(&status);
                printf("End of process %d: \n", pid);
                if (WIFEXITED(status)) {
                        printf("The child process ended with exit(%d).\n", 
WEXITSTATUS(status));
                }
                if (WIFSIGNALED(status)) {
                        printf("The child process ended with kill -%d.\n", 
WTERMSIG(status));
                }
        }
        else 
                childProcess();
        
        return 0;
}

void parentProcess()
{
        pid_t pid = getpid(); 
        char prefix[] = "Parent: ";
        printf("%sPID:%d %s\n", prefix, pid, "");
}

void childProcess()
{
        pid_t pid = getpid();   
        char prefix[] = "Child: ";
        printf("%sPID:%d %s\n", prefix, pid, "");
        char *args[4];

    args[0] = "kill";        // first arg is the full path to the executable
    args[1] = "-15";
        args[2] = "-2345";
        args[3] = NULL; // list of args must be NULL terminated
        execv( "/bin/kill", args );
        
        sleep(5);
}

```

pid equals 0, then sig is sent to every process in the process group of
the calling process.

skill.c code:

```c
static void __attribute__ ((__noreturn__))
    kill_main(int argc, char **argv)
{
        int signo, i;
        long pid;
        int exitvalue = EXIT_SUCCESS;
        union sigval sigval;
        bool use_sigqueue = false;
        char *sig_option;

        static const struct option longopts[] = {
                {"list", optional_argument, NULL, 'l'},
                {"table", no_argument, NULL, 'L'},
                {"signal", required_argument, NULL, 's'},
                {"help", no_argument, NULL, 'h'},
                {"version", no_argument, NULL, 'V'},
                {"queue", required_argument, NULL, 'q'},
                {NULL, 0, NULL, 0}
        };

        setlocale (LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
        atexit(close_stdout);

        if (argc < 2)
                kill_usage(stderr);

        signo = skill_sig_option(&argc, argv);
        if (signo < 0)
                signo = SIGTERM;

        opterr=0; /* suppress errors on -123 */
        while ((i = getopt_long(argc, argv, "l::Ls:hVq:", longopts, NULL)) != 
-1)
                switch (i) {

                case '?':
                        if (!isdigit(optopt)) {
                                xwarnx(_("invalid argument %c"), optopt);
                                kill_usage(stderr);
                        } else {
                            /* Special case for signal digit negative
                             * PIDs */
                            pid = atoi(argv[optind-1]);
                            if (kill((pid_t)pid, signo) != 0)
                                exitvalue = EXIT_FAILURE;
                            exit(exitvalue);
                        }
                        xerrx(EXIT_FAILURE, _("internal error"));
                default:
                        kill_usage(stderr);
                }
}

```

maybe getopt_long parse negative pid(-2345) as opt,so pid =
atoi(argv[optind-1]) become 0.

** Affects: procps (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to procps in Ubuntu.
https://bugs.launchpad.net/bugs/2025603

Title:
  /bin/kill in ubuntu22.04 has bug in killing process group

Status in procps package in Ubuntu:
  New

Bug description:
  root@master:~/software/test# cat /etc/os-release 
  PRETTY_NAME="Ubuntu 22.04.1 LTS"
  NAME="Ubuntu"
  VERSION_ID="22.04"
  VERSION="22.04.1 LTS (Jammy Jellyfish)"
  VERSION_CODENAME=jammy
  ID=ubuntu
  ID_LIKE=debian
  HOME_URL="https://www.ubuntu.com/";
  SUPPORT_URL="https://help.ubuntu.com/";
  BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/";
  
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy";
  UBUNTU_CODENAME=jammy

  procps  2:3.3.17-6ubuntu2

  root@master:~/software/test# strace -f  kill -15 -2345
  execve("/usr/bin/kill", ["kill", "-15", "-2345"], 0x7ffc2eb1ba28 /* 34 vars 
*/) = 0
  brk(NULL)                               = 0x55ac1f787000
  kill(0, SIGTERMstrace: Process 228286 detached
   <detached ...>
  Terminated

  when pid is not exist negative pid(-2345), then become 0

  test code:
  ```c
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <unistd.h>
  #include <signal.h>
  #include <errno.h>
  #include <pthread.h>

  void parentProcess();
  void childProcess();

  static struct sigaction siga;

  static void signal_handler(int sig, siginfo_t *siginfo, void *context) {
      // get pid of sender,
      pid_t sender_pid = siginfo->si_pid;

      if(sig == SIGTERM) {
          printf("TERM, from [%d]\n", (int)sender_pid);
          return;
      }

      return;
  }

  int main(int argc, const char *argv[])
  {
        int   status;
        // prepare sigaction
      siga.sa_sigaction = *signal_handler;
      siga.sa_flags |= SA_SIGINFO; // get detail info
        if(sigaction(SIGTERM, &siga, NULL) != 0) {
                printf("error sigaction()");
                return errno;
      }
        
        int pid = fork();
        
        if (pid != 0) {
                parentProcess();
                pid = wait(&status);
                printf("End of process %d: \n", pid);
                if (WIFEXITED(status)) {
                        printf("The child process ended with exit(%d).\n", 
WEXITSTATUS(status));
                }
                if (WIFSIGNALED(status)) {
                        printf("The child process ended with kill -%d.\n", 
WTERMSIG(status));
                }
        }
        else 
                childProcess();
        
        return 0;
  }

  void parentProcess()
  {
        pid_t pid = getpid(); 
        char prefix[] = "Parent: ";
        printf("%sPID:%d %s\n", prefix, pid, "");
  }

  void childProcess()
  {
        pid_t pid = getpid();   
        char prefix[] = "Child: ";
        printf("%sPID:%d %s\n", prefix, pid, "");
        char *args[4];

      args[0] = "kill";        // first arg is the full path to the executable
      args[1] = "-15";
        args[2] = "-2345";
        args[3] = NULL; // list of args must be NULL terminated
        execv( "/bin/kill", args );
        
        sleep(5);
  }

  ```

  pid equals 0, then sig is sent to every process in the process group
  of the calling process.

  skill.c code:

  ```c
  static void __attribute__ ((__noreturn__))
      kill_main(int argc, char **argv)
  {
        int signo, i;
        long pid;
        int exitvalue = EXIT_SUCCESS;
        union sigval sigval;
        bool use_sigqueue = false;
        char *sig_option;

        static const struct option longopts[] = {
                {"list", optional_argument, NULL, 'l'},
                {"table", no_argument, NULL, 'L'},
                {"signal", required_argument, NULL, 's'},
                {"help", no_argument, NULL, 'h'},
                {"version", no_argument, NULL, 'V'},
                {"queue", required_argument, NULL, 'q'},
                {NULL, 0, NULL, 0}
        };

        setlocale (LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
        atexit(close_stdout);

        if (argc < 2)
                kill_usage(stderr);

        signo = skill_sig_option(&argc, argv);
        if (signo < 0)
                signo = SIGTERM;

        opterr=0; /* suppress errors on -123 */
        while ((i = getopt_long(argc, argv, "l::Ls:hVq:", longopts, NULL)) != 
-1)
                switch (i) {

                case '?':
                        if (!isdigit(optopt)) {
                                xwarnx(_("invalid argument %c"), optopt);
                                kill_usage(stderr);
                        } else {
                            /* Special case for signal digit negative
                             * PIDs */
                            pid = atoi(argv[optind-1]);
                            if (kill((pid_t)pid, signo) != 0)
                                exitvalue = EXIT_FAILURE;
                            exit(exitvalue);
                        }
                        xerrx(EXIT_FAILURE, _("internal error"));
                default:
                        kill_usage(stderr);
                }
  }

  ```

  maybe getopt_long parse negative pid(-2345) as opt,so pid =
  atoi(argv[optind-1]) become 0.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/procps/+bug/2025603/+subscriptions


-- 
Mailing list: https://launchpad.net/~touch-packages
Post to     : touch-packages@lists.launchpad.net
Unsubscribe : https://launchpad.net/~touch-packages
More help   : https://help.launchpad.net/ListHelp

Reply via email to