[Bug 2025603] [NEW] /bin/kill in ubuntu22.04 has bug in killing process group

li liao 2025603 at bugs.launchpad.net
Mon Jul 3 08:57:47 UTC 2023


Public bug reported:

root at 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 at 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
Foundations Bugs, 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 at 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 at 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




More information about the foundations-bugs mailing list