When testing compatibility for an update of a legacy program in OpenSUSE, I traced the problem to a strange version difference. The following C program creates a child process in sudo, and then kills this process in sudo:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
char execName[80] = "/usr/bin/sudo";
char cmd[128];
int pid = 0;
int SIG = 15;
if (argc > 1) SIG = atoi(argv[1]);
printf("Sudo sleeping for 30 seconds.\n");
printf("Sudo killing with signal %d.\n", SIG);
printf("Use `ps aux | grep sleep` within 30 seconds to verify it was killed. Only this grep should show.\n");
if ((pid = vfork()) == 0) {
execl (execName, execName, "/bin/sleep", "30", (char *)NULL);
perror(execName);
exit (-1);
} else {
if (pid == -1) perror("Bad PID for sleeper");
fprintf( stderr, "sleeper process PID = %d\n", pid );
}
sprintf(cmd, "/usr/bin/sudo kill -%d %d", SIG, pid);
system(cmd);
}
In order to execute this code, users need to be given access to sudo
, and sudoers
needs to be given access to kill
.
This accurately represents how the legacy program works, except the sleeper program is a process that runs continuously, and there are more steps in between. Unfortunately, it is not realistic to abandon this program entirely.
In OpenSUSE 13.2, this program successfully kills the sleeper. However, in OpenSUSE 42.3, the sleeper remains. Why? How can I rewrite this so that I can give my own sudo children in OpenSUSE 42.3 a kill signal?
As an experiment, I changed the final system call to /usr/bin/sudo pkill -15 -P %d
, where %d
is the process ID. For some reason, this worked across versions, although not reliably. None of the theories I had for why these differ could adequately explain why this works.