Omnifarious
Omnifarious

Reputation: 56078

How do I drop supplementary groups in Linux?

I have an executable that's ug+s to a non-root user and group. I would like it to leave all the supplementary groups it originally had behind. Is there a way to make this happen? It doesn't look like the setgroups call allows you to do this if you're not root. And when I try it, I get EPERM.

It seems like there ought to be a way to lose privileges you previously possessed.

Upvotes: 3

Views: 1944

Answers (2)

stsp
stsp

Reputation: 410

You normally want to change the group list, rather than to drop it, to match your new identity after the suid/sgid-assisted switch. You need the group list to match your new uid (and actually gid too, as the group list usually includes gid itself).

Unfortunately, as was already mentioned, currently you need CAP_SETGID for calling initgroups(). However in an attempt to solve that, I posted a few proposals to LKML. This one allows to "restrict" a group list, which is somewhat similar to dropping it, but doesn't give you any extra access rights if they were blocked by one of the groups in a list. This one actually allows you to get the correct group list, but you need a privileged helper process to assist you with that task.

I personally prefer the second solution as it gives you a correct group list, but the first one is at least very simple and doesn't require any helper process or extra privs.

Unfortunately both patch-sets only yielded 1 review comment each, which means the lack of an interest to this problem among LKML people. Maybe those who are interested in this problem here, can evaluate my patches and offer some more discussion of them in LKML.

Upvotes: 0

Omnifarious
Omnifarious

Reputation: 56078

The short answer is "A process without CAP_SETGID can't.". And it is by design that setgroups can't be used to remove groups when the process has no privileges. The previous link is to an excellent LWN article detailing why not.

In my particular case, since I'm immediately creating a user namespace, those supplementary groups get mapped to 'nobody' anyway. And so it isn't very important. If it is important, you can use setcap(8) to set capabilities on a wrapper executable that checks that it's being run by the expected user with the expected group permissions and then drops the groups and drops CAP_SETGID and runs the executable you really want to run. The command you would use to do this is:

sudo setcap cap_setgid+ep wrapper_exe

Be careful though, it's now possible that someone who has a shell on your system can use that executable to run some sort of privilege escalation attack if you did not write it very carefully.

Upvotes: 4

Related Questions