chris@mimsy.UUCP (Chris Torek) (03/27/88)
In article <368@wsccs.UUCP> terry@wsccs.UUCP (terry) writes: >... for instance, if mknod() had to be done by root, as the only user >capable of modifying a file system, as is the case in a number of recent >UNIX implimentations. Your "mkdir" command would have to be SUID root, >but still be able to tell who actually ran it. This is precisely the problem. When a setuid program is running and needs to make a new directory, it must (on these systems) run the `mkdir' program. That setuid program's permissions are in fact those of the EFFECTIVE user, not the real user; but mkdir will check only the permissions of the real user. Often this is not what is desired. Example: % ls -l foo -rwsr-xr-x 1 jane misc 12345 Mar 26 14:27 foo % cat foo.c ... int mkdir(dirname) /* not quite right */ char *dirname; { char buf[1000]; (void) sprintf(buf, "/bin/mkdir %s", dirname); if (system(buf) == 0) return (0); errno = EPERM; /* wrong! must scan output from /bin/mkdir */ return (-1); } ... realuser = uid_to_name(getuid()); if (chdir("/tmp/jane/foousers") < 0) ... if (stat(realuser, &st) < 0 && errno == ENOENT) err = mkdir(realuser); ... % ls -ldg /tmp/jane/foousers drwxr-xr-x 3 jane misc 512 Mar 25 17:34 foousers % whoami joe % ./foo mkdir: joe: Not owner (or is it Permission denied?) % There is a way around it, but it is ugly: if (stat(realuser, &st) < 0 && errno == ENOENT) { /* BEGIN mkdir */ int pid, w, status; switch (pid = fork()) { case -1: /* error */ ... case 0: /* child */ (void) setgid(getgid()); (void) setuid(getuid()); _exit(mkdir(realuser) == 0 ? 0 : errno); /*NOTREACHED*/ default: /* parent */ while ((w = wait(&status)) != pid) if (w == -1) uh oh. break; } err = status == 0 ? 0 : -1; if (err) errno = status >> 8; /* END mkdir */ } The above can be done. It just is not done often enough. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
les@chinet.UUCP (Leslie Mikesell) (03/27/88)
In article <10811@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >>UNIX implimentations. Your "mkdir" command would have to be SUID root, >>but still be able to tell who actually ran it. > >This is precisely the problem. When a setuid program is running >and needs to make a new directory, it must (on these systems) run >the `mkdir' program. That setuid program's permissions are in >fact those of the EFFECTIVE user, not the real user; but mkdir >will check only the permissions of the real user. Often this is >not what is desired. Example: > Real-life example: I have a subdirectory tree that I need to duplicate on another machine via uucp. To save transmission time, I like to use: find . -print |cpio -oc |compress | uux - "remote!unpackit" where remote is the machine name and unpackit is a shell script that goes to the right place and runs zcat|cpio -imd on its input. Now, one would think that these files and directories would be owned by uucp since uuxqt is setuid to uucp. However, if the particular run of uucico that delivered the batch was started by a user on the remote machine, guess who owns the newly created directories... Cpio uses system(mkdir) which gives the directory to the real user which happens to be the one who originally started the process (even in SysVr3 where it doesn't have to!). Even if the first run operates as uucp (due to our system logging in to deliver the file) later attempts may fail due to incorrect permissions when creating a new dirctory. -Les ...ihnp4!chinet!les
james@bigtex.uucp (James Van Artsdalen) (03/28/88)
IN article <4190@chinet.UUCP>, les@chinet.UUCP (Leslie Mikesell) wrote: > Cpio uses system(mkdir) which gives the directory to the real > user which happens to be the one who originally started the process > (even in SysVr3 where it doesn't have to!). /bin/mkdir on my SysVr3 system isn't suid to anything. Hence I assume it works by creating directories via mkdir(2) and then giving them away to the real uid and gid. I don't think much would break if you replaced /bin/mkdir with one that didn't give away the resulting directory. -- James R. Van Artsdalen ...!uunet!utastro!bigtex!james "Live Free or Die" Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746
samperi@marob.MASA.COM (Dominick Samperi) (03/28/88)
In article <4190@chinet.UUCP> les@chinet.UUCP (Leslie Mikesell) writes: |>Real-life example: |>I have a subdirectory tree that I need to duplicate on another machine |>via uucp. To save transmission time, I like to use: |>find . -print |cpio -oc |compress | uux - "remote!unpackit" |> where remote is the machine name and unpackit is a shell script |> that goes to the right place and runs zcat|cpio -imd on its input. |> |>Now, one would think that these files and directories would be owned |>by uucp since uuxqt is setuid to uucp. However, if the particular |>run of uucico that delivered the batch was started by a user on the |>remote machine, guess who owns the newly created directories... |>Cpio uses system(mkdir) which gives the directory to the real |>user which happens to be the one who originally started the process |>(even in SysVr3 where it doesn't have to!). Even if the first |>run operates as uucp (due to our system logging in to deliver the |>file) later attempts may fail due to incorrect permissions when |>creating a new dirctory. |> -Les |> ...ihnp4!chinet!les This is precisely the problem that motivated me to write the (slightly) enhanced version of mkdir that I recently posted to comp.unix.wizards. It has a -g flag which causes mkdir to use the process EFFECTIVE group id when it makes directories. You will have to modify cpio so that it calls mkdir with the -g flag, and so that it always gives rwx access to a particular group, like uucpio. -- Dominick Samperi, Manhattan College, NYC manhat!samperi@NYU.EDU ihnp4!rutgers!nyu.edu!manhat!samperi philabs!cmcl2!manhat!samperi ihnp4!rutgers!hombre!samperi (^ that's an ell) uunet!swlabs!mancol!samperi
zeeff@b-tech.UUCP (Jon Zeeff) (03/30/88)
Other than the correct fix of adding a system call, the way that News (2.11) uses is the only way I've seen of creating proper directories from a suid program. --Jon -- Jon Zeeff Branch Technology, uunet!umix!b-tech!zeeff zeeff%b-tech.uucp@umix.cc.umich.edu