https://stackoverflow.com

sudo ignores SIGTERM sent from same script

I'm trying to figure out why this doesn't work:

#!/bin/bash

sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid

I'd expect that after the kill, the sudo command and its child sleep process would be terminated, but they aren't, as shown by this script:

#!/bin/bash

sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid

if ps -p $sudo_pid > /dev/null; then
    sudo kill $sudo_pid
else
    echo "No sudo process running"
    exit 1
fi

if ps -p $sudo_pid > /dev/null; then
    echo "sudo (pid $sudo_pid) is still running"
    ps -F $sudo_pid
else
    echo "sudo successfully killed"
fi

Which yields this output when I run it (with sudo creds cached):

jon@ubuntu:~$ ./so.sh
sudo (pid 46199) is still running
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD
root      46199  46198  0 14764  3984   3 13:37 pts/0    S+     0:00 sudo sleep 60

After the script completes (and sudo sleep 60 is still running), it is possible to kill it with the identical command:

jon@ubuntu:~$ ps -F 46199
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD
root      46199      1  0 14764  3984   3 13:37 pts/0    S      0:00 sudo sleep 60

jon@ubuntu:~$ sudo kill 46199

jon@ubuntu:~$ ps -F 46199
UID         PID   PPID  C    SZ   RSS PSR STIME TTY      STAT   TIME CMD

jon@ubuntu:~$

I notice that after the so.sh script exits, the parent process ID for sudo sleep 60 has changed from the script to the init process, which I think is significant. It's also possible to successfully kill the sudo sleep 60 process from a different shell while the so.sh script is still running.

I also noticed that using sudo kill -ABRT in the script (as opposed to kill's default SIGTERM) does successfully kill the sudo process, so I assume that is has something to do with the way sudo handles SIGTERM. However, based on the man page, I don't think it should be doing anything special:

Signal handling
  When the command is run as a child of the sudo process, sudo will relay
  signals it receives to the command.  The SIGINT and SIGQUIT signals are
  only relayed when the command is being run in a new pty or when the sig‐
  nal was sent by a user process, not the kernel.  This prevents the com‐
  mand from receiving SIGINT twice each time the user enters control-C.

The only special handling of SIGTERM mentioned in the man page is for signals that were sent by the command it is running; not the case here. Furthermore, I changed the ps -F in above script to ps -o blocked,caught,ignored,pending and it output

sudo (pid 46429) is still running
         BLOCKED           CAUGHT          IGNORED          PENDING
0000000000000000 00000001800b7a07 0000000000000000 0000000000000000

Which seems to indicate that SIGTERM isn't being blocked or ignored, so why isn't the sudo sleep 60 process getting terminated?

I've come up with several workarounds ( setsid, sudo -b, killing the child sleep process rather than the parent sudo process), so I'm not looking for alternate approach answers. I just want to understand what's going on here.

In case it matters:

jon@ubuntu:~$ uname -a
Linux ubuntu 4.13.0-16-generic #19-Ubuntu SMP Wed Oct 11 18:35:14 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
jon@ubuntu:~$ sudo --version
Sudo version 1.8.20p2
Sudoers policy plugin version 1.8.20p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.20p2