develooper 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:
Abigail
Date:
February 3, 2011 08:46
Subject:
Re: setuid and serious trouble (Re: Time to update POSIX.pm?)
Message ID:
20110203164604.GG31664@almanda
On Thu, Feb 03, 2011 at 05:29:09PM +0100, Mark Overmeer wrote:
> * Leon Timmermans (fawaka@gmail.com) [110203 13:07]:
> > On Thu, Feb 3, 2011 at 11:14 AM, Mark Overmeer <mark@overmeer.net> wrote:
> > >   sub setuid($) { $< = $_[0] }
> > 
> > That is *not* what setuid(2) does. That would be violating people's
> > expectations (and indirectly the standard). Worse yet, that would
> > break people's code and open security holes. setuid is a mess, but
> > let's not redefine what the function does.
> 
> $< uses setruid, setreuid (setting only uid), setresuid (setting only uid)
> or setuid. (mg.c line 3310) In that order. The latter is PerlProc_setuid,
> just as in POSIX.xs because both include XSUB.h which rewrites it via
> a macro. Via iperlsys.h, however, it is translated back into the normal
> setuid(2).
> 
> It would be very unexpected to see  setreuid($uid, -1)  do something
> different than  setuid($uid).  The former is to avoid race-conditions
> when uid and euid both have to change.
> 
> Anyway, I do not have the POSIX standard on my shelf (yet). My HP-UX 6.5
> reference (1988) does not differ from my Linux manual page about setuid()
> (in logic to say, the text is completely different)


--------------------------------------------------------------------------------

The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Copyright © 2001-2004 The IEEE and The Open Group, All Rights reserved.

--------------------------------------------------------------------------------

NAME

    setuid - set user ID

SYNOPSIS

    #include <unistd.h>

    int setuid(uid_t uid);

DESCRIPTION

    If the process has appropriate privileges, setuid() shall set the
    real user ID, effective user ID, and the saved set-user-ID of the
    calling process to uid.

    If the process does not have appropriate privileges, but uid is equal
    to the real user ID or the saved set-user-ID, setuid() shall set
    the effective user ID to uid; the real user ID and saved set-user-ID
    shall remain unchanged.

    The setuid() function shall not affect the supplementary group list
    in any way.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall
    be returned and errno set to indicate the error.

ERRORS

    The setuid() function shall fail, return -1, and set errno to the
    corresponding value if one or more of the following are true:

    [EINVAL]
        The value of the uid argument is invalid and not supported by
        the implementation.
    [EPERM]
        The process does not have appropriate privileges and uid does
        not match the real user ID or the saved set-user-ID.

The following sections are informative.

EXAMPLES

    None.

APPLICATION USAGE

    None.

