On GNU/Linux systems that are build using RPM packages, the rpmlint utility complains about programs that don't call setgroups before setuid.

The idea is that before dropping privileges, a process should also drop the list of supplementary group ID's with setgroups(0, NULL).

However, is this something that should always be done?

Suppose that we are running setuid root, and are carrying a list of supplementary group ID's from our original security context: the groups associated with the real user ID.

When we drop back to that real user ID, we don't necessarily want to lose those groups: code executing as the original user may depend on those supplementary memberships being in place, right?

Should we not omit setgroups(0, NULL) in setuid code before dropping privs to the original user?

(By the way, of course we don't drop privileges with setuid on Linux because that doesn't work for code running setuid non-root.)


This almost entirely depends on whether you're temporarily or permanently dropping privileges.

In the case of temporarily dropping privileges, it's actually ill-advised to call setgroups with a single group as you'll be wiping the list of ancillary groups, potentially making it impossible (without external intervention) to restore the process back to its original privilege level.

In the case of permanently dropping privileges, it is important to clear the ancillary groups list in order to make it more difficult for an exploit to re-instate privileges after they are dropped. The problem arises when you attempt to do this the wrong way around: if you setuid to a non-zero value first (meaning you're no longer root), then call setgroups, the effective uid of the process is now no longer root, meaning that the internal setgid call fails. Doing it the other way around doesn't have this problem because calling setgid first doesn't alter the effective uid of the process, allowing setuid to be called.

More info can be found here:

  • I'm interested specifically in the case of permanently dropping privileges, back to the original real ID user who invoked a setuid program. – Kaz May 2 '16 at 21:24
  • @Kaz In which case, the second half of my answer should cover what you want. Failing to drop the ancillary groups may imbue additional capabilities which would otherwise be lost when doing setgroups with a single non-zero gid (before setuid of course). – Polynomial May 2 '16 at 21:27
  • Are you trying to say that the diagnostic in rpmlint is purely about order? That is to say, it is saying that you have both setgroups and setuid in the program, but apparently in the wrong order? – Kaz May 2 '16 at 21:28
  • Is that because more groups may have been added? E.g. user 1 has groups 10, 11, 12. Runs setuid program, which makes it 10, 11, 12, 51. Dropping back to user 1 should restore the supplementary groups to 10, 11, 12. No? Not just clobber the list to empty. What if I control all the code that runs setuid root and know that the group ID's have not been manipulated? – Kaz May 2 '16 at 21:32
  • The "Dropping Privileges in setuid Programs" in fact is saying that the supplementary group list may be manipulated under setuid root (this is the issue), and that when returning to the original privileges, the original list may be restored. That's basically the answer: don't clobber, but restore (if there is any reason to suspect it was changed). – Kaz May 2 '16 at 21:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.