bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: dropping setuid/setgid privileges


From: James Youngman
Subject: Re: dropping setuid/setgid privileges
Date: Sun, 7 Jun 2009 23:11:55 +0100

On Sun, Jun 7, 2009 at 10:35 PM, Bruno Haible<address@hidden> wrote:
>  /* Drop the gid privilege first, because in some cases dropping the gid

I think you need to delete the word "dropping" in the line above.

>     privilege cannot be dropped after the uid privilege has been dropped.  */
> #if HAVE_GETUID
>  int uid = getuid ();
> #endif
> #if HAVE_GETGID
>  int gid = getgid ();
> #endif
>
>  /* This is for executables that have the setgid bit set.  */
> #if HAVE_SETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
>  /* This code is needed: In particular, on HP-UX 11.11, setregid (gid, gid)
>     may leave the saved uid as 0.  See also the comment below regarding
>     setresuid.  */
>  if (setresgid (gid, gid, gid) < 0)
>    return -1;
> #elif HAVE_SETREGID /* MacOS X, NetBSD, AIX, IRIX, Solaris, OSF/1, Cygwin */
>  if (setregid (gid, gid) < 0)
>    return -1;
> #elif HAVE_SETEGID /* Solaris 2.4 */
>  if (setegid (gid) < 0)
>    return -1;
> #endif

It's possible that one of the process's supplementary groups is
privileged.   So we may also need to do something like this:

#if HAVE_SETGROUPS
  /* Use of setgroups() is restricted to root only. */
  if (0 == geteuid())
    {
      /* We're either root or running setuid-root. */
      gid_t groups[1];
      groups[0] = gid;
      if (0 != setgroups(1u, groups))
        {
           return -1;
        }
    }
#endif



>  /* This is for executables that have the setuid bit set.  */
> #if HAVE_SETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
>  /* On systems which have setresuid(), we use it instead of setreuid(),
>     because
>       <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
>     says about setreuid(): "The rule by which the saved uid id is modified
>     is complicated." Similarly, <http://unixpapa.com/incnote/setuid.html>
>     says about setreuid(): "What exactly happens to the saved UID when this
>     is used seems to vary a lot."  */
>  if (setresuid (uid, uid, uid) < 0)
>    return -1;
> #elif HAVE_SETREUID /* MacOS X, NetBSD, AIX, IRIX, Solaris, OSF/1, Cygwin */
>  if (setreuid (uid, uid) < 0)
>    return -1;
> #elif HAVE_SETEUID /* Solaris 2.4 */
>  if (seteuid (uid) < 0)
>    return -1;
> #endif
>
>  /* Verify that the privileges have really been dropped.
>     This verification is here for security reasons.  Doesn't matter if it
>     takes a couple of system calls.
>     <http://www.usenix.org/events/sec02/full_papers/chen/chen.pdf>
>     section 8.1.3 also recommends to use a setreuid call as a probe, but
>     this call would unexpectedly succeed (and the verification thus fail)
>     on Linux if the process has the CAP_SETUID capability.  */

I'm not convinced this approach is correct.   If we hold CAP_SETUID, I
think we should drop that too.  Otherwise, our privilege drop is
reversible.

We also need to cope with the case where the attacker invokes the
setuid proram with the ability to call setuid() turned off, which on
some systems could cause the attempt to drop privileges to fail.   For
this reason locate currently does this:

              /* Check that we can no longer switch back to root */
              if (0 == setuid (0))
                {
                  what = _("Failed to fully drop privileges");
                  /* The errno value here is not interesting (since
                   * the system call we are complaining about
                   * succeeded when we wanted it to fail).  Arrange
                   * for the call to error() not to print the errno
                   * value by setting errno=0.
                   */
                  errno = 0;
                  goto fail;
                }

I think it's also worth briefly stating into the introductory comment
that the caller should also worry about things that dropping
privileges doesn't directly solve, such as holding in-memory copies of
sensitive data or open FDs.

James.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]