[net.bugs.4bsd] A hidden gotcha in SCCS on non SYSIII or SYSV systems.

clewis@mnetor.UUCP (Chris Lewis) (06/12/85)

To all you people using SCCS on a non-SYSIII, SYSV or PWB system.
SCCS is relying upon a hidden "feature" of "setuid" for its operation.

Description:
	In the SV kernel, when the user exec's a setuid program, the
	kernel remembers this fact and propagates the id of the program
	to the children, I think... (during forks).  It certainly
	does it to the program that was the setuid program.
	Then, if the program or child setuids to the real userid, 
	the SV kernel will ALSO let him setuid back to the effective 
	id of the setuid program.

	Get -e uses something like:

		lock(z.file)	(creates z.file, using effective id)
		holdid = geteuid();
		setuid(getuid());
		...
		do the get -e
		...
		setuid(holdid);
		unlock(z.file); (attempts to unlink, effective=realid)

	Of course, the "unlock" fails on a V7 or BSD system (or a Pyramid
	in either universe).

	Normally this is not a problem, because get is running:
	real = effective = user's id

	However, if "get" is being run setuid (so that you can cross
	userid boundaries for multiple userid projects), the unlink
	will fail, and the z.file will be left lying around.

	This "feature" is not documented in AT&T setuid(2), but it
	is easy to see in the kernel sources.

	(note: this may or not be a dramatic security hole depending
	upon what the kernel sets it to the first time.  Make
	sure that /etc/init is not setuid!)

Repeat-by:
/*	
	cc -o setutest setutest.c
	chown somebody setutest
	chmod 6755 setutest
	su somebody else
    Then run this program (in a directory owned by "somebody").  on an 
    AT&T system, the file "setu" is created then deleted.  On a 
    BSD system (and pyramid att universe) "setu" is created but NOT deleted
*/
main() {
	/* here I am really you, effectively somebody else */
	int fd;
	int oldu;
	oldu = geteuid();
	fd = creat("setu", 0444);
	write(fd, "hello", 6);
	close(fd);
	setuid(getuid());
	/* here's the trick, ATT remembers that you were chmod 6755'd,
	   all children are then allowed to setuid BACK to the owner id
	   of the setuid program */
	setuid(oldu);
	printf("On Pyramid and vanilla BSD's this is -1: %d\n", unlink("setu"));
}
-- 
Chris Lewis,
UUCP: {allegra, linus, ihnp4}!utzoo!mnetor!clewis
BELL: (416)-475-8980 ext. 321

mp@allegra.UUCP (Mark Plotnick) (06/13/85)

I suppose this feature is useful, but a hidden gotcha on SYSV
machines is that the kernel doesn't support saved gid's, though SCCS
expects it to.

There's no security problem with children; p.p_suid is set to
u.u_uid upon exec.