This reminds me of a bugfix [1] I added to nmap almost a decade ago, where runtime interaction was previously broken due to interaction with sudo and signal propagation. Was a fun rabbit-hole to figure out why the issue was happening.
Back in 2017, the Linux developers' notion was that not even all of this PAM stuff was enough for the parent process to be doing.
Their then asserted correct solution to TIOCSTI was that su, sudo, doas, and the like should open a pseudo-terminal and get involved in pumping pseudo-terminal I/O. They were to do this as well as, presumably, managing all of setsid(), child process stopping/suspending with a signal, and setlogname() for the new session; to keep what the old books all say about keeping the same logname even though one has switched user, and being able to use the suspend command in the second shell.
> Another point Alan brought up is that if a program is careless enough not to allocate a new pty, it's probably also careless enough not to close any fd's that might be open in the parent shell or by the program
itself.
Oof, weird inference. File inheritance is pretty well known. TIOCSTI is really esoteric.
It's quite possible to build and use sudo without PAM support even on Linux, most distributions just tend to build everything in "kitchen sink" mode. If I remember right on Alpine it's PAM-free by default so it doesn't need to fork. On Gentoo it's behind a USE flag.
Requiring pam_close_session is just bad design - if it needs special cleanup, pam_open_session should grab process pidfd and spawn separate monitor process (or pass pidfd to existing daemon).
PAM predates pidfd by about 25 years or so, though it's really weird how steadfastly unix heritage systems avoided handles for important things, resulting in race conditions and security issues all over the place.
setpriv is very much a Johnny-come-lately here, dating from 2013, which was almost a decade and a half afterwards.
If you have BusyBox installed, you have runit's chpst and setuidgid built in to it. And most Linux distributions not only package that but also package one or more of these toolsets; most often daemontools and runit, but nosh has an Arch package for example.
That seems like a disingenuous title, it's not abusing su, that's just one of the many things that tool was used for. That was never a bad practice, the tool just changed and pulled the rug out from under very many programs.
Looking at the shell script, is kill guaranteed to be synchronous? I.e., isn’t there a race condition anyway between kill returning and SIGTERM being processed by the target process?
I don't do a lot of bash scripting but is this common? Using sudo in a script? Seems weird to me. If the process needs root just run the script as root right?
It is not common, but could be considered best practise in some circumstances because it limits the amount of time the script and any child processes are running with extra privileges and so reduces the potential splash damage of any bugs in the unprivileged parts of the script. If your sudo is configured not to prompt for auth every time (the usual default) the user being reprompted for auth each time is not an issue¹.
I've needed to use it in some scripts for checking/managing content on FUSE mounts which are mounted without “-o allow_root”, here calling the script through sudo doesn't do the full job as root can't access the content through the fuse-based mount so we sudo again to impersonate the user owning the mount.
----
[1] if the script may be a while doing other things before the first sudo call, you might want to run “sudo -v”² early on meaning the user can give auth at the start if needed so they don't run your script, it ask for auth a minute later, and them not notice as they are looking at something else at the time.
[2] from the manpage: -v, --validate, Update the user's cached credentials, authenticating the user if necessary.
sudo isn't exclusively for root privileges. I've set up generic users with complex home/config setups where the script itself was rather simple but relied on a lot of the environment.
also, sudo can be used to explicitly whitelist certain commands, so "killall processname" can work, but "rm - rf" wont. If you run the whole script as root, everyone who can edit can introduce a footgun.
This reminds me of a bugfix [1] I added to nmap almost a decade ago, where runtime interaction was previously broken due to interaction with sudo and signal propagation. Was a fun rabbit-hole to figure out why the issue was happening.
[1]: https://github.com/nmap/nmap/commit/f2e162d2245679f420b40feb...
ELI5, why is there a separate sudo process instead of sudo finishing by calling exec()?
PAM changed everything, back in the 1990s.
* https://jdebp.uk/FGA/dont-abuse-su-for-dropping-privileges.h...
> aside from a few hold-out BSDs and BSD-derived systems
One wonders if perhaps these systems weren't on to something.
Back in 2017, the Linux developers' notion was that not even all of this PAM stuff was enough for the parent process to be doing.
Their then asserted correct solution to TIOCSTI was that su, sudo, doas, and the like should open a pseudo-terminal and get involved in pumping pseudo-terminal I/O. They were to do this as well as, presumably, managing all of setsid(), child process stopping/suspending with a signal, and setlogname() for the new session; to keep what the old books all say about keeping the same logname even though one has switched user, and being able to use the suspend command in the second shell.
* https://www.openwall.com/lists/oss-security/2017/06/03/9
* https://www.openwall.com/lists/kernel-hardening/2017/05/10/3...
Six months ago, TIOCSTI became optional in Linux.
> Another point Alan brought up is that if a program is careless enough not to allocate a new pty, it's probably also careless enough not to close any fd's that might be open in the parent shell or by the program itself.
Oof, weird inference. File inheritance is pretty well known. TIOCSTI is really esoteric.
It's quite possible to build and use sudo without PAM support even on Linux, most distributions just tend to build everything in "kitchen sink" mode. If I remember right on Alpine it's PAM-free by default so it doesn't need to fork. On Gentoo it's behind a USE flag.
Requiring pam_close_session is just bad design - if it needs special cleanup, pam_open_session should grab process pidfd and spawn separate monitor process (or pass pidfd to existing daemon).
PAM predates pidfd by about 25 years or so, though it's really weird how steadfastly unix heritage systems avoided handles for important things, resulting in race conditions and security issues all over the place.
Which is definitely what you want in your authentication subsystem.
sudo is that monitor process, it's the same with how containerd and podman work, it's much much easier to babysit a process when you're its parent.
This article's list of privilige dropping tools is missing setpriv(1) from util-linux, which is the only one actually installed on my system.
setpriv is very much a Johnny-come-lately here, dating from 2013, which was almost a decade and a half afterwards.
If you have BusyBox installed, you have runit's chpst and setuidgid built in to it. And most Linux distributions not only package that but also package one or more of these toolsets; most often daemontools and runit, but nosh has an Arch package for example.
That seems like a disingenuous title, it's not abusing su, that's just one of the many things that tool was used for. That was never a bad practice, the tool just changed and pulled the rug out from under very many programs.
TL;DR: PAM requires session cleanup, which might require extra privileges.
Looking at the shell script, is kill guaranteed to be synchronous? I.e., isn’t there a race condition anyway between kill returning and SIGTERM being processed by the target process?
I don't do a lot of bash scripting but is this common? Using sudo in a script? Seems weird to me. If the process needs root just run the script as root right?
If the whole script is run with sudo, then all parts of the script that wouldn't have needed suddenly become dangerous.
It is not common, but could be considered best practise in some circumstances because it limits the amount of time the script and any child processes are running with extra privileges and so reduces the potential splash damage of any bugs in the unprivileged parts of the script. If your sudo is configured not to prompt for auth every time (the usual default) the user being reprompted for auth each time is not an issue¹.
I've needed to use it in some scripts for checking/managing content on FUSE mounts which are mounted without “-o allow_root”, here calling the script through sudo doesn't do the full job as root can't access the content through the fuse-based mount so we sudo again to impersonate the user owning the mount.
----
[1] if the script may be a while doing other things before the first sudo call, you might want to run “sudo -v”² early on meaning the user can give auth at the start if needed so they don't run your script, it ask for auth a minute later, and them not notice as they are looking at something else at the time.
[2] from the manpage: -v, --validate, Update the user's cached credentials, authenticating the user if necessary.
sudo isn't exclusively for root privileges. I've set up generic users with complex home/config setups where the script itself was rather simple but relied on a lot of the environment.
also, sudo can be used to explicitly whitelist certain commands, so "killall processname" can work, but "rm - rf" wont. If you run the whole script as root, everyone who can edit can introduce a footgun.
It’s not common. but employ’s the least privilege principle, so there’s that