> Just to make sure I understand what is expected of isssetguid() - could you
> perhaps, in terms of ls -l output with suid programs describe the
> sequence(s) where the value should be 1 - and especially, when they might
> (read should) be 0.
> 
> >From memory of what I read (how I understood) the man page, if was
> superuser, and am still user - then 0 is appropriate. However, if was
> superuser (euid == 0) and a setuid call is used to demote/lower privilidge
> then 1 is the correct value.

Completely wrong, and I have no no idea where you got that from!

Read the man page again!

http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/issetugid.2?query=issetugid

The issetugid status of a process is only affected by execve().

Let's look at the OpenBSD kernel, where this system call was invented,
for the exact semantics.

This issetugid() system call simply returns the status:

        if (p->p_p->ps_flags & PS_SUGIDEXEC)
                *retval = 1;
        else
                *retval = 0;

What affects PS_SUGIDEXEC?  It is only set or cleared in execve()
based on variables which are probably self-evident:

        /*
         * If process does execve() while it has a mismatched real,
         * effective, or saved uid/gid, we set PS_SUGIDEXEC.
         */
        if (cred->cr_uid != cred->cr_ruid ||
            cred->cr_uid != cred->cr_svuid ||
            cred->cr_gid != cred->cr_rgid ||
            cred->cr_gid != cred->cr_svgid)
                atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC);
        else
                atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC);

Meanwhile, at fork() time, the child simply inherits the status of
the parent:

        pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC);

You will note a second flag called PS_SUGID at fork, which dates back
to the dawn of time.  The difference between these flags is very
subtly described in the .h file:

#define PS_SUGID        0x00000010      /* Had set id privs since last exec. */
#define PS_SUGIDEXEC    0x00000020      /* last execve() was set[ug]id */

The dominant usage pattern for issetugid() is to prevent inspection of
the environment via getenv(), down in a library.

The issetugid() API relieves programs from having to sanitize their
environment before calling into libraries, because the 90's showed us
someone always screws up that pattern........ the libraries need a
method to save themselves.  Patterns like getuid() != geteuid() do not
give you the same guarantees.  issetugid() tells you that your
priviledge level is incompatible with the provinance of the
environment strings.

Reply via email to