[net.bugs.uucp] mkdir

mojo@kepler.UUCP (Morris Jones) (02/07/86)

This is a known problem that was discussed in the 2.10.3 documentation
when I was installing net news.  I've now encountered the problem
under honey danber uucp.

Problem: Directories created by programs running under a user id
	 different from the real user id (suid bit set) are owned
	 by the real user and not the effective user.

	 When honey danber uucico creates a machine directory, its
	 ownership may be the person sending mail to that machine,
	 and uux, running as user "uucp", will not be able to create
	 command and data files.

For the time being, I've commented out the portion of the cleanup
script that erases empty spooling directories.  If the directories
don't have to be created, I won't encounter the problem.  ("Hey
Doc, it hurts when I do this: #*$%&#*%&!").  For the sake of news,
I built a script that finds directories that aren't owned by the
news user and fixes them.

But the news documentation hints at another solution -- building
your own version of mkdir().  Did you do this?  Will you share it
with me?

-- 
Mojo
... Morris Jones, MicroPro Product Development
{lll-crg,ptsfa,dual,well,pyramid}!micropro!kepler!mojo

mdb@laidbak.UUCP (Mark Brukhartz) (02/08/86)

> [...] 
> Problem: Directories created by programs running under a user id
> 	 different from the real user id (suid bit set) are owned
> 	 by the real user and not the effective user.
> 
> 	 When honey danber uucico creates a machine directory, its
> 	 ownership may be the person sending mail to that machine,
> 	 and uux, running as user "uucp", will not be able to create
> 	 command and data files.
> [...] 
> But the news documentation hints at another solution -- building
> your own version of mkdir().  Did you do this?  Will you share it
> with me?

System V allows one to give files and directories away with
chown(). All known versions of UNIX let setuid processes give
up their special permissions.

Together, these make it possible for a setuid command to make
a protected directory within a protected parent. Briefly:

	o Temporarily chmod() the parent directory to 777.

	o Fork and execute mkdir, which will make the new
	  directory and leave it owned by the user of the
	  setuid command (...as opposed to the *owner* of
	  the command, which is what we want).

	o Chmod() the parent directory back to its original
	  (protected) permissions.

	o Fork another child. Have it use setuid(getuid())
	  to relinquish setuid permissions, chown() to give
	  the directory to the setuid ID, and exit.

This requires that the setuid command actually *own* the parent
directory, rather than merely having write access to it. Ownership
is neccessary for chmod(). There is a window in which the parent
directory is mode 777, but it is very small.

Either of two features from the 4.2BSD kernel would avoid these
problems:

	o Allowing one to set the real uid from the effective one
	  with setuid(geteuid()).

	o A mkdir() system call, which avoids all of the real vs.
	  effective uid problems in the first place.

The former is a sufficient solution, and one which I would like
to see in System V. The latter, while useful, does not *really*
have to be in the kernel; hence, it does not belong there.

				Mark Brukhartz
				ihnp4!laidbak!mdb

guy@sun.uucp (Guy Harris) (02/10/86)

> Either of two features from the 4.2BSD kernel would avoid these
> problems:
> 
> 	o Allowing one to set the real uid from the effective one
> 	  with setuid(geteuid()).
> 
> 	o A mkdir() system call, which avoids all of the real vs.
> 	  effective uid problems in the first place.
> 
> The former is a sufficient solution, and one which I would like
> to see in System V.

The former is a *necessary* solution to the protection problems introduced
by S5's looser rules for when a process can send a signal to another
process.  Those rules permit a process to send a signal to another process
iff the real or effective UID of the sending process matches the real or
saved set-UID UID of the receiving process.

Consider a set-UID program like "uucico".  If run as the result of a user
directly or indirectly (e.g., from "mail") running a UUCP job queueing program
like "uucp" or "uux", it runs with the real UID of that user.  This means
that the user can do a "kill -9" on that "uucico" and have it "take".
Furthermore, since "uucico" cannot set its real UID to match its effective
UID (unless it is run as set-UID to "root" and sets them both to the UUCP
account), it cannot protect itself from this.

> The latter, while useful, does not *really* have to be in the kernel;
> hence, it does not belong there.

No.  "mkdir" would have to be grossly hacked-up in order to know, *in
advance*, all the file system types it could be asked to make a directory
on.  (You say that it will only be ased to make a directory on a UNIX file
system?  Try again.  Sun's NFS, for instance, can be implemented on non-UNIX
systems.  Furthermore, the "virtual file system" layer that NFS is built on
top of permits Sun UNIX to support non-UNIX file systems, such as the MS-DOS
file system.  Version 8 has a similar mechanism, although I don't know if it
can support non-UNIX file systems.)

"mkdir" is an abstract operation, just like "creat" is.  The same module
which implements the "create a file" operation - namely, the UNIX kernel, in
present-day UNIX systems - should implement the "create a directory"
operation (which is NOT the same as the "make a node of type directory"
operation; "create a directory" also involves making the "." and ".." links,
at least on UNIX file systems, and may be totally unrelated to a "make a
node" operation on a non-UNIX file system).
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy%gorodish@sun.arpa	(yes, really)

yde@necis.UUCP (David Elins ext. 220) (02/11/86)

In article <495@kepler.UUCP> mojo@kepler.UUCP (Morris Jones) writes:
>Problem: Directories created by programs running under a user id
>	 different from the real user id (suid bit set) are owned
>	 by the real user and not the effective user.
>...
>But the news documentation hints at another solution -- building
>your own version of mkdir().  Did you do this?  Will you share it
>with me?

I never saw this documentation and didn't know that the directory
ownership problem was known.

Anyway, I fixed it on our 2.10.3 news installation and will be
happy to send the fix to anyone who requests it.

By the way, I did not change mkdir, but changed the portion of inews.c
that calls mkdir. On USG systems it was changing the ownership of directories
it created before it actually created the directories.

There was another problem I had to fix also: the expire program supports
a -n option to specify newsgroups that are to be expired. It wasn't parsing
these newsgroups as it had in news 2.10.2, and nothing was being expired.
I don't know if this was a bug or a feature as it could be worked around
by invoking expire with a slightly different syntax (-n newsgroup1,newsgroup2,)
but I will supply that fix too, if anyone wants it.

Now the obligatory question (probably should go to unix-wizards,
but this is my first posting, I don't want to inundate the net):

In fixing the directory ownership problem mentioned above, I noticed
that if a process's effective uid was non-zero but the real uid was
zero (root), a setuid(0) system call failed. The documentation implies
that if the argument to setuid() is the process's real uid, setuid
should succeed (and set the effective uid = the arg = the real uid).
This works as advertised if the real uid is non-zero (e.g. uucp) and
it works as advertised on our system III systems, but not on system V.
I know how to fix it, but I would like confirmation from someone who has
been working with Unix longer than I that this really is a bug and not
an intentional exception, before I do it.


Thanks in advance.

david