Awatmath.1423 net.unix-wizards utzoo!decvax!watmath!dmmartindale Sat Jan 9 23:40:59 1982 Re: changing user id's (from Lauren) Re Lauren's query about changing userids: We have had a schizo() call which simply swapped real and effective userids for years, and I've always thought it was a little ugly, because spoolers which caught SIGINT and quit always had to do something like: interrupt() { unlink(cfile); schizo(); unlink(cfile); ..... because they didn't know which id they were running as. I also decided that it would be very nice if a process running with an effective uid of 0 could turn itself into an arbitrary user temporarily in order to access a file, and then turn back into root (this is invaluable for deamons on systems which try to be secure.) The solution I finally came up with is this: I added two additional entries to the U area called u.u_euid and u.u_egid. (Think of them as exec-time uid/gid). They are set to u.u_uid and u.u_gid in exec once it has done all the checking for setuid/setgid and decided what the final uid/gid will be. Then I have two new system calls: schizo() { struct a { int flag; }; if (((struct a *)u.u_ap)->flag) { u.u_uid = u.u_ruid; u.u_gid = u.u_rgid; } else { u.u_uid = u.u_euid; u.u_gid = u.u_egid; } } become() { register struct a { int uid; int gid; } *uap; uap = (struct a *)u.u_ap; if(u.u_euid == 0) { /* must check euid rather than uid */ u.u_acflag |= ASU; u.u_uid = uap->uid; u.u_gid = uap->gid; return; } else u.u_error = EPERM; } A process can "turn itself into" the uid/gid which invoked it by doing a schizo(1), and return to its setuid permissions later with schizo(0). I use this in spoolers which must be setuid to access a protected spool area, yet must temporarily revert to the user's permissions in order to do a getwd() or to access a user's file (no more need for access(), and if you creat a file, it is automatically owned by the correct person). The call is unprivileged, since anything you can do via it could also be done (much more clumsily) by a sequence of pipe(), fork(), setuid(getuid()), etc. The become(uid, gid) sys call allows a process which is setuid to root (or invoked by root, such as from /etc/rc) to "become" an arbitrary user/group id at any time. Spoolers can put the uid, gid, and umask of whoever invoked them into a control file and when a daemon starts processing that control file, it can set its uid, gid, and umask to these whenever it wishes to open, creat, or unlink a file as directed by the user. This scheme has an advantage over the setid() call discussed by Alan Watt in that the ruid/rgid are never touched and are thus always correct, which is important if you do process accounting since they get written to the accounting file (and passed on to children). Dave Martindale (watmath!dmmartindale) ----------------------------------------------------------------- gopher://quux.org/ conversion by John Goerzen of http://communication.ucsd.edu/A-News/ This Usenet Oldnews Archive article may be copied and distributed freely, provided: 1. There is no money collected for the text(s) of the articles. 2. The following notice remains appended to each copy: The Usenet Oldnews Archive: Compilation Copyright (C) 1981, 1996 Bruce Jones, Henry Spencer, David Wiseman.