Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Jun 2000 10:45:40 -0700
From:      Kirk McKusick <mckusick@mckusick.com>
To:        Gregory Neil Shapiro <sendmail+gshapiro@Sendmail.ORG>
Cc:        sendmail-questions@Sendmail.ORG, eric@Sendmail.ORG (Eric Allman), arch@freebsd.org
Subject:   Re: Broken FreeBSD setuid(2)? 
Message-ID:  <200006171745.KAA08559@beastie.mckusick.com>
In-Reply-To: Your message of "Thu, 15 Jun 2000 12:05:27 PDT." <14665.10487.273074.915885@horsey.gshapiro.net> 

next in thread | previous in thread | raw e-mail | index | archive | help
My answer is at the bottom. I am copying the FreeBSD arch group
so they can complain if I am misrepresenting how this came to be.

> Date: Thu, 15 Jun 2000 12:05:27 -0700 (PDT)
> From: Gregory Neil Shapiro <sendmail+gshapiro@Sendmail.ORG>
> To: sendmail-questions@Sendmail.ORG
> Cc: eric@sendmail.com, mckusick@mckusick.com
> Subject: Broken FreeBSD setuid(2)?
> In-Reply-To: <26017.961092745@ux.cs.niu.edu>
> References: <14665.5036.94759.10387@horsey.gshapiro.net>
> 	<25862.961091528@ux.cs.niu.edu>
> 	<14665.6387.591517.166768@horsey.gshapiro.net>
> 	<26017.961092745@ux.cs.niu.edu>
> X-Mailer: VM 6.75 under 21.2  (beta34) "Molpe" XEmacs Lucid
> 
> I'm considering sending this off to someone at FreeBSD.  Opinions before I
> do?
> 
> 
> I believe we (sendmail-bugs) have found a _possible_ bug in the setuid(2)
> implementation on FreeBSD 3.4 (and possibly 4.0).  setuid(2) appears to set
> the saved uid even if the process is not running as root and not
> set-user-id root.  For example:
> 
> #include <sys/types.h>
> #include <stdio.h>
> #include <unistd.h>
> 
> int
> main(int argc, char **argv)
> {
> 	uid_t euid = geteuid();
> 	uid_t ruid = getuid();
> 
> 	printf("Before: ruid=%d euid=%d\n", getuid(), geteuid());
> 	if (setuid(ruid) < 0)
> 		perror("setuid");
> 	printf("Middle: ruid=%d euid=%d\n", getuid(), geteuid());
> 	if (setuid(euid) < 0)
> 		perror("setuid");
> 	printf("After: ruid=%d euid=%d\n", getuid(), geteuid());
> }
> 
> And an example run:
> 
> > uname -a
> FreeBSD horsey.gshapiro.net 3.4-STABLE FreeBSD 3.4-STABLE #51: Sun May 21 22:36:42 PDT 2000     root@horsey.gshapiro.net:/usr/src/sys/compile/HORSEY i386
> > ls -lag try
> -rwsr-xr-x  1 generic  gshapiro  3731 Jun 15 10:27 try
> > id
> uid=103(gshapiro)
> > id generic
> uid=101(generic)
> > ./try
> Before: ruid=103 euid=101
> Middle: ruid=103 euid=103
> setuid: Operation not permitted
> After: ruid=103 euid=103
> 
> 
> POSIX Part I, section 4.2.2.2 states:
> 
>       If {_POSIX_SAVED_IDS} is defined:
> ...
>       (2) If the process does not have appropriate privileges, but uid is
>           equal to the real user ID or the saved set-user-ID, the setuid()
>           function sets the effective user ID to uid; the real user ID and
>           saved set-user-ID remain unchanged by this function call.
> 
> This is the case demonstrated above.  It does not have appropriate privileges
> since it is not running as root.  The uid is equal to the real UID.
> However, the setuid() function is setting the saved set-user-ID and not
> leaving it unchanged.  If it were unchanged, then the second setuid()
> should not fail, again because of this statement and the fact that the uid
> is equal to the saved set-user-ID.
> 
> Looking at other implementations, we have found that the second setuid only
> fails on FreeBSD.  It succeeds and the program works as expected on
> Solaris, Linux, and OpenBSD.
> 
> I checked /usr/src/sys/kern/kern_prot.c and see comments about appendix B
> but I do not believe they apply to this case.  The setuid() man page
> states:
> 
> STANDARDS
>      The setuid() and setgid() functions are compliant with the IEEE
>      Std1003.1-1990 (``POSIX'') specification with _POSIX_SAVED_IDS not de-
>      fined with the permitted extensions from Appendix B.4.2.2.  The seteuid()
>      and setegid() functions are extensions based on the POSIX concept of
>      _POSIX_SAVED_IDS, and have been proposed for a future revision of the
>      standard.
> 
> It's arguable whether or not you can follow the rules of !_POSIX_SAVED_IDS
> while still using saved IDs as it creates a subtle difference between
> FreeBSD and other operating systems that more than likely goes unnoticed by
> application writers and has the potential of breaking some of these
> programs.

I agree that FreeBSD does not implement saved id's according
to the Posix spec. And indeed they do not claim to do so as
{_POSIX_SAVED_IDS} is defined as false (see `sysctl kern.saved_ids').
As released, 4.4BSD defined {_POSIX_SAVED_IDS} as true and had the
behavior of NetBSD and OpenBSD. Posix argues that a non-priviledged
user should not have the ability to set the saved-id. They further
argue that they should never need the ability to set the saved-id
since they are only running their own trusted code. They can lose
the special priviledge in any sub-processes that they exec simply
by setting the real user-id to the effective user-id before doing
the exec (since the effective user-id is copied to the saved user-id
on exec). What Posix fails to account for is a program that gets
corrupted by a stack overflow and wants to guard against it by
losing their saved-id before starting to accept outside input.
Posix would say that a program with a stack overflow is not compliant
with the standard, and hence is outside the scope of the document.
The FreeBSD folks decided to change the semantics of setuid to
overwrite the saved user-id so that programs could protect themselves
from stack overflows, debugger attaches, etc. They argue that
seteuid is available if you just want to set the effective user-id
and it is stupid to have a second system call (setuid) which does
exactly the same thing when you are not root. Since Posix never
bought into adding seteuid, they had to overload setuid to get the
equivalent functionality. This is a good example of why Posix options
were a bad idea. By letting each system ship with different option
settings, you end up with very subtilely different semantics.
Each vendor is well meaning, but makes for a programming nightmare
among application developers that have to deal with all the
combinations.

	Kirk McKusick


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200006171745.KAA08559>