After start up I'd like my Linux program to drop root privileges and switch to a non-privileged account. I've found various examples online but nothing canonical for my requirements, specifically:
The best approach I've found is:
uid_t new_uid = ...;
gid_t new_gid = ...;
gid_t rgid, egid, sgid;
if (setresgid(new_gid, new_gid, new_gid) < 0)
{
perror("setresgid");
exit(EXIT_FAILURE);
}
if (getresgid(&rgid, &egid, &sgid) < 0)
{
perror("getresgid");
exit(EXIT_FAILURE);
}
if (rgid != new_gid || egid != new_gid || sgid != new_gid)
{
printf("unexpected gid");
exit(EXIT_FAILURE);
}
if (setgroups(0, 0) != 0)
{
perror("setgroups");
exit(EXIT_FAILURE);
}
uid_t ruid, euid, suid;
if (setresuid(new_uid, new_uid, new_uid) < 0)
{
perror("setresuid");
exit(EXIT_FAILURE);
}
if (getresuid(&ruid, &euid, &suid) < 0)
{
perror("getresuid");
exit(EXIT_FAILURE);
}
if (ruid != new_uid || euid != new_uid || suid != new_uid)
{
printf("unexpected uid");
exit(EXIT_FAILURE);
}
I can wrap this in an exe and demonstrate that the uid's and gid's appear correct using:
ps -eO user,uid,ruid,suid,group,gid,rgid,sgid
The program can't bind to a privileged port or manipulate most root-owned files, so that's all good.
I've also found the captest program (included in libcap-ng-utils) which verifies that the process does not have any unexpected capabilities(7).
However, since security is a concern I'd like to be more confident that I've dropped all non-essential privileges correctly. How can I be certain?
Thanks.
The "canonical" way to do this was implemented by D.J.Bernstein in his 'setuidgid' code, which was originally used into his QMail program, nowadays included in 'daemontools'.
The actual code used in GNU coreutils is based on DJB's description of the procedure, its code is visible here https://github.com/wertarbyte/coreutils/blob/master/src/setuidgid.c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With