Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!bionet!agate!ucbvax!network!ucsd!orion.cf.uci.edu!uci-ics!zardoz!ccicpg!cci632!rit!tropix!moscom!ur-valhalla!uhura.cc.rochester.edu!rochester!rutgers!cs.utexas.edu!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.xenix Subject: getting it straight this time? (was: Setuid(geteuid()), help) Keywords: what do you think of it, Chris? Message-ID: <2778@kappl.cs.vu.nl> Date: 22 Jul 89 08:37:36 GMT References: <197@ajfcal.UUCP> Organization: V.U. Informatica, Amsterdam, the Netherlands Lines: 54 Let's return to the original article. tony@ajfcal.UUCP (Tony Field) wrote: \... \I have a shell script that is running an effective uid of "news". The \script calls a process that has a real uid of a "user". The process can \create directories with mkdir that belong to "user", however it cannot \create a file. \ \If the process is setuid to root, then I can create the directores and \the files, however the owner becomes "root", and I would prefer the \owner be "news". Apparently the current directory is unwritable for `news'. Yet Tony wants to create files and directories owned by that very uid. We conclude: the directory should be writable for `news'. Letting `root' create the entries and chown()ing them is a kludge. On the other hand we don't want to `chmod 777'. The solution seems to be: make the directory writable for the GROUP `news' and let the shell script run SETUID `news' AND SETGID `news'. But wait! If we want to make a directory, our effective uid of `news' still gets overwritten by 0, because /bin/mkdir is setuid root. Right. We can solve this by invoking a setuid root wrapper, ONLY executable for the GROUP `news'. (Yup, another kludge. Who sees a way out?) This wrapper will set the real uid to `news', and execute the specified command in turn. In our problem we only want to execute /bin/mkdir, but it's good practice to set things up in a more general fashion: #define NEWS 6 /* uid of news */ main(argc, argv) int argc; char **argv; { if (argc == 1) exit(0); if (setuid(NEWS) == -1) { /* eff. gid is still `news' */ perror("setuid"); exit(1); } execvp(argv[1], &argv[1]); perror(argv[1]); exit(1); } Invoke like: $ donews mkdir foo bar baz or execl("donews", "donews", "mkdir", "foo", "bar", "baz", (char *) 0); Boy, does SysV miss setuid(geteuid()) and mkdir(2)! :-( -- "I HATE arbitrary limits, especially when |Maarten Litmaath @ VU Amsterdam: they're small." (Stephen Savitzky) |maart@cs.vu.nl, mcvax!botter!maart