develooper Front page | perl.perl5.porters | Postings from April 2003

Re: setuid() and MacOS X (Was: Re: nobody has uid -2 on OS X, this confuses getpwnam())

Thread Next
From:
Dan Kogai
Date:
April 9, 2003 23:25
Subject:
Re: setuid() and MacOS X (Was: Re: nobody has uid -2 on OS X, this confuses getpwnam())
Message ID:
29A95286-6B1D-11D7-B355-000393AE4244@dan.co.jp
On Thursday, April 10, 2003, at 02:38  PM, Dan Kogai wrote:
> It seems on MacOS X only EUID can be modified.  But also notice on 
> FreeBSD assignments to both $< and $> is working as expected.

I have checked to see if setuid() of C in MacOS X has a problem.  Here 
is a simple C program.

#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>

int main(int argc, char *argv[]){
     int err;
     struct passwd *pw;
     if (argc < 2){
         fprintf(stderr, "%s username\n", argv[0]);
         exit(0);
     }
     if ((pw = getpwnam(argv[1])) == NULL){
         fprintf(stderr, "%s: no such user.\n", argv[1]);
         exit(0);
     }
     printf("UID is %u, EUID is %u\n", getuid(), geteuid());
     printf("New E?UID will be %u\n", pw->pw_uid);
     err = setuid(pw->pw_uid);
     if (err == -1){ fprintf(stderr, "%s\n", strerror(errno)); }
     printf("UID is %u, EUID is %u\n", getuid(), geteuid()); 
system("id");
     err = seteuid(pw->pw_uid);
     if (err == -1){ fprintf(stderr, "%s\n", strerror(errno)); }
     printf("UID is %u, EUID is %u\n", getuid(), geteuid()); 
system("id");
}
/* END */

And here is the result.

MacOS X
> UID is 0, EUID is 0
> New E?UID will be 4294967294
> uid=4294967294(nobody) gid=0(wheel) groups=0(wheel), 1(daemon), 
> 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest), 70(www), 
> 80(admin)
> UID is 4294967294, EUID is 4294967294
> UID is 4294967294, EUID is 4294967294
> uid=4294967294(nobody) gid=0(wheel) groups=0(wheel), 1(daemon), 
> 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest), 70(www), 
> 80(admin)

FreeBSD
> UID is 0, EUID is 0
> New E?UID will be 65534
> UID is 65534, EUID is 65534
> uid=65534(nobody) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 
> 4(tty), 5(operator), 20(staff), 31(guest)
> UID is 65534, EUID is 65534
> uid=65534(nobody) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 
> 4(tty), 5(operator), 20(staff), 31(guest)

As you see, setuid() not only changes UID but also EUID altogether.  
And here is the result when seteuid() is committed BEFORE setuid().

MacOS X
> t% sudo ./a.out nobody
> UID is 0, EUID is 0
> New E?UID will be 4294967294
> UID is 0, EUID is 4294967294
> uid=0(root) euid=4294967294(nobody) gid=0(wheel) groups=0(wheel), 
> 1(daemon), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest), 
> 70(www), 80(admin)
> Operation not permitted
> UID is 0, EUID is 4294967294
> uid=0(root) euid=4294967294(nobody) gid=0(wheel) groups=0(wheel), 
> 1(daemon), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest), 
> 70(www), 80(admin)

FreeBSD
> sudo ./a.out nobody
> UID is 0, EUID is 0
> New E?UID will be 65534
> UID is 0, EUID is 65534
> uid=0(root) euid=65534(nobody) gid=0(wheel) groups=0(wheel), 2(kmem), 
> 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
> UID is 65534, EUID is 65534
> uid=65534(nobody) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 
> 4(tty), 5(operator), 20(staff), 31(guest)

Now see this?  Once seteuid() is committed, MacOS X does not allow you 
to setuid() while FreeBSD does.  I think this is the very reason why 
MacOS X behaves that way.

Which is the correct behaviour?  Both FreeBSD and MacOS X share the 
same manual.  Let's see

man 3 setuid says...
>      The setuid() function sets the real and effective user IDs and 
> the saved
>      set-user-ID of the current process to the specified value.  The 
> setuid()
>      function is permitted if the specified ID is equal to the real 
> user ID or
>      the effective user ID of the process, or if the effective user ID 
> is that
>                                                  
> ^^^^^^^^^^^^^^^^^^^^^^^^
>      of the super user.

So far as I see MacOS X is the one behaving correctly.  Since EUID is 
no longer 0 once seteuid(), you are not supposed to be able to setuid().

Dan the Man with Too Many Platforms to Babysit


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About