How do I drop root privileges in shell scripts?
Covering only runit and sudo misses a lot. There is actually a whole family of toolsets like runit, and a wide choice of tools for doing exactly this, the very task that they were designed for:
- Daniel J. Bernstein's daemontools has
setuidgid
:setuidgid user /home/user/unprivileged.sh
- util-linux (installed by default on newer Debians) has
setpriv
:setpriv --reuid=user --regid=group --init-groups --inh-caps=-all /home/user/unprivileged.sh
- Adam Sampson's freedt has
setuidgid
:setuidgid user /home/user/unprivileged.sh
- Bruce Guenter's daemontools-encore has
setuidgid
:setuidgid user /home/user/unprivileged.sh
- Gerrit Pape's runit has
chpst
:chpst -u user /home/user/unprivileged.sh
- Wayne Marshall's perp has
runuid
:runuid user /home/user/unprivileged.sh
- Laurent Bercot's s6 has
s6-setuidgid
:s6-setuidgid user /home/user/unprivileged.sh
- my nosh has
setuidgid
:setuidgid user /home/user/unprivileged.sh
They don't mix in the different task of adding privileges, and never fall into an interactive mode.
Your tacked-on problems are little more than your forgetting to have sbin
as well as bin
in your PATH
, by the way.
Further reading
- Jonathan de Boyne Pollard (2014). Don't abuse su for dropping user privileges. Frequently Given Answers.
I use runit's chpst
tool for tasks like this. For example, from the up script call your unprivileged script:
chpst -u nobody /path/to/script
script which drops privileges and runs other script (but here I just made it to run itself):
#!/bin/sh
id=`id -u`
safeuser="nobody"
if [ $id = "0" ]
then
# we're root. dangerous!
sudo -u $safeuser "$0" # Be sure to quote "$0"
else
echo "I'm not root"
id
fi
Example:
root@n3:/tmp/x# id
uid=0(root) gid=0(root) группы=0(root)
root@n3:/tmp/x# ./drop.sh
I'm not root
uid=65534(nobody) gid=65534(nogroup) группы=65534(nogroup)