SA Bugzilla – Bug 3586
[review] perl setuid fails, breaking spamd in FreeBSD, MacOS X
Last modified: 2004-07-22 12:08:43 UTC
Getting these types of errors after processing messages: Jul 10 14:44:03 fat_man spamd[1822]: DCC -> check failed: setuid 0 to 1000 failed! at /usr/local/lib/perl5/site_perl/5.6.1/Mail/SpamAssassin/Util.pm line 932. Jul 10 14:44:28 fat_man spamc[1821]: failed sanity check, 6050 bytes claimed, 17021 bytes seen
Subject: Re: New: failed sanity check On Sat, Jul 10, 2004 at 12:49:07PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > Jul 10 14:44:03 fat_man spamd[1822]: DCC -> check failed: setuid 0 to 1000 > failed! at /usr/local/lib/perl5/site_perl/5.6.1/Mail/SpamAssassin/Util.pm line 932. > Jul 10 14:44:28 fat_man spamc[1821]: failed sanity check, 6050 bytes claimed, > 17021 bytes seen Hrm. Well, the sanity check error is caused by spamd being killed from the first message. The first message is from spamd not able to change its real uid to match the effective uid, which I have no idea what to tell you. The code is really simple there: sub setuid_to_euid { return if (RUNNING_ON_WINDOWS); if ($< != $>) { dbg ("setting real uid from $< to match effective uid $>"); $< = $>; if ($< != $>) { die "setuid $< to $> failed!"; } } } $< is real uid, $> is effective uid. So for security reasons, we try dropping root priv, then spamd blows up because the real uid (0) doesn't equal the effective uid (1000). So ... The real issue is: why can't your spamd process drop root privs? I have no answer to that, as far as I know, root can always change ruid to another user, but then you can't go back, which is expected. Unless there's something I'm missing though, this seems like a perl/OS issue, not an SA one.
Maybe some weird security restriction from FreeBSD? Something like Linux Capabilities on That Other OS? I don't think anybody is running FreeBSD here, you should ask on your local BSD list. I keep this bug open as I'm not sure if we should really die there or do so just in paranoid mode.
My setup works fine with 2.63. Seems like, as you said, a strange permissions issue. Is there anything else I can try?
Some ideas: - Maybe that code was never called in 2.6x? Don't think so, but who knows. - Maybe spamd already dropped privs before but Perl didn't update the uid accordingly? That could be caused by the new pre-forked children code and smells like a Perl bug.
Is there anything I can do to help troubleshoot?
Subject: Re: failed sanity check On Sat, Jul 10, 2004 at 05:57:22PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > - Maybe that code was never called in 2.6x? Don't think so, but who knows. As I recall, the code is new in 3.0 to fix up any potential security issues pre-helper launch.
I've rebuilt all the modules used for my SA installation, cleaned out all preferences, and ran with a plain local.cf file. Nothing seems to fix this problem. Should I disable support for all "helpers"? Is there something in my setup that is causing this problem or is this a bug between perl and SA?
Subject: Re: failed sanity check On Sun, Jul 11, 2004 at 06:36:44PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > Should I disable support for all "helpers"? That will bypass the issue for now, yes. > Is there something in my setup that is causing this problem or is this a bug > between perl and SA? It's between perl and your OS.
I'm going to post a message to one of the perl and/or FreeBSD mailing lists. How should I phrase the question? "Why won't perl drop root privilages?"
Subject: Re: failed sanity check On Sun, Jul 11, 2004 at 07:46:31PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > I'm going to post a message to one of the perl and/or FreeBSD mailing lists. > How should I phrase the question? "Why won't perl drop root privilages?" Interestingly, the same exact issue occurs on my Mac OS X machine, but not any of the other platforms I have access to... root# perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $>=1000; p; $<=$>; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 0, EUID: 1000 The end line should read "RUID: 1000, EUID: 1000". Linux: # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $>=1000; p; $<=$>; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 1000, EUID: 1000 Solaris: # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $>=1000; p; $<=$>; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 1000, EUID: 1000 More interesting bits: # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $<=1000; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 0 # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX; setuid(1000); p;' RUID: 0, EUID: 0 RUID: 0, EUID: 0 # cat - > t.c main() { printf("RUID: %d, EUID: %d\n", getuid(), geteuid()); setuid(1000); printf("RUID: %d, EUID: %d\n", getuid(), geteuid()); } # gcc t.c # ./a.out RUID: 0, EUID: 0 RUID: 1000, EUID: 1000 so setuid() obviously works. just not at all from perl.
Mac OS X / FreeBSD...birds of a feather... So its clearly a FreeBSD / Perl issue.
Googling for hints about this I found http://freebsd.qmailrocks.org/qmailscanner.htm which are instructions for installing qmail-scanner, presumably on FreeBSD. The relevance of this oage is that it has two sets for of instructions for the cases, quoting: "How you go about configuring and installing qmail-scanner from this point on depends on how you server's installation of Perl is configured. For the purposes of this installation, there are 2 Perl setups. 1. Perl is configured to allow for setuid functions. 2. Perl is not configured for setuid functionality and, in fact, does not permit it." It appears that we should find out about these two configurations of perl.
ok, so this increasingly is looking like we'll have to deal with it. so moving to 3.0 queue. BTW: from Sidney's post, I dug around a little myself. the Config module has a d_dosuid option listed. In and of itself, it doesn't seem to tell me whether or not I can suid, but: perl -e 'use Config; foreach("dosuid","seteuid","setresuid","setreuid","suidsafe"){print "$_ = ",(defined $Config{"d_$_"} ? $Config{"d_$_"} : "undef"),"\n"}' Linux: dosuid = define seteuid = define setresuid = define setreuid = define suidsafe = undef Solaris: dosuid = undef seteuid = define setresuid = undef setreuid = define suidsafe = define Mac OS X: dosuid = undef seteuid = define setresuid = undef setreuid = define suidsafe = undef fwiw.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 09:24:32AM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > perl -e 'use Config; foreach("dosuid","seteuid","setresuid","setreuid","suidsafe"){print "$_ = ",(defined > $Config{"d_$_"} ? $Config{"d_$_"} : "undef"),"\n"}' So far it looks like we can suid if: dosuid|suidsafe More data is welcome. > Linux: > dosuid = define > suidsafe = undef > > Solaris: > dosuid = undef > suidsafe = define > > Mac OS X: > dosuid = undef > suidsafe = undef
I asked on #perl about this and unfortunately the only response I got was <Roderick>Moonflux: The program should be changed to set the real uid first, then the effective uid. I don't know what he means with that though :) But while I looked at the man page, I found a reference to POSIX::setuid(). Maybe that offers a way to check if the routine works?
Some more googling and reading leads me to think that the link I found is only talking about setting a perl script file (beginning with #!/usr/bin/perl) setuid, not about setting the uid from within a perl program. I haven't found any discussion of the latter.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 10:26:05AM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > <Roderick>Moonflux: The program should be changed to set the real uid > first, then the effective uid. > > I don't know what he means with that though :) But while I looked at the man > page, I found a reference to POSIX::setuid(). Maybe that offers a way to check > if the routine works? Well, he means: $<=1000; $>=$<; but that doesn't work either, already tested that. ;): # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $<=1000; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 0 BTW: I had a friend test out his fbsd box: default in fbsd 4.9 is perl 5.005: dosuid = define seteuid = define setresuid = define setreuid = define suidsafe = undef RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 0, EUID: 1000 he also has the perl-5.6.1_15 ports version installed: dosuid = define seteuid = undef setresuid = define setreuid = define suidsafe = undef RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 1000, EUID: 1000 # uname -a FreeBSD some.host.name 4.9-RELEASE-p10 FreeBSD 4.9-RELEASE-p10 #0: Fri Jun 18 18:52:47 EDT 2004 root@some.host.name:/usr/obj/usr/src/sys/GENERIC i386
Subject: Re: failed sanity check -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 >he also has the perl-5.6.1_15 ports version installed: > >dosuid = define >seteuid = undef >setresuid = define >setreuid = define >suidsafe = undef > >RUID: 0, EUID: 0 >RUID: 0, EUID: 1000 >RUID: 1000, EUID: 1000 Good -- that's what I would have expected to happen, what should be happening, and what's happening elsewhere. It now strongly suggests a perl bug on *BSD: - Linux, perl version 5.8.x: ok - Solaris, perl version ???: ok - MacOS X, perl version ???: fails - FreeBSD, perl version 5.005: fails - FreeBSD, perl version 5.6.1: ok I wonder if freebsd fails to support setting the real uid to non-root if "seteuid" is defined in Config? setreuid() would fix this. could freebsd-ers try: perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setreuid); POSIX::setreuid(1000,1000); p;' or setresuid(): perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setresuid); POSIX::setresuid(1000,1000,1000); p;' however, if those aren't exported, we can't use them :( PS: the "suidsafe" stuff is for running setuid scripts, not for this situation, so it can be discounted. - --j. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (GNU/Linux) Comment: Exmh CVS iD8DBQFA8wYxQTcbUG5Y7woRAj9pAJ4/z4kABmCDFr4vZSjdMPDwCipsMQCfSt7o lCC0wrb+zWuXkqlQpHn16Rw= =8I4s -----END PGP SIGNATURE-----
> - FreeBSD, perl version 5.6.1: ok Hrm...I'm using 5.6.1 and it isn't working for me. [17:08:51 root@fat_man: /home/mike/mailsort]# perl5.6.1 -V Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=freebsd, osvers=4.4-stable, archname=i386-freebsd uname='freebsd fat_man.ascendency.net 4.4-stable freebsd 4.4-stable #1: tue mar 26 16:40:22 cst 2002 root@fat_man.ascendency.net:usrobjusrsrcsysfat_man_scsi _kernel i386 ' config_args='' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=unde f useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -I/usr/local/include', optimize='-O', cppflags='-fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='2.95.3 20010315 (release) [FreeBSD]', gccosandvers ='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize =8 alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags ='-Wl,-E -L/usr/local/lib' libpth=/usr/lib /usr/local/lib libs=-lm -lc -lcrypt -lutil perllibs=-lm -lc -lcrypt -lutil libc=, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-DPIC -fpic', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: USE_LARGE_FILES Built under freebsd Compiled at Apr 11 2002 04:43:42 @INC: /usr/local/lib/perl5/5.6.1/i386-freebsd /usr/local/lib/perl5/5.6.1 /usr/local/lib/perl5/site_perl/5.6.1/i386-freebsd /usr/local/lib/perl5/site_perl/5.6.1 /usr/local/lib/perl5/site_perl/5.005/i386-freebsd /usr/local/lib/perl5/site_perl/5.005 /usr/local/lib/perl5/site_perl [17:09:00 root@fat_man: /home/mike/mailsort]# uname -a FreeBSD fat_man.ascendency.net 4.4-STABLE FreeBSD 4.4-STABLE #1: Tue Mar 26 16:40:22 CST 2002 root@fat_man.ascendency.net:/usr/obj/usr/src/sys/FAT_MAN_SCSI_KERNEL i386 [17:04:52 root@fat_man: /home/mike/mailsort]# perl5.6.1 -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setreuid); POSIX::setreuid(1000,1000); p;' "setreuid" is not exported by the POSIX module at /usr/local/lib/perl5/5.6.1/i386-freebsd/POSIX.pm line 19 Can't continue after import errors at /usr/local/lib/perl5/5.6.1/i386-freebsd/POSIX.pm line 19 BEGIN failed--compilation aborted at -e line 1. [17:05:18 root@fat_man: /home/mike/mailsort]# perl5.6.1 -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setresuid);POSIX::setresuid(1000,1000,1000); p;' "setresuid" is not exported by the POSIX module at /usr/local/lib/perl5/5.6.1/i386-freebsd/POSIX.pm line 19 Can't continue after import errors at /usr/local/lib/perl5/5.6.1/i386-freebsd/POSIX.pm line 19 BEGIN failed--compilation aborted at -e line 1.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 02:44:34PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > - Solaris, perl version ???: ok I tried both both 5.005 and 5.8.3 > - MacOS X, perl version ???: fails 5.8.1 RC3 > perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setreuid); > POSIX::setreuid(1000,1000); p;' > > or setresuid(): > > perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setresuid); > POSIX::setresuid(1000,1000,1000); p;' > > however, if those aren't exported, we can't use them :( That's the case on my Mac OS X box unfortunately: # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setreuid); POSIX::setreuid(1000,1000); p;' "setreuid" is not exported by the POSIX module Can't continue after import errors at /System/Library/Perl/5.8.1/darwin-thread-multi-2level/POSIX.pm line 19 BEGIN failed--compilation aborted at -e line 1. # perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; use POSIX qw(setresuid); POSIX::setresuid(1000,1000,1000); p;' "setresuid" is not exported by the POSIX module Can't continue after import errors at /System/Library/Perl/5.8.1/darwin-thread-multi-2level/POSIX.pm line 19 BEGIN failed--compilation aborted at -e line 1. I'm thinking a kluge for this is to simply try it, and instead of doing a die, throw a debug warning that this is a potential security issue, and document it somewhere.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 03:07:56PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > > - FreeBSD, perl version 5.6.1: ok > > Hrm...I'm using 5.6.1 and it isn't working for me. are you using the standard of "ports" version of perl? it seems somehow related to how perl is built on these bsd-based platforms. they clearly can do setuid() from a C program, but not from perl, so either there's some security thing enabled such that perl is blocked or it was compiled in such a way so that it doesn't try. I'm attempting to get truss/strace (whatever the fbsd equivilent is) on "perl -e '$<=1234;'". I don't seem to have that ability on the Mac box. :(
> are you using the standard of "ports" version of perl? No. I can paste my Makefile if you want.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 06:13:37PM -0400, Theo Van Dinter wrote: > I'm attempting to get truss/strace (whatever the fbsd equivilent is) on > "perl -e '$<=1234;'". I don't seem to have that ability on the Mac box. :( ok, the truss output from the default fbsd 4.9 perl shows that there was no attempt for setuid() or anything similar. so it's not like it's trying and the OS throws an error.
Subject: Re: failed sanity check On Mon, Jul 12, 2004 at 03:20:47PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > > are you using the standard of "ports" version of perl? Sorry, I meant "standard" _or_ "ports". I'm assuming "standard" (although I was under the impression the standard version was 5.005 on pretty much all the fbsd versions).
I'm not using the ports version.
Actually, I have both installed... /usr/bin/perl (5.005_03 ) /usr/local/bin/perl5.6.1 perl is from the system and perl5.6.1 was installed manually. I kept both for compatability reasons.
Changed summary to better reflect problem and show up better in searches
Is this an answer? (I'm not near my MacOS X box to try it myself) Quote from http://archives.listbox.com/spf-discuss@v2.listbox.com/200312/0446.html (see link for attributions): > However I was assuming the script was to be run as root via > /etc/init.d/something for example, and doesn't require > suidperl. I can't think of why a perl intepreter can't use > the setuid or setgid system call (achived by using > '$( = 111' or '$< = 111' to set(gu)id to (gu)id 11). It was solved, the particular syntax of the setuid was not liked by freebsd I guess. That's not to say I wasn't a bit confused ;) So $< = $> = $user; became $< = $user; $> = $user; and so on.
I tried that on MacOS X and it did not work. Here is the entire thread which contains two full code examples that supposedly work in FreeBSD. I'll look at it later if nobody else solves this first. http://archives.listbox.com/spf-discuss@v2.listbox.com/200312/index.html#0296
yeah, separating the commands doesn't matter. it's a red herring anyway, we already change stuff separately. the boiled down issue here is: $<=1000; die if ($< != 1000); This fails on the default FreeBSD and Mac OS X perl installs (I'd guess probably also NetBSD and OpenBSD). We're trying to drop privilege, but setuid() away from uid 0 fails. On FreeBSD 4.9, anyway, doing some truss checking shows the perl binary not even trying the setuid() call, so the problem seems to be completely perl binary related. My guess is that either the default BSD-supplied build config, or the perl configure script, for some reason disables all setuid functionality (though they leave seteuid() functionality)). I see two issue paths we need to work on here: 1) Instead of spamd doing die, it really ought to just throw a loud warning, and return "fail". This is, after all, just a rule. 2) Figure out a way to get around this issue. It seems to be a perl binary issue, and setuid (via $<, POSIX, etc,) doesn't work at all. So IMO: - add in documentation about the issue - suggest people compile/get a different perl that does allow setuid - somehow autodetect the situation and disable "helper" rules automatically. users will probably be confused that DCC/etc doesn't work, we'll have to say RTFM a lot... I'm not really sure how to autodetect this though. It's not an OS issue, since you can get different perl binaries that work fine on FreeBSD, for instance. So we can't just disable if $^O is set appropriately. It doesn't seem to be obviously available via %Config, based on the results thus far. FWIW: This issue just affects DCC, and Pyzor: setuid_to_euid() is only called by helper_app_pipe_open_unix(), which is only called by helper_app_pipe_open(), which is only called via Dns.pm and Reporter.pm for DCC and Pyzor. Just so we're clear this doesn't impact the majority of SA functionality. :)
BTW see also this thread on perl5-porters: http://archive.develooper.com/perl5-porters@perl.org/msg95384.html http://archive.develooper.com/perl5-porters@perl.org/msg95385.html http://archive.develooper.com/perl5-porters@perl.org/msg95387.html aha! the MacOS X behaviour is a confirmed perl bug -- perl#24122: http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2003-10/msg00495.html Anyway. Theo -- perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $< = 1000; $> = 1000; p;' doesn't work on FreeBSD? that's whta that spfd thread suggests... if that at least works on FreeBSD, we can throw in a kludge for that, fixing half of the problem OSes ;) It may work where "$>=1000; $<=1000;" doesn't, because of the ordering. '1) Instead of spamd doing die, it really ought to just throw a loud warning, and return "fail". This is, after all, just a rule.' -1. In this situation, we do not want the helper apps to run as root. We should ensure that they do not get to run. IMO, "die" and it's exception-like semantics are the best way to do that, rather than risking that a "return 0" may be lost/ignored along the call stack. Note that the die's are already caught and do not effect other rules anyway. However, if the 'throw a loud warning, and return "fail"' idea is implemented in terms of catching that specific "die" using an eval { } block in the helper-app running code, and turning it into a prettier error message, then +1, that'd be fine ;) However I agree it'll need doco -- probably a top FAQ item. re: autodetecting -- agreed this doesn't really seem to be possible. You can't even detect at install time unless we get the user to run "make test" as root, and I'm -1 on that idea. ;) PS: for setuid reference docs: http://www.cs.berkeley.edu/~hchen/paper/usenix02.html also some stuff about saved userIDs (argh!): http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2004-05/msg00699.html
Subject: Re: perl setuid fails, breaking spamd in FreeBSD, MacOS X On Tue, Jul 13, 2004 at 11:44:53AM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > '1) Instead of spamd doing die, it really ought to just throw a loud warning, > and return "fail". This is, after all, just a rule.' > > -1. In this situation, we do not want the helper apps to run as root. We > should ensure that they do not get to run. IMO, "die" and it's exception-like > semantics are the best way to do that, rather than risking that a "return 0" > may be lost/ignored along the call stack. Note that the die's are already > caught and do not effect other rules anyway. um. right, that's why we would return "fail" and not run the helper app. ;) perhaps this wasn't fully clear in my initial statement. the die() currently happens in a child process, pre running the helper app. there's a filehandle between the child and parent for communication/output from helper app. so instead of calling die(), just close the filehandle and exit (we need to exit anyway since we're a child). do _not_ run the helper app. the calling spamd process will simply get an EOF when trying to read the output, and throw a "read failed" or whatever, and the rule doesn't trigger. btw: if I read the ticket correctly, the die() is apparently _NOT_ caught. that's what causes the sanity check issue via spamc. > re: autodetecting -- agreed this doesn't really seem to be possible. You > can't even detect at install time unless we get the user to run "make test" > as root, and I'm -1 on that idea. ;) ditto.
Subject: Re: perl setuid fails, breaking spamd in FreeBSD, MacOS X On Tue, Jul 13, 2004 at 11:44:53AM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $< = 1000; $> = 1000; p;' > > doesn't work on FreeBSD? that's whta that spfd thread suggests... if that at > least works on FreeBSD, we can throw in a kludge for that, fixing half of the > problem OSes ;) It may work where "$>=1000; $<=1000;" doesn't, because of the > ordering. Well, "perl -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $<=1000; p;'" fails on OS X (already in the ticket), but seems to work on FreeBSD: RUID: 0, EUID: 0 RUID: 1000, EUID: 0 The issue here, of course, is that we seteuid() in spamd, then later on the helper app stuff tries the setuid(). Wait a minute, is this something stupid where perl checks EUID == 0 for setuid instead of using RUID? A-ha! It is! $ perl5.00503 -e 'sub p {print "RUID: $<, EUID: $>\n";} p; $>=1000; p; $<=1000; p; $>=0; $<=1000; $>=1000; p;' RUID: 0, EUID: 0 RUID: 0, EUID: 1000 RUID: 0, EUID: 1000 RUID: 1000, EUID: 1000 ARG! Ok, so the simple solution, it seems, is: $>=$<; $<=$newuid; $>=$newuid; if ($<!=$>) { ... }
I emailed Mark Foster, one of the spfd developers from that thread to ask about what they did. He confirmed that the fix they put in was changing $< = $> = $user to $< = $user; $> = $user; "See http://archives.listbox.com/spf-discuss@v2.listbox.com/200312/0408.html I believe Hans Dieter Pearcey was the one who solved this. The fix was committed in v1.96." Theo said it is a red herring since we do it separately anyway, but I see in spamd.raw in the latest trunk that there is one place that is not done, line 858 has $> = $<; Could that be the remaining place to fix to work in FreeBSD, and we are stuck in the case of MacOS X? Can someone with FreeBSD check this out?
Created attachment 2139 [details] suggested patch Ok, this patch does the kluge where we change euid back to ruid, then change ruid, then change euid (again). As posted in the ticket, this works in the one-liner test, but I have not tried it via SpamAssassin at all. I'd appreciate it if the folks able to reproduce the problem with SA try this patch out. Thanks. :)
The patch won't help in MacOS X. We should document somewhere what functionality will not work in MacOS X with a reference to perl bug -- perl#24122 and the discussion at http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2003-10/msg00495.html Should we create a spamd/README.MacOSX file? Looking at patch... What about the following code in spamd.raw line 670 # Change GID $) = "$ugid $ugid"; # effective gid $( = $ugid; # real gid # Change UID $> = $uuid; # effective uid $< = $uuid; # real uid. we now cannot setuid anymore and line 1018,1364, 1507, and 1551: Do we know that $< == 0 and $> == 0 at that point, or do we need some checking? Those three places all say: $) = "$gid $gid"; # eGID $> = $uid; # eUID Also, do we need to do anything similar for $) and $( ?
Subject: Re: [review] perl setuid fails, breaking spamd in FreeBSD, MacOS X On Fri, Jul 16, 2004 at 03:13:02PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > The patch won't help in MacOS X. We should document somewhere what functionality Ah, good point. I forgot about that whole "no setuid" thing. <sigh> > will not work in MacOS X with a reference to perl bug -- perl#24122 and the > discussion at > http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2003-10/msg00495.html Indeed. > Should we create a spamd/README.MacOSX file? I'm thinking a Mac OS X section of the spamd/READMe file. ;) > Looking at patch... What about the following code in spamd.raw line 670 > > # Change GID > $) = "$ugid $ugid"; # effective gid > $( = $ugid; # real gid Hrm. $) works fine, $( doesn't. :( stupid mac os x! > # Change UID > $> = $uuid; # effective uid > $< = $uuid; # real uid. we now cannot setuid anymore yeah, we should reverse these. > and line 1018,1364, 1507, and 1551: Do we know that $< == 0 and $> == 0 at that > point, or do we need some checking? Those three places all say: > > $) = "$gid $gid"; # eGID > $> = $uid; # eUID I believe e[ug]id works fine everywhere. > Also, do we need to do anything similar for $) and $( ? good question. anyone have a bsd box we can try this on?
Yes. What do you want me to do...
Subject: Re: [review] perl setuid fails, breaking spamd in FreeBSD, MacOS X On Fri, Jul 16, 2004 at 08:33:35PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > Yes. What do you want me to do... Ok, so first, we should do the gid first, then the uid. I believe we do it this way now. Second, the question at the moment is: Do the platforms that have the UID issue have the same issue with GID? If we're still root, as long as setgid is allowed, it shouldn't matter what the order is. I think these commands, run as root, will tell us: perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; $( = 1000; p;' perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $( = 1000; $) = "1000 1000"; p;' perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; p; $) = $(; p; $( = 1000; $) = "1000 1000"; p;' The first is the way we do it now. The second is just reversing the order of setting. The third mimics the patch for uid. The output of both $( and $) are multiple numbers, annoyingly. The first number is what really matters though. Mac OS X: Will not setuid nor setgid. seteuid and setegid work ok. # perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; $( = 1000; p;' RGID: 0 80 31 20 5 4 3 2 1 0, EGID: 0 80 31 20 5 4 3 2 1 0 RGID: 0 1000, EGID: 1000 1000 # perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 80 31 20 5 4 3 2 1 0, EGID: 0 80 31 20 5 4 3 2 1 0 RGID: 0 1000, EGID: 1000 1000 perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; p; $) = $(; p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 80 31 20 5 4 3 2 1 0, EGID: 0 80 31 20 5 4 3 2 1 0 RGID: 0 1000, EGID: 1000 1000 RGID: 0 0, EGID: 0 0 RGID: 0 1000, EGID: 1000 1000 Linux, just for comparison: # perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; $( = 1000; p;' RGID: 0 100 10 6 4 3 2 1 0, EGID: 0 100 10 6 4 3 2 1 0 RGID: 1000 1000, EGID: 1000 1000 # perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 100 10 6 4 3 2 1 0, EGID: 0 100 10 6 4 3 2 1 0 RGID: 1000 1000, EGID: 1000 1000 # perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; p; $) = $(; p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 100 10 6 4 3 2 1 0, EGID: 0 100 10 6 4 3 2 1 0 RGID: 0 1000, EGID: 1000 1000 RGID: 0 1000, EGID: 0 1000 RGID: 1000 1000, EGID: 1000 1000
[00:13:06 root@fat_man: /home/mike]# perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; $( = 1000; p;' RGID: 0 31 20 5 4 3 2 0 0, EGID: 0 31 20 5 4 3 2 0 0 RGID: 1000 1000, EGID: 1000 1000 [00:13:37 root@fat_man: /home/mike]# perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 31 20 5 4 3 2 0 0, EGID: 0 31 20 5 4 3 2 0 0 RGID: 1000 1000, EGID: 1000 1000 [00:13:53 root@fat_man: /home/mike]# perl -e 'sub p {print "RGID: $(, EGID: $)\n";} p; $) = "1000 1000"; p; $) = $(; p; $( = 1000; $) = "1000 1000"; p;' RGID: 0 31 20 5 4 3 2 0 0, EGID: 0 31 20 5 4 3 2 0 0 RGID: 0 1000, EGID: 1000 1000 RGID: 0 0, EGID: 0 0 RGID: 1000 1000, EGID: 1000 1000
+0.5. can you change + if ($< != $>) { to be + if ($< != $touid) { just in case $> doesn't change from 0 on the 2nd one for some reason?
Subject: Re: [review] perl setuid fails, breaking spamd in FreeBSD, MacOS X On Sun, Jul 18, 2004 at 10:52:53PM -0700, bugzilla-daemon@bugzilla.spamassassin.org wrote: > +0.5. can you change > > + if ($< != $>) { > > to be > > + if ($< != $touid) { > > just in case $> doesn't change from 0 on the 2nd one for some reason? sure. although, the euid will change (at least in every test we tried), so $< won't == $> in that situation. actually, I'll add a little more logic to it, since this stupidity doesn't have to be done for most platforms.
Created attachment 2147 [details] new version
+1 -- I like the extra sanity checking. ;)
+1
committed. r23168