Pop quiz: What's wrong with dropping privileges of a process, started as root, to "nobody", like this?
my $uid = getpwnam("nobody");
$< = $uid;
Answer: It's easy to regain root privileges afterwards by simply assigning 0 to $<.
Why is that? Turns out that assigning a uid to $< (or the effective uid $> for that matter) isn't using setuid(), at least not on Linux. Instead, it uses setreuid32() which allows the unprivileged user to switch back to the "saved set-user-ID".
You can see what's going on in a perl script like
$< = $uid;
$> = $uid;
$> = 0;
$< = 0;
by looking at the strace output:
$ sudo strace ./switchback 2>&1 | grep '^set'
setreuid32(99, -1) = 0
setresuid32(-1, 99, -1) = 0
setresuid32(-1, 0, -1) = 0
setreuid32(0, -1) = 0
The last two calls successfully restore root privileges (uid and euid) while running as an unprivileged user.
Question: What's the best way to drop privileges, then? POSIX:setuid( $uid ) seems to work, is that the best practice?