RATIONALE

    The various behaviors of the setuid() and setgid() functions when
    called by non-privileged processes reflect the behavior of different
    historical implementations. For portability, it is recommended that
    new non-privileged applications use the seteuid() and setegid()
    functions instead.

    The saved set-user-ID capability allows a program to regain the
    effective user ID established at the last exec call. Similarly,
    the saved set-group-ID capability allows a program to regain
    the effective group ID established at the last exec call. These
    capabilities are derived from System V. Without them, a program might
    have to run as superuser in order to perform the same functions,
    because superuser can write on the user's files. This is a problem
    because such a program can write on any user's files, and so must be
    carefully written to emulate the permissions of the calling process
    properly. In System V, these capabilities have traditionally
    been implemented only via the setuid() and setgid() functions
    for non-privileged processes. The fact that the behavior of those
    functions was different for privileged processes made them difficult
    to use. The POSIX.1-1990 standard defined the setuid() function to
    behave differently for privileged and unprivileged users. When the
    caller had the appropriate privilege, the function set the calling
    process' real user ID, effective user ID, and saved set-user ID on
    implementations that supported it. When the caller did not have the
    appropriate privilege, the function set only the effective user ID,
    subject to permission checks. The former use is generally needed for
    utilities like login and su, which are not conforming applications
    and thus outside the scope of IEEE Std 1003.1-2001. These utilities
    wish to change the user ID irrevocably to a new value, generally that
    of an unprivileged user. The latter use is needed for conforming
    applications that are installed with the set-user-ID bit and need
    to perform operations using the real user ID.

    IEEE Std 1003.1-2001 augments the latter functionality with a
    mandatory feature named _POSIX_SAVED_IDS. This feature permits a
    set-user-ID application to switch its effective user ID back and
    forth between the values of its exec-time real user ID and effective
    user ID. Unfortunately, the POSIX.1-1990 standard did not permit a
    conforming application using this feature to work properly when it
    happened to be executed with the (implementation-defined) appropriate
    privilege. Furthermore, the application did not even have a means
    to tell whether it had this privilege. Since the saved set-user-ID
    feature is quite desirable for applications, as evidenced by the
    fact that NIST required it in FIPS 151-2, it has been mandated by
    IEEE Std 1003.1-2001. However, there are implementors who have been
    reluctant to support it given the limitation described above.

    The 4.3BSD system handles the problem by supporting separate
    functions: setuid() (which always sets both the real and effective
    user IDs, like setuid() in IEEE Std 1003.1-2001 for privileged
    users), and seteuid() (which always sets just the effective user
    ID, like setuid() in IEEE Std 1003.1-2001 for non-privileged
    users). This separation of functionality into distinct functions
    seems desirable. 4.3BSD does not support the saved set-user-ID
    feature. It supports similar functionality of switching the effective
    user ID back and forth via setreuid(), which permits reversing the
    real and effective user IDs. This model seems less desirable than
    the saved set-user-ID because the real user ID changes as a side
    effect. The current 4.4BSD includes saved effective IDs and uses
    them for seteuid() and setegid() as described above. The setreuid()
    and setregid() functions will be deprecated or removed.

    The solution here is:

        * Require that all implementations support the functionality of
          the saved set-user-ID, which is set by the exec functions and
          by privileged calls to setuid().
        * Add the seteuid() and setegid() functions as portable
          alternatives to setuid() and setgid() for non-privileged and
          privileged processes.

    Historical systems have provided two mechanisms for a set-user-ID
    process to change its effective user ID to be the same as its real
    user ID in such a way that it could return to the original effective
    user ID: the use of the setuid() function in the presence of a saved
    set-user-ID, or the use of the BSD setreuid() function, which was
    able to swap the real and effective user IDs. The changes included
    in IEEE Std 1003.1-2001 provide a new mechanism using seteuid() in
    conjunction with a saved set-user-ID. Thus, all implementations with
    the new seteuid() mechanism will have a saved set-user-ID for each
    process, and most of the behavior controlled by _POSIX_SAVED_IDS
    has been changed to agree with the case where the option was
    defined. The kill() function is an exception. Implementors of the
    new seteuid() mechanism will generally be required to maintain
    compatibility with the older mechanisms previously supported by
    their systems. However, compatibility with this use of setreuid()
    and with the _POSIX_SAVED_IDS behavior of kill() is unfortunately
    complicated. If an implementation with a saved set-user-ID allows a
    process to use setreuid() to swap its real and effective user IDs,
    but were to leave the saved set-user-ID unmodified, the process
    would then have an effective user ID equal to the original real
    user ID, and both real and saved set-user-ID would be equal to the
    original effective user ID. In that state, the real user would be
    unable to kill the process, even though the effective user ID of
    the process matches that of the real user, if the kill() behavior
    of _POSIX_SAVED_IDS was used. This is obviously not acceptable. The
    alternative choice, which is used in at least one implementation,
    is to change the saved set-user-ID to the effective user ID during
    most calls to setreuid(). The standard developers considered that
    alternative to be less correct than the retention of the old behavior
    of kill() in such systems. Current conforming applications shall
    accommodate either behavior from kill(), and there appears to be no
    strong reason for kill() to check the saved set-user-ID rather than
    the effective user ID.

FUTURE DIRECTIONS

    None.

SEE ALSO

    exec(), getegid(), geteuid(), getgid(), getuid(), setegid(),
    seteuid(), setgid(), setregid(), setreuid(), the Base Definitions
    volume of IEEE Std 1003.1-2001, <sys/types.h>, <unistd.h>

CHANGE HISTORY

    First released in Issue 1. Derived from Issue 1 of the SVID.

