Newsgroups: comp.unix.wizards Path: utzoo!utgpu!jarvis.csri.toronto.edu!ai.toronto.edu!rayan From: rayan@ai.toronto.edu (Rayan Zachariassen) Subject: setreuid() functionality in sysV Message-ID: <1988Jan19.192854.3411@jarvis.csri.toronto.edu> Organization: University of Toronto, AI group Date: Tue, 19-Jan-88 19:28:54 EST I'm trying to simulate the effect (within a root process) of the BSD construct: setreuid(0, uid); ... setreuid(0, 0); The important thing being that the '...' is run with effective uid 'uid', and that both real and effective uid are restored to 0 afterwards. Now, the SysV manual for setuid() says that setuid(uid); ... setuid(0); is possible iff 0 is the "saved set_user id" and refers to exec(2). Of course, exec(2) doesn't mention this concept. What does "saved set_user id" mean? That the suid bit is set on the executable and this is the owner of the binary, or that it is the uid that actually did the exec'ing (uid of parent)? So, we tried it under SysVr2v4 (no, this is not crypt output...) on a Honeywell box, the token System V machine here. Apparently, the documented behaviour refers to neither of the two possibilities hypothesized. If anyone knows how to achieve the desired result under some System V (without using fork()), pray tell. Incidentally, the '...' is essentially an fopen call. Can't use access(); for one thing it is junk, for another it tests on the real uid anyway, which brings us back to the problem at hand. You can also tell me it can't be done, in which case this program will allow astute persons to deduce the contents of files they can't read, and aren't allowed to access. :-( How does one write secure code under System V without using zillions of forks? (that's rhetorical). Incidentally, I was reminded that the SVID mumbles something about setuid() making use of the original uid/gid's of the process. Might this mean that (some versions of) System V and the SVID are different in these details? If so, what's the scoop? I dimly recall a discussion here on the subject. rayan ps: to make this educational, here's a method using one too many fork()'s: if ((pid = fork()) == 0) { /* child */ (void) setuid(uid); if (open(file, 0) < 0) _exit(errno) _exit(0); } else if (pid < 0) { sorry, we can't check permissions right now... return; /* assume bad guy */ } (void) wait(&status); if (status > 0) return; /* permission denied */ ...open file, etc... but this is really really really silly.