issetugid [deraadt@CVS.OPENBSD.ORG]

Chip Salzenberg (chip@perl.org)
Sun, 12 Jul 1998 01:26:05 -0400


In a message to BUGTRAQ, Theo de Raadt <deraadt@CVS.OPENBSD.ORG>
writes about the old bugaboo of setuid programs trusting their
environment, and how FreeBSD addresses this issue. I think that
keeping this kind of info in the kernel is a Great Idea [tm]:

> issetugid() tells you that the process is "tainted", because at some
> point in the past it or it's parent(s) were started as a setuid
> process. This kind of means it has or did have two uids or two gids,
> but more generally it just means it was setuid or setuid back a while
> ago. It's parent might have and might have revoked the privs before
> fork()'ing the child, but in such a case the child still is "tainted".
> (Who knows. it might have some nasty descriptor inside it, like a
> SOCK_RAW, or a writeable descriptor to /etc/master.passwd).
>
> The issetugid() status remains attached to a process and it's children
> until execve() -- at which point it is assumed that either (1) the
> environment was cleaned, or (2) the elevated uid/gid permissions were
> completely revoked -- hence execve() is a safe place to remove the
> status. If either of these two assumptions is not met, you've got a
> hell of a lot worse problem, and nothing could save you.
>
> Since the program is tainted, there are a couple of resources you should
> not trust.
>
> One of those is the environment.
>
> Or at least, processes with this state should be careful with how MUCH
> they trust the environment.
>
> In a program itself, it is easy to detect this issue because you have
> access to your uid and gid information. Deep in a library, it is
> impossible to reliably get access to the uid and gid information, so
> issetugid() tells you when you should not trust completely.
>
> Does this mean $TZ can't work at all when when issetugid() returns 1?
>
> No -- $TZ works..... It just doesn't work completely and fully.
>
> TZ=Canada/Mountain works.
>
> TZ=/dev/rst0 doesn't work (ie. it doesn't rewind the tape which your
> backup software was carefully writing a series of files onto using
> /dev/nrst0)
>
> Here's the code snippet in tzload() that matters:
>
> if (name != NULL && issetugid() != 0)
> if ((name[0] == ':' && name[1] == '/') ||
> name[0] == '/' || strchr(name, '.'))
> name = NULL;
>
> This is obviously the right thing to do. (We could improve it a bit
> perhaps, but for now it is completely safe).
>
> Similar things are done in other places in the libraries (not just
> libc). Some variables from the environment are completely ignored;
> others have various restrictions placed upon them.
>
> We've solved this problem. We had to add a system call, which is
> unfortunate, but noone can deny that we solved this problem. We
> looked at crt0 based solutions as well, but we decided to do it this
> way.

-- 
Chip Salzenberg               - a.k.a. -              <chip@perlsupport.com>
  "Take it to the bridge, Sinbad!  ... drop it in the water ..."  //MST3K

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html