Issue 6

    In the SYNOPSIS, the optional include of the <sys/types.h> header
    is removed.

    The following new requirements on POSIX implementations derive from
    alignment with the Single UNIX Specification:

        * The requirement to include <sys/types.h> has been
          removed. Although <sys/types.h> was required for conforming
          implementations of previous POSIX specifications, it was not
          required for UNIX applications.
        * The functionality associated with _POSIX_SAVED_IDS is now
          mandatory. This is a FIPS requirement.

    The following changes were made to align with the IEEE P1003.1a
    draft standard:

        * The effects of setuid() in processes without appropriate
          privileges are changed.
        * A requirement that the supplementary group list is not affected
          is added.

--------------------------------------------------------------------------------

NAME

    seteuid - set effective user ID

SYNOPSIS

    #include <unistd.h>

    int seteuid(uid_t uid);

DESCRIPTION

    If uid is equal to the real user ID or the saved set-user-ID, or
    if the process has appropriate privileges, seteuid() shall set the
    effective user ID of the calling process to uid; the real user ID
    and saved set-user-ID shall remain unchanged.

    The seteuid() function shall not affect the supplementary group list
    in any way.

RETURN VALUE

    Upon successful completion, 0 shall be returned; otherwise, -1 shall
    be returned and errno set to indicate the error.

ERRORS

    The seteuid() function shall fail if:

    [EINVAL]
        The value of the uid argument is invalid and is not supported
        by the implementation.
    [EPERM]
        The process does not have appropriate privileges and uid does
        not match the real user ID or the saved set-user-ID.

The following sections are informative.

EXAMPLES

    None.

APPLICATION USAGE

    None.

RATIONALE

    Refer to the RATIONALE section in setuid().

FUTURE DIRECTIONS

    None.

SEE ALSO

    exec(), getegid(), geteuid(), getgid(), getuid(), setegid(), setgid(),
    setregid(), setreuid(), setuid(), the Base Definitions volume of
    IEEE Std 1003.1-2001, <sys/types.h>, <unistd.h>

CHANGE HISTORY

    First released in Issue 6. Derived from the IEEE P1003.1a draft standard.

    IEEE Std 1003.1-2001/Cor 2-2004, item XSH/TC2/D6/123 is applied,
    making an editorial correction to the [EPERM] error in the ERRORS
    section.

--------------------------------------------------------------------------------

NAME

    setreuid - set real and effective user IDs

SYNOPSIS

    #include <unistd.h>

    int setreuid(uid_t ruid, uid_t euid);

DESCRIPTION

    The setreuid() function shall set the real and effective user IDs
    of the current process to the values specified by the ruid and euid
    arguments. If ruid or euid is -1, the corresponding effective or
    real user ID of the current process shall be left unchanged.

    A process with appropriate privileges can set either ID to any
    value. An unprivileged process can only set the effective user ID if
    the euid argument is equal to either the real, effective, or saved
    user ID of the process.

    It is unspecified whether a process without appropriate privileges
    is permitted to change the real user ID to match the current real,
    effective, or saved set-user-ID of the process.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall
    be returned and errno set to indicate the error.

ERRORS

    The setreuid() function shall fail if:

    [EINVAL]
        The value of the ruid or euid argument is invalid or out-of-range.
    [EPERM]
        The current process does not have appropriate privileges, and
        either an attempt was made to change the effective user ID to a
        value other than the real user ID or the saved set-user-ID or
        an attempt was made to change the real user ID to a value not
        permitted by the implementation.

The following sections are informative.

EXAMPLES

    Setting the Effective User ID to the Real User ID

    The following example sets the effective user ID of the calling
    process to the real user ID, so that files created later will be
    owned by the current user.

    #include <unistd.h>
    #include <sys/types.h>
    ...
    setreuid(getuid(), getuid());
    ...

APPLICATION USAGE

    None.

RATIONALE

    None.

FUTURE DIRECTIONS

    None.

SEE ALSO

    getegid(), geteuid(), getgid(), getuid(), setegid(), seteuid(),
    setgid(), setregid(), setuid(), the Base Definitions volume of IEEE
    Std 1003.1-2001, <unistd.h>

CHANGE HISTORY

    First released in Issue 4, Version 2.

Issue 5

    Moved from X/OPEN UNIX extension to BASE.

--------------------------------------------------------------------------------

Thread Previous | Thread Next


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