> how do you fix this? how does a _library_ know this? openbsd has defined an > issetugid() syscall (or something) that libraries could use to ignore the > things like $TAPE and $TERMCAP, etc., but that isn't correct. You don't think it is correct? Almost two years ago we completely solved the problem this entire thread is talking about. And you don't think that is correct? Is it better to leave it unfixed? > how does it > know what the real userid _really_ is, to perform the necessary checks on > whether a file will be used or not -- or do you simple say that priviledged > programs don't get this functionality? Well, first off, it is obvious that you completely misunderstand how this interface is intended to be used. 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. I've been told that vmailer calls issetugid() for similar reasons (if it exists, which means OpenBSD or FreeBSD, though the FreeBSD semantics are a tiny little bit different). (Wietse helped me clean up the man page). > i've had fixing this in problem in my TODO liist for over 2 years but > without a total solution i've left it as is for now. these are the > variables listed that NetBSD uses that i've determined are affected: > > - TZ > - TERMCAP > - HOSTALIASES So for two years you've done absolutely nothing, and yet you think it is your place to denounce the actions of others who fixed this problem? In this community, "I knew about that security problem two years ago" doesn't count for much. And what about the following, from your library source tree? PROFDIR LOCALDOMAIN NLSPATH TMPDIR RCMD_CMD RES_OPTIONS DEBUGTTY HOME PATH_LOCALE ---------------------------------------- Here is our man page: ISSETUGID(2) OpenBSD Programmer's Manual ISSETUGID(2) NAME issetugid - is current executable running setuid or setgid SYNOPSIS #include <unistd.h> int issetugid(void); DESCRIPTION The issetugid() function returns 1 if the process was made setuid or set- gid as the result of the last or other previous execve() system calls. Otherwise it returns 0. This system call exists so that library routines (inside libtermlib, libc, or other libraries) can gaurantee safe behavior when used inside setuid or setgid programs. Some library routines may be passed insuffi- cient information and hence not know whether the current program was started setuid or setgid because higher level calling code may have made changes to the uid, euid, gid, or egid. Hence these low-level library routines are unable to determine if they are being run with elevated or normal priveledges. In particular, it is wise to use this call to determine if a pathname re- turned from a getenv() call may safely be used to open() the specified file. Quite often this is not wise because the status of the effective uid is not known. The issetugid() system call's result is unaffected by calls to setuid(), setgid(), or other such calls. In case of a fork(), the child process inherits the same status. The status of issetugid() is only affected by execve(). If a child pro- cess executes a new executable file, a new issetuid status will be deter- mined. This status is based on the existing process' uid, euid, gid, and egid permissions and on the modes of the executable file. If the new ex- ecutable file modes are setuid or setgid, or if the existing process is executing the new image with uid != euid or gid != egid, the new process will be considered issetugid. ERRORS The issetugid() function is always successful, and no return value is re- served to indicate an error. SEE ALSO execve(2), setuid(2), seteuid(2), setgid(2), setegid(2) HISTORY The issetugid() function call first appeared in OpenBSD 2.0. OpenBSD 2.0 August, 25 1996 1
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:03:12 PDT