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

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

From:
perlbug-followup
Date:
October 5, 2003 16:00
Subject:
[perl #24122] setreuid and friends borked on darwin/osx
Message ID:
rt-24122-65678.14.2411168523081@rt.perl.org
# New Ticket Created by  pxm@nubz.org 
# Please include the string:  [perl #24122]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=24122 >


This is a bug report for perl from pxm@nubz.org,
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:

int
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 @@
 #else
-	if (PL_uid == PL_euid)		/* special case $< = $> */
+	if (PL_uid == PL_euid) {		/* special case $< = $> */
+#ifdef PERL_DARWIN
+	    if (PL_uid != 0 && PerlProc_getuid() == 0)
+		(void)PerlProc_setuid(0);
+#endif
 	    (void)PerlProc_setuid(PL_uid);
-	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]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=medium
---
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:
  Platform:
    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 '
    config_args=''
    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
  Compiler:
    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
    gnulibc_version=''
  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:
    /sw/lib/perl5/5.8.1/darwin
    /sw/lib/perl5/5.8.1
    /sw/lib/perl5/darwin
    /sw/lib/perl5/5.8.0/darwin
    /sw/lib/perl5/5.8.0
    /sw/lib/perl5
    /sw/lib/perl5/5.8.1/darwin
    /sw/lib/perl5/5.8.1
    /sw/lib/perl5/site_perl/5.8.1/darwin
    /sw/lib/perl5/site_perl/5.8.1
    /sw/lib/perl5/site_perl/5.8.0/darwin
    /sw/lib/perl5/site_perl/5.8.0
    /sw/lib/perl5/site_perl
    /Library/Perl/darwin
    /Library/Perl
    /System/Library/Perl/darwin
    /System/Library/Perl
    .

---
Environment for perl v5.8.1:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/xmath
    LANG=en_US
    LANGUAGE (unset)
    LC_ALL=C
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/sw/bin:/sw/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/Developer/Tools
    PERL5LIB=/sw/lib/perl5
    PERL_BADLANG (unset)
    SHELL=/bin/tcsh




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