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

[perl #24122] setreuid and friends borked on darwin/osx

October 5, 2003 16:00
[perl #24122] setreuid and friends borked on darwin/osx
Message ID:
# New Ticket Created by 
# Please include the string:  [perl #24122]
# in the subject line of all future correspondence about this issue. 
# <URL: >

This is a bug report for perl from,
generated with the help of perlbug 1.34 running under perl v5.8.1.

[Please enter your report here]

The library calls setruid, setrgid, setreuid, and setregid on
darwin (MacOS X) are severely broken, causing any attempt to
change $< or $( to fail silently.

This will cause problems in scripts that use those variables to
drop privileges.  Either they'll die unpleasantly (if they properly
check $< afterwards) or they might gain a security vulnerability.
Scripts that use POSIX::setuid will be unaffected ofcourse.

The only solution I can think of is to make the configure script
pretend those four calls don't exist on darwin.  Properly testing
whether they work would require root perms.

The kernel has no useful alternate calls to changing ruid/rgid.. 
the only calls actually available are set[gu]id and sete[gu]id.

For reference, here's how setreuid is implemented in darwin's libc,
which should make the problem painfully clear:

setreuid(ruid, euid)
        uid_t ruid, euid;
        static uid_t saveduid = -1;

        if (saveduid == -1)
                saveduid = geteuid();
         * we assume that the intent here is to be able to
         * get back ruid priviledge. So we make sure that
         * we will be able to do so, but do not actually
         * set the ruid.
        if (ruid != -1 && ruid != getuid() && ruid != saveduid) {
                errno = EPERM;
                return (-1);
        if (euid != -1 && seteuid(euid) < 0)
                return (-1);
        return (0);

setregid is equivalent.  setr[ug]id are implemented as calls to
setre[gu]id with the e[gu]id argument set to -1.

To further add to the joy, setuid(x) fails if x != ruid && euid != 0,
which means that $< = $> doesn't work, only ($>,$<)=($uid,$uid) does
thanks to delay-magic..  a workaround (tested) for this:

--- mg.c.bak	2003-10-05 22:29:39.000000000 +0200
+++ mg.c	2003-10-05 22:32:49.000000000 +0200
@@ -2253,5 +2253,9 @@
-	if (PL_uid == PL_euid)		/* special case $< = $> */
+	if (PL_uid == PL_euid) {		/* special case $< = $> */
+	    if (PL_uid != 0 && PerlProc_getuid() == 0)
+		(void)PerlProc_setuid(0);
-	else {
+	} else {
 	    PL_uid = PerlProc_getuid();

<@woggle> xmath: Did Apple have some committee setup to break set*id()?

[Please do not change anything below this line]
Site configuration information for perl v5.8.1:

Configured by xmath at Sun Oct  5 19:54:59 CEST 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 1) configuration:
    osname=darwin, osvers=6.6, archname=darwin
    uname='darwin quoose.lan 6.6 darwin kernel version 6.6: thu may 1 21:48:54 pdt 2003; root:xnuxnu-344.34.obj~1release_ppc power macintosh powerpc '
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    cc='gcc-3.3', ccflags ='-g -pipe -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -I/sw/include',
    optimize='-Os -mcpu=750 -mtune=750',
    cppflags='-g -pipe -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -I/sw/include'
    ccversion='', gccversion='3.3 20030304 (Apple Computer, Inc. build 1435)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=8
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc-3.3', ldflags ='-L/sw/lib -flat_namespace'
    libpth=/sw/lib /usr/lib
    libs=-lgdbm -ldb -ldl -lSystem
    perllibs=-ldl -lSystem
    libc=/usr/lib/libSystem.dylib, so=dylib, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dyld.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -flat_namespace -bundle -undefined suppress -L/sw/lib'

Locally applied patches:

@INC for perl v5.8.1:

Environment for perl v5.8.1:
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)
    SHELL=/bin/tcsh Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About