ccement@rivm.UUCP (Martien F v Steenbergen) (02/16/88)
According to the (System V) manuals from AT&T, Uniq, Nuxi and Xenix the chapter about the setuid(2) system call lists: "...<Setuid> will fail if the real user ID of the calling process is not equal to <uid> and its effective user ID is not super-user. [EPERM]..." If this is true, then the last command in the following sequence should be unsuccessful (assuming the use of legal user IDs): $ pr -n -t setuidbug.c 1 extern int errno; 2 3 main() 4 { 5 errno = 0; 6 if (setuid(100) == -1) 7 perror("setuid"); 8 return 0; 9 } $ make setuidbug cc -O setuidbug.c -o setuidbug $ chmod u+s setuidbug $ id uid=100(jim) gid=101(cce) $ ...at this time jim logs out and john logs in... $ ls -l setuidbug -rwsr-xr-x 1 jim cce 3295 Feb 16 09:04 setuidbug $ id uid=139(john) gid=171(pharm) $ setuidbug $ This last setuidbug call should result in something like: setuid: Not owner but it doesn't. So there's either a bug in Unix or in the manuals (or in me?). (This bug won't do you any harm, it results in a no op.) Comment please. Martien. ________________________________________________________________ Martien F. van Steenbergen National Institute of Public Health and Environmental Protection dept. RIVM/CCE PO Box 1 3720 BA Bilthoven The Netherlands tel: (31) 30 742819 email: ...!mcvax!rivm!martien ___________________________MSDOSN'T_____________________________
rikki)) (02/18/88)
From article <679@rivm05.UUCP>, by ccement@rivm.UUCP (Martien F v Steenbergen): > > According to the (System V) manuals from AT&T, Uniq, Nuxi and > Xenix the chapter about the setuid(2) system call lists: > > "...<Setuid> will fail if the real user ID of the > calling process is not equal to <uid> and its effective > user ID is not super-user. [EPERM]..." > The paragraph right before the above says: "If the effective user ID of the calling process is not super-user, but the saved set-user ID from exec(2) is equal to uid, the effective ID is set to uid." By having the setuid bit on in the executable, you are forcing the job to run as jim (effective ID = 100) which is equal to <uid>. Looks like it does what it should to me. -- Rikki Welsh Centel Information Systems 5515 Security Lane, Rockville, Maryland, 20852, (301) 984-3636 UUCP: decuac!macom1!rikki
jonl@sco.COM (ScoMole #192-1232A) (02/20/88)
+-I seem to recall ccement@rivm.UUCP (Martien F v Steenbergen) writing: | | According to the (System V) manuals from AT&T, Uniq, Nuxi and | Xenix the chapter about the setuid(2) system call lists: | | "...<Setuid> will fail if the real user ID of the | calling process is not equal to <uid> and its effective | user ID is not super-user. [EPERM]..." | | If this is true, then the last command in the following sequence | should be unsuccessful (assuming the use of legal user IDs): | | < short program and exmaples deleted > | | Comment please. | | Martien. Hmm. I tried out your example, and it appears that only one's effective uid must be equal to "uid" in 'setuid (uid)', and the chmod u+s on the executeable set that to be true. It seems to me that this is how it should work and the documentation should be changed. off hand, i don't see any kind of security problem with only checking for the effective uid instead of the real uid. After all, who really needs to set their uid to what it already is? if a fish's eye was a telephone pole, it would swim lopsided. =============================================================================== jon luini || WORK: 408-425-7222 || HOME: 408-423-2917 Disclaimer|| You don't think SCO would agree with THAT, do you????? Work: || jonl@sco.com || ...!{uunet, ihnp4, ucbvax!ucscc}!sco!jonl Evil: || niteowl@ssyx.ucsc.edu || ...!{ucbvax}!ucscc!ssyx!niteowl ===============================================================================
bsteve@occrsh.ATT.COM (02/23/88)
The program gives the expected response on my 3b2 running SVR3.1. Could this be a bug from a previous release or a bug in a particular vendor kernel implementation? Steve Blasingame ihnp4!gorgo!bsteve (bsteve@gorgo.att.com) AT&T Itasca, Illinois (312) 250-5376
igb@Fulcrum.BT.CO.UK (Ian G Batten) (03/15/89)
Should the following program work or not, on System Five? This is a
common idiom in the source code of HoneyDanber uucp, and two local System
Five machines refuse to honour the second setuid. The manual page implies
they should. Please, no flames --- just mail me an answer. I've been
sweating blood over the code all day and I hope I can lodge this as a
kernel problem.
ian
main ()
{
int uid, euid;
printf ("uid = %d; euid = %d\n", uid = getuid (), euid = geteuid ());
if (setuid (uid) != 0)
perror ("setuid (uid)");
printf ("uid = %d; euid = %d\n", getuid (), geteuid ());
if (setuid (euid) != 0)
perror ("setuid (euid)");
printf ("uid = %d; euid = %d\n", getuid (), geteuid ());
}
--
Ian G Batten, BT Fulcrum - igb@fulcrum.bt.co.uk - ...!uunet!ukc!fulcrum!igb
les@chinet.chi.il.us (Leslie Mikesell) (03/18/89)
In article <123@cat.Fulcrum.BT.CO.UK> igb@Fulcrum.BT.CO.UK (Ian G Batten) writes: >Should the following program work or not, on System Five? This is a >common idiom in the source code of HoneyDanber uucp, and two local System >Five machines refuse to honour the second setuid. The manual page implies >they should. Please, no flames --- just mail me an answer. I've been >sweating blood over the code all day and I hope I can lodge this as a >kernel problem. >main () >{ > int uid, euid; > > printf ("uid = %d; euid = %d\n", uid = getuid (), euid = geteuid ()); > if (setuid (uid) != 0) > perror ("setuid (uid)"); > printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); > if (setuid (euid) != 0) > perror ("setuid (euid)"); > printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); >} If your current effective uid is 0 and you execute setuid(anything_but_0) then there is no way back. Other combinations of different uid and euid can flip back and forth as desired. You have to fork off a child process if you are root and want to do something as another id and go back to being root (or just assume that root's permissions are sufficient anyway and chown() any files that you create..) Les Mikesell
dwd@cbnewsc.ATT.COM (david.w.dykstra) (03/21/89)
From article <123@cat.Fulcrum.BT.CO.UK>, by igb@Fulcrum.BT.CO.UK (Ian G Batten): - - Should the following program work or not, on System Five? This is a - common idiom in the source code of HoneyDanber uucp, and two local System - Five machines refuse to honour the second setuid. - - main () - { - int uid, euid; - - printf ("uid = %d; euid = %d\n", uid = getuid (), euid = geteuid ()); - if (setuid (uid) != 0) - perror ("setuid (uid)"); - printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); - if (setuid (euid) != 0) - perror ("setuid (euid)"); - printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); - } This works on my System V 3.2.1 system only if the program is not set-uid to root. If it is set-uid to something else (like uucp in the HoneyDanber stuff) then it works. I'm not sure why it shouldn't work for root. - Dave Dykstra AT&T Bell Labs, Skokie, IL att!ttrdf!dwd
jeffj@pedsga.UUCP (03/21/89)
In Message-ID: <123@cat.Fulcrum.BT.CO.UK>, Ian G Batten asks: >Should the following program work or not, on System Five? This is a >common idiom in the source code of HoneyDanber uucp, and two local System >Five machines refuse to honour the second setuid. The manual page implies >they should. Please, no flames --- just mail me an answer. I've been >sweating blood over the code all day and I hope I can lodge this as a >kernel problem. > >ian > >main () >{ > int uid, euid; > > printf ("uid = %d; euid = %d\n", uid = getuid (), euid = geteuid ()); > if (setuid (uid) != 0) > perror ("setuid (uid)"); > printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); > if (setuid (euid) != 0) > perror ("setuid (euid)"); > printf ("uid = %d; euid = %d\n", getuid (), geteuid ()); >} >-- Sounds like a kernel bug to me. A problem setting the SAVED SET-UID to be precise. Let me explain: Assuming this is not run as UID 0, let's look at the manual. A process has a REAL UID that identifies the person running the process. Only root can change this, so this is invariant. The EFFECTIVE UID determines the permissions. It is the same as the REAL UID, unless the SET UID bit is on, then the EFFECTIVE UID is that of the file. The SAVED SET-UID is the effective UID of the process before an exec(). If the previous process was not SET-UID, the SAVED-SET UID is the same as the effective UID. This is to allow the effective UID to alternate between the real UID and its previous value. So, setuid() as a non-root allows the process to set the EFFECTIVE UID to the REAL UID, or the SAVED UID. Let's say this a.out has no set-uid. This runs okay, telling me uid=euid=44 all the time. Now try this a.out set-UID 44, run it as UID 33. The output is REAL EFFECTIVE 33 44 33 33 33 44 The first setuid sets the effective UID from 44 to the real (33). Now you want to set it back. The secret hidden SAVED SET-UID holds the UID 44, so the second call succeeds. Unless, of course, this was exec'd from something set-UID something-not-UID 44. Perhaps crash(1M) displays the saved set-uid? Perhaps the saved-uid was erroneously set to the real UID? __________ UN*X UNIX (ver 6, ver 7, PWB, Sys III, Sys V) AIX BSD (4.0, 4.1, 4.2, 4.3) MINIX REGIS RTU T/PIX ULTRIX UTS VNIX XENIX XINU your-version-here Jeffrey Jonas INTERNET: jeffj@pedsga.tinton.ccur.com USENET: allegra!io!mtune ---------> petsd!pedsga!jeffj decvax!mcnc!rutgers _____/
stevea@laidbak.UUCP (Steve Alexander) (03/22/89)
In article <822@pedsga.UUCP> jeffj@pedsga.UUCP writes: >Perhaps the saved-uid was erroneously set to the real UID? I believe that if the current effective id is root, the saved set-uid is set to the new uid along with the effective uid and the real uid when the setuid() is done. Thus, the following will not work: root -> user -> root This is only true for effective uid 0. Otherwise, the saved set-uid is left alone. For non-zero uid's, the setuid() proceeds if the new uid is equal to either the real uid or the saved set-uid. -- Steve Alexander, TCP/IP Development | stevea%laidbak@sun.com Lachman Associates, Inc. | ...!sun!laidbak!stevea
guy@auspex.UUCP (Guy Harris) (03/24/89)
>This works on my System V 3.2.1 system only if the program is not >set-uid to root. If it is set-uid to something else (like uucp in the >HoneyDanber stuff) then it works. I'm not sure why it shouldn't work >for root. It shouldn't work for root because they decided not to make it work for root. The problem is that "setuid" can mean two things: 1) "I'm running set-UID, but want to change back - possibly temporarily - to my real UID, and then be able to change to my original set-UID effective UID again;" 2) "I'm a program such as 'login', and am running as root; I want to set the user ID for a newly created session - real, effective, and original set-UID effective UIDs - to some value." (The "original set-UID effective UID" is generally referred to as something like the "saved set-user ID" in S5 documentation.) Instead of providing new calls based on the 4.2BSD "setreuid" call - that call can independently set the real and effective UIDs, and can be told to leave one of the UIDs alone by supplying -1 as an argument - they overloaded "setuid". They did so by making it act differently for an effective UID of 0 (or maybe it was real UID, our S5R3 sources aren't on-line at the moment) than for other effective UIDs. I suspect S5R4 and 4.4BSD may end up following the SunOS lead on this one; "setreuid" was enhanced to support an S5-style "saved set-user ID", so that you can do the following in a set-UID program: ruid = getuid(); euid = geteuid(); <stuff with the effective user ID equal to the set-user ID> seteuid(ruid); <stuff with the effective user ID equal to the real user ID> seteuid(euid); <stuff with the effective user ID equal to the set-user ID> regardless of whether the effective or real user ID is 0 or not. Both BSD and S5 flavors of "setuid" can be implemented atop "setreuid".
davidsen@steinmetz.ge.com (Wm. E. Davidsen Jr) (03/24/89)
The setuid behavior gets to be a real pain in the case where a program is running setuid (not root) and needs to run another program to perform some task. The execed program runs with its uid and euid set to the uid rather than the euid, and there's no reasonable way to change this, such as setuid(geteuid()) in BSD. I hit this all the time on a BBS, where the bbs program runs setuid to the BBS uid, and a file transfer using a protocol program is to be done. I found a way by it, but it's ugly, and the only thing in the whole system which requires root permission (to install not run). -- bill davidsen (wedu@crd.GE.COM) {uunet | philabs}!steinmetz!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/24/89)
In article <1196@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >Both BSD and S5 flavors of "setuid" can be implemented atop "setreuid". I don't think the "saved set-UID" feature can be emulated using setreuid(). Ron Natalie and I looked into this a few years ago and decided that a simple semantic extension to setreuid() could be made that would enable full emulation of saved set-UID, and that our extension would not cause any new security holes. However, we never got around to it and I have since forgotten the details. Maybe for 4.4BSD?
aeh@j.cc.purdue.edu (Dale Talcott) (03/25/89)
> It shouldn't work for root because they decided not to make it work for > root. Does anyone know what security holes are plugged by this behavior? We have some applications where it would be nice to be able to bounce back and forth between root and a given user. Before I change the kernel, though, it would be prudent to know what I'm letting us in for. From looking at the source, it seems as if the only processes which end up with curtailed permissions because of the SYS V behavior are the current process (which has root permission already until it setuid()'s to something else) and its children, until they exec(). Protecting one part of a program from other parts of itself doesn't make sense to me, so there must be a backdoor I am missing. Can someone shed some light? Dale Talcott, Purdue University Computing Center aeh@j.cc.purdue.edu, j.cc.purdue.edu!aeh, aeh@purccvm.bitnet
les@chinet.chi.il.us (Leslie Mikesell) (03/26/89)
In article <13416@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes: > > The setuid behavior gets to be a real pain in the case where a program >is running setuid (not root) and needs to run another program to perform >some task. The execed program runs with its uid and euid set to the uid >rather than the euid, and there's no reasonable way to change this, such >as setuid(geteuid()) in BSD. I've had similar problems trying to bundle files with cpio and using uux to restore them at other sites. The problem is that cpio runs /bin/mkdir (even under SysVr3 where it doesn't have to) to create any needed directories, and /bin/mkdir decides that the owner should be the real uid. The real uid of uux is likely to be anyone who recently sent mail, so the next time something is delivered to that directory, uux (same euid, different real uid) can't write there. The only way I can make this work without putting setuid programs on other people's machines is to make sure all the directories are writable by everyone before cpio'ing them. Les Mikesell
les@chinet.chi.il.us (Leslie Mikesell) (03/26/89)
In article <9915@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>Both BSD and S5 flavors of "setuid" can be implemented atop "setreuid". >I don't think the "saved set-UID" feature can be emulated using setreuid(). >Ron Natalie and I looked into this a few years ago and decided that a >simple semantic extension to setreuid() could be made that would enable >full emulation of saved set-UID, and that our extension would not cause >any new security holes. How about a 3-argument function to set effective, real, and saved set-uid that is only allowed for root. Then a process running as root could start a child which would be allowed to flip between two different ids, neither required to be 0. Les Mikesell
guy@auspex.UUCP (Guy Harris) (03/26/89)
>>Both BSD and S5 flavors of "setuid" can be implemented atop "setreuid". > >I don't think the "saved set-UID" feature can be emulated using >setreuid(). OK, let me state it better, making explicit an implicit part of my statement: Both BSD and S5 flavors of "setuid" can be (and have been) implemented atop "setreuid" *if you put the saved set-UID feature into your system in the fashion described in my article in the parts preceding the statement.* This isn't emulating the saved set-user ID feature using a vanilla "setreuid"; it's emulating both the BSD and S5 behaviors of "setuid" atop a "setreuid" that works with a saved set-user ID feature already in the system. >Maybe for 4.4BSD? As I said, they may end up picking up a SunOS-style "saved set-user ID" implementation (as I presume S5R4 will).
chris@mimsy.UUCP (Chris Torek) (03/26/89)
>In article <1196@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >>Both BSD and S5 flavors of "setuid" can be implemented atop "setreuid". In article <9915@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >I don't think the "saved set-UID" feature can be emulated using setreuid(). If you are willing to substitute your own getuid(), geteuid(), and access() for the `real' versions, it can. (Obviously you also have to substitute setuid and seteuid.) In any case, Mike K. has talked about having 4.4 have `saved setuid done right'. The real problem with the SysV version is that it overloads setuid(), and can tell `set all IDs including saved effective uid' from `set real and effective uid' only when the caller is not root. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guy@auspex.UUCP (Guy Harris) (03/27/89)
>Does anyone know what security holes are plugged by this behavior? Are you assuming the reason that behavior was specified was to plug security holes? As far as I know, there *aren't* any security holes plugged by that behavior, and that the reason it was specified wasn't security - it was backwards compatibility with programs such as "su" that ran set-UID "root" and that used "setuid" to set the effective *and* real UIDs to that of the specified user; those programs were trying to create a new environment with that UID, and would want to set all the UIDs, including the saved set-user ID, to the specified value. >Protecting one part of a program from other parts of itself doesn't make >sense to me, so there must be a backdoor I am missing. Why do you assume that there is such a backdoor, or that you're missing something? Perhaps it was System V that was missing something, namely a procedure that can be told explicitly to set only the effective UID or to set all the UIDs for a process.
rml@hpfcdc.HP.COM (Bob Lenk) (04/05/89)
As numerous folks have said, the saved ID is overwritten when the euid of the calling process is 0. Also, in System V Release 2 (all versions that I know of) a call to setuid(0) was never honored for a non-superuser, even if the saved uid is 0. This was not documented, and I never understood or ascertained a good reason for this, and it was apparently changed in release 3. This could explain why one System V port did not work the same as another. Bob Lenk hplabs!hpfcla!rml rml%hpfcla@hplabs.hp.com