Once upon a time, Leon Timmermans via RT <perlbug-followup@perl.org> said: > On Mon Sep 12 09:39:58 2011, cmadams@hiwaay.net wrote: > > [Please enter your report here] > > Setting a user/group ID by assigning to the perl special variables > > does > > not clear $!, so confusing errors can occur. This test program fails > > on > > 5.8.8 (RHEL 5) and 5.12.4 (Fedora Linux 15): > > > > ######################################################################## > > #!/usr/bin/perl > > > > use warnings; > > use strict; > > > > my @foo = stat ("/does/not/exist"); > > my $gid = $( + 0; > > $( = $gid; > > die "setgid($gid): $!\n" if ($!); > > ######################################################################## > > > > I get "setgid(1000): No such file or directory". If I take out the > > stat() or add a "$! = undef" after the stat(), the script runs as > > expected. > > First of all, that is exactly what you should expect. Succeeding system > calls do not set errno, only failing ones do. If you want to check for > an error by using $!, you should set it to 0 before setting $(. The problem is that is not what the documentation says. The docs say "require a check to $! to detect any possible errors", not "you must clear $! first, make your change, then check the results". The underlying problem is that the perl source code doesn't check or save the return code from the setregid() call. Since library calls can have unexpected side-effects, perl should handle this internally. For example, my actual code that shows the problem fails after a getpwnam() for some users (and not others). getpwnam() uses the NSS library for its lookups, and some users are local (/etc/passwd) while most are from the network (LDAP). The NSS library tries a couple of locations to load libnss_ldap.so.2, and errno doesn't get cleared after the first location returns ENOENT. This is highly confusing, and there's really no reason to push this off on the people writing perl code. At a minimum, perl internally could do something like: if (setregid(gid,-1) == 0) errno = 0; (and that goes for all the setuid/setgid family of functions). > Secondly, what you're doing is completely wrong. You're setting the real > GID but not the effective GID, thus not dropping privileges at all. Try > POSIX' setuid/setgid, or better yet something like Unix::SetUser or > Proc::UID. No, I only want to set the real GID here (I'm dropping privs temporarily for a check). Also, the above is just a short-and-simple example of the problem, not my full code. -- Chris Adams <cmadams@hiwaay.net> Systems and Network Administrator - HiWAAY Internet Services I don't speak for anybody but myself - that's enough trouble.Thread Next