[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: discarding root privileges in suid perl



>>>>> "Daniel" == Daniel Jacobowitz <dan@debian.org> writes:

    Daniel> I would expect this to be something to do with saved
    Daniel> userids... see setresuid(2) for more information:

Yes, I think you might be correct.

    Daniel>        Unprivileged user processes (i.e., processes with
    Daniel> each of real, effective and saved user ID nonzero) may
    Daniel> change the real, effective and saved user ID, each to one
    Daniel> of: the current uid, the current effective uid or the
    Daniel> current saved uid.

    Daniel>        The super-user may set real, effective and saved
    Daniel> user ID to arbitrary values.

    Daniel> It's not clear what happens when saved uid is zero and the
    Daniel> others are nonzero, but I bet that's what you're seeing.
    Daniel> Note that saved uid is -not- preserved across exec() IIRC.
    Daniel> So if you drop priviledges and then run a script that
    Daniel> tries to get them back, it will fail, even if the parent
    Daniel> could.

This sounds correct. Where did you find this documented? I tried
looking up the functions in the info documentation for libc, but it
doesn't seem to contain anything (that I could find).


>From the messages <ufa4s42bca7.fsf@epithumia.math.uh.edu> in
comp.lang.perl.moderated on deja.com,

--- cut ---
 >...
 >I think the real bug here, if there's one that can be easily identified,
 >is that POSIX::setuid() isn't actually setuid() like it should be.
  
 I agree.  I was "on" POSIX::setuid() a long time ago.  If it had been implemented to call setuid(),
 that would have been the end of the matter.  Oh well...
  
 I think that perl is trying to do The Right Thing when you code: 
  
         $> = $id;
         $< = $id;
  
 and it does relinquish root when this is done on Solaris.  The 
 documentation is far from clear about this, though and the perlsec manual page is just plain
 wrong since it never assigns to $< to drop privileges. 
--- cut ---

So, perhaps somebody should file a bug report against the perlsec man
page.  My guess, is its advice is non-portable, and only works on some
platforms.

I would file a bug report, but I am getting totally confused, and not
sure I could justify the reasons why the example is incorrect. I will
try here. I don't claim this is accurate or anything...

--- cut & [mis]interpreted ---
So, the following functions, as implemented in the kernel would
look something like this???? I have prefixed kernel variables
with "k" to make them different from the perl values.

setuid {
  my ($uid) = @_;
  if ($kEUID == 0) { $kUID=$kEUID=$ksaved=$uid; }
  elsif ($kEUID == $kUID or $kEUID == $ksaved) { $kEUID=$uid; }
}

seteuid {
  my ($uid) = @_;
??????
}

setreuid {
  my ($uid,$X) = @_;
  ($kUID,$kEUID) = ($kEUID,$kUID);
  if ($saved != $kUID) { $saved = $kEUID; }
}
--- cut & [mis]interpreted ---

So debugging the code in the man page (I won't worry about groups):

initially:
$saved=?; $EUID = 0; $UID=1003;

print("$EUID $UID");
>> prints 0 1003
 
my @temp = ($EUID);
>>> @temp = (0);

$EUID = $UID;
>>> seteuid(1003);
>>> $kEUID = 1003;
>>> $EUID = 1003;

print("$EUID $UID");
>> prints 1003 1003

($EUID) = @temp;
>>> seteuid(0);
>>> $kEUID = 0
>>> $kUID = 0

print("$EUID $UID");
>> prints 0 1003

So I am still a bit of a loss, and I am not sure how seteuid works.

Either:
  - $saved initially is 0 and not affected by the seteuid(1003).

OR: 
  - $saved is set to 0 by seteuid(1003) possibly because $EUID was
previous 0.

I hope some of this makes sense to someone :-)


Just to confuse matters even more:

ps xf -eo pid,ppid,uid,euid,fuid,fsuid,svuid,suid,ruid,ucmd | less

don't ask me what all of these mean ;-)
ruid != uid
uid == euid == fuid == fsuid generally
svuid == suid == ruid except for:

  PID  PPID   UID  EUID  FUID FSUID SVUID  SUID  RUID CMD
  566     1     1     1     1     1     1     1     0 atd
21980     1   109   109   109   109   109   109   109 rproxy
 4028 21980   109   109   109   109   109   109     0  \_ rproxy <defunct>
 4030 21980   109   109   109   109   109   109     0  \_ rproxy <defunct>
 4032 21980   109   109   109   109   109   109     0  \_ rproxy <defunct>
 4033 21980   109   109   109   109   109   109     0  \_ rproxy <defunct>
27266     1  1003  1003  1003  1003  1003  1003  1003 gnome-terminal
27268 27266  1003  1003  1003  1003  1003  1003  1003  \_ zsh
 4362 27268     0     0     0     0     0     0  1003      \_ perl5.00503
 4391  4362     0     0     0     0     0     0  1003          \_ tail


which, too me, doesn't make any sense what-so-ever. Why does rproxy,
which is *not* a setuid program, have ruid==0?

The last process is mine, where $UID=0, $EUID=1003, as shown by a perl
print statement, before calling system("tail")). So I guess
RUID=real user
UID=somethingelse
EUID=effective user
SUID=saved UID???

Note:
[1] Is this the same on Linux? I have Linux 2.2.17, final version.
-- 
Brian May <bam@debian.org>



Reply to: