Front page | perl.perl5.porters |
Postings from February 2011
Re: setuid and serious trouble (Re: Time to update POSIX.pm?)
Thread Previous
|
Thread Next
From:
Tom Christiansen
Date:
February 3, 2011 05:57
Subject:
Re: setuid and serious trouble (Re: Time to update POSIX.pm?)
Message ID:
18507.1296741400@chthon
> I hope you will comment on the bigger story as well.
Very well.
I haven't looked into the matter in detail. I do know that there
may now be something of a mismatch between traditional setxid
semantics of two different id sets wherein setting the real id
was a one-way trip, and current prevailing semantics where you
have three different id sets and can get back the saved id even
having set both real and effective ids. That doesn't map so well
to Perl's two-id system unless you clump them.
I'm concerned that platform variations may preclude ever managing
these things in a uniform manner. Consider that all these hints
files mention /set[re]*[ug]id/:
aix.sh darwin.sh freebsd.sh openbsd.sh svr5.sh
aix_3.sh dcosx.sh linux.sh qnx.sh unicos.sh
aix_4.sh dgux.sh mpeix.sh solaris_2.sh unicosmk.sh
bsdos.sh epix.sh netbsd.sh svr4.sh vmesa.sh
For example, from the very top of openbsd.sh:
# In OpenBSD < 3.3, the setre?[ug]id() are emulated using the
# _POSIX_SAVED_IDS functionality which does not have the same
# semantics as 4.3BSD. Starting with OpenBSD 3.3, the original
# semantics have been restored.
case "$osvers" in
[0-2].*|3.[0-2])
d_setregid=$undef
d_setreuid=$undef
d_setrgid=$undef
d_setruid=$undef
esac
Looking at manpages on a couple of BSD systems (OpenBsd and Darwin),
Solaris, and Linux, it begins to look like there may be some convergence
at least amongst those three/four. I include the three relevant manpage
sections from those respective systems below by signature.
So it may be that we can do something reasonable. I'd very much
like to keep as uniform an interface into the id sets as we can,
because setxid is too important a matter to be left up to
platform variation if there's any possible way to avoid that.
I suspect it may be unrelated, but I have old memories of
insecurity creep involved in setxid scripts that set spider
senses tingling. I notice there's at least one lesson to be
learnt in looking at which hints files mention the associated
flag for secure suid scripts:
dcosx.sh:d_suidsafe=define
dgux.sh:d_suidsafe='define'
epix.sh:d_suidsafe='define' # "./Configure -d" can't figure this out easilly
esix4.sh:d_suidsafe=define
linux.sh:d_suidsafe='undef'
mirbsd.sh:d_suidsafe=$define
openbsd.sh:d_suidsafe=$define
powerux.sh:d_suidsafe='define'
qnx.sh: d_suidsafe='define'
solaris_2.sh:d_suidsafe=${d_suidsafe:-define}
svr4.sh:d_suidsafe='define' # "./Configure -d" can't figure this out easilly
svr5.sh:d_suidsafe='define' # "./Configure -d" can't figure this out easily
uts.sh:d_suidsafe='define'
vmesa.sh:d_suidsafe='undef'
The lesson? That we cut and paste a lot, and that
we don't most of us spell check our hints files. :)
--tom
====== OpenBSD and also Darwin setuid(2) ======
The setuid() function sets the real and effective user IDs and the saved
set-user-ID of the current process to the specified value. The setuid()
function is permitted if the effective user ID is that of the superuser,
or if the specified user ID is the same as the effective user ID. If
not, but the specified user ID is the same as the real user ID, setuid()
will set the effective user ID to the real user ID.
The setgid() function sets the real and effective group IDs and the
saved set-group-ID of the current process to the specified value. The
setgid() function is permitted if the effective user ID is that of the
superuser, or if the specified group ID is the same as the effective
group ID. If not, but the specified group ID is the same as the real
group ID, setgid() will set the effective group ID to the real group
ID. Supplementary group IDs remain unchanged.
The seteuid() function (setegid()) sets the effective user ID (group ID)
of the current process. The effective user ID may be set to the value of
the real user ID or the saved set-user-ID (see intro(2) and execve(2));
in this way, the effective user ID of a set-user-ID executable may be
toggled by switching to the real user ID, then re-enabled by reverting to
the set-user-ID value. Similarly, the effective group ID may be set to
the value of the real group ID or the saved set-group-ID.
====== Solaris setuid(2) ======
The setuid() function sets the real user ID, effective user
ID, and saved user ID of the calling process. The setgid()
function sets the real group ID, effective group ID, and
saved group ID of the calling process. The setegid() and
seteuid() functions set the effective group and user IDs
respectively for the calling process. See intro(2) for more
information on real, effective, and saved user and group
IDs.
At login time, the real user ID, effective user ID, and
saved user ID of the login process are set to the login ID
of the user responsible for the creation of the process. The
same is true for the real, effective, and saved group IDs;
they are set to the group ID of the user responsible for the
creation of the process.
When a process calls one of the exec(2) family of functions
to execute a file (program), the user and/or group identif-
iers associated with the process can change. If the file
executed is a set-user-ID file, the effective and saved user
IDs of the process are set to the owner of the file exe-
cuted. If the file executed is a set-group-ID file, the
effective and saved group IDs of the process are set to the
group of the file executed. If the file executed is not a
set-user-ID or set-group-ID file, the effective user ID,
saved user ID, effective group ID, and saved group ID are
not changed.
If the {PRIV_PROC_SETID} privilege is asserted in the effec-
tive set of the process calling setuid(), the real, effec-
tive, and saved user IDs are set to the uid argument. If
the uid argument is 0 and none of the saved, effective or
real UID is 0, additional restrictions apply. See
privileges(5).
If the {PRIV_PROC_SETID} privilege is not asserted in the
effective set, but uid is either the real user ID or the
saved user ID of the calling process, the effective user ID
is set to uid.
If the {PRIV_PROC_SETID} privilege is asserted in the effec-
tive set of the process calling setgid(), the real, effec-
tive, and saved group IDs are set to the gid argument.
If the {PRIV_PROC_SETID} privilege is not asserted in the
effective set, but gid is either the real group ID or the
saved group ID of the calling process, the effective group
ID is set to gid.
====== Linus setuid(2) ======
setuid() sets the effective user ID of the calling process. If the
effective UID of the caller is root, the real UID and saved set-user-
ID are also set.
Under Linux, setuid() is implemented like the POSIX version with
the _POSIX_SAVED_IDS feature. This allows a set-user-ID (other
than root) program to drop all of its user privileges, do some un-
privileged work, and then re-engage the original effective user ID in
a secure manner.
If the user is root or the program is set-user-ID-root, special care
must be taken. The setuid() function checks the effective user ID of
the caller and if it is the superuser, all process-related user ID's
are set to uid. After this has occurred, it is impossible for the
program to regain root privileges.
Thus, a set-user-ID-root program wishing to temporarily drop root
privileges, assume the identity of a non-root user, and then regain
root privileges afterwards cannot use setuid(). You can accomplish this
with the (non-POSIX, BSD) call seteuid(2).
Thread Previous
|
Thread Next