[net.unix-wizards] hazards of linking directories

trb@masscomp.UUCP (10/05/84)

First, the experience of one of our customers, second, my experience
of the past two days.

One of our customers typed:

	% lpr /

Sounds harmless enough, right?  Lpr is a spooler which links the file
you printed (root here) into /usr/spool/lpr/<linktofile>.  Lpr is
setuid to root because it has to be able to link people's protected
files to its spool directory for later printing.

When lpr tried to unlink <linktofile>, it couldn't, of course, because
it was a directory and there were (lots of) files in it.  So lpr left
it there.  Later that evening, the customer's cron entry which cleans
up the file systems looked for orphaned files in the spool directories,
assumed to be left by glitches such as system crashes.  It did an rm
-rf /usr/spool/lpr/<linktofile> and yes, you guessed it.  The next
morning, there were no (count 'em) files left in the file system.

Second, my experience.

I had been having trouble lately with cpio, files were allegedly being
written, but I couldn't find them.  I know for a fact that if a cpio
input stream is at all in error, cpio gets checksum and phase errors.
No such luck here, the files were just not showing up, though cpio
claimed to be writing them.

I put debugging statements all through cpio, and sure enough, it was
writing all my files, with valid counts, valid names, creating the
directories, and not unlinking anything it shouldn't have.

Finally, I decided to grep through my nightly find / -print logs.  The
file, /install/foo, showed up in /usr/src/install/foo.  Oh no.  Here's
what happened:

A few months ago, being short on disk space, I decided that I would
link /usr/src/uts/h to /usr/include, and save myself 1200 blocks.
This required setuid privs to link the directories, but being of the
age of consent, I did it.  Now, as cpio goes depositing files in a
tree, it climbs the tree by itself using a cd routine, rather than
depositing each file from the root.  So cpio puts some files in
/usr/include, cd's to ../.., which it thinks is root, but is actually
../.. relative to /usr/src/uts/h, that being /usr/src.  Poof.

To quote from the System V manual:

	Link and unlink perform their respective system calls on their
	arguments, abandoning all error checking.  These commands may
	only be executed by the super-user, who (it is hoped) knows
	what he or she is doing.

Might this have some effect on systems that have symbolic links to
directories?  Symbolic links (4.2) and cpio (System N) have been
pretty mutually exclusive, but it's worth a thought.

	Andy Tannenbaum   Masscomp Inc  Westford MA   (617) 692-6200 x274

clyde@ut-ngp.UUCP (Clyde W. Hoover) (10/05/84)

The moral is: programs that do such linking shouuld CHECK what kind
of files their arguments are and reject those that are not ordinary files.
-- 
Shouter-To-Dead-Parrots @ Univ. of Texas Computation Center; Austin, Texas  
"Let's show this prehistoric bitch how we do things downtown"
	clyde@ut-ngp.ARPA, clyde@ut-sally.ARPA
	...!ihnp4!ut-ngp!clyde, ...!allegra!ut-ngp!clyde

jbn@wdl1.UUCP (jbn ) (10/06/84)

     This is a strong argument against running utilities such as the
line printer spooler as ``setuid to root''.  Such programs should
open the file of interest while running as the requestor and then
exec a second program which is set-uid to a service user id which owns
the spooling directory, after which a copy can be performed.  This
is a little more complex but much safer.

wls@astrovax.UUCP (William L. Sebok) (10/07/84)

1) In 4.2 BSD the sequence 
	ln -s directory linkfile
	rm -rf linkfile
 will delete the symbolic link "linkfile" but leave directory "directory" and 
 its children intact.

 Thus:
	ln -s / linkfile
	rm -rf linkfile

 is perfectly safe.

2)
> A few months ago, being short on disk space, I decided that I would
> link /usr/src/uts/h to /usr/include, and save myself 1200 blocks.
> This required setuid privs to link the directories, but being of the
> age of consent, I did it.  Now, as cpio goes depositing files in a
> tree, it climbs the tree by itself using a cd routine, rather than
> depositing each file from the root.  So cpio puts some files in
> /usr/include, cd's to ../.., which it thinks is root, but is actually
> ../.. relative to /usr/src/uts/h, that being /usr/src.  Poof.
>	.... 
> Might this have some effect on systems that have symbolic links to
> directories?  Symbolic links (4.2) and cpio (System N) have been
> pretty mutually exclusive, but it's worth a thought.
> 	Andy Tannenbaum   Masscomp Inc  Westford MA   (617) 692-6200 x274

Yes, in the presence of symbolic links one cannot assume that
	cd directory
	cd ..
will bring you back to where you started.  Programs just have to keep this
in mind.  In general one probably wants an option anyway in one's tape archiving
program whether or not to follow a symbolic link.  Otherwise many directory
subtrees will get dumped twice.

I consider neither of these two points a security issue.

I have found symbolic links to directories an extremely nice thing to have.
It gives a system manager a great deal more flexiblity in where to put things.
For example, when I get some wonderful new software but filesystem /usr/src
is full I can place it somewhere on the big user filesystem /mnt and place
a symbolic link on /usr/src to it.  That way it can be still found by someone
expecting to find it in /usr/src.  When the disk in which /usr/lib/news
resided began to go back and give extremely strange news core dumps I used
a symbolic link to place this directory on another disk and verify that
indeed it was the disk at fault.
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,noao,princeton,vax135}!astrovax!wls

guy@rlgvax.UUCP (Guy Harris) (10/09/84)

> But, more seriously: a line printer spooler that "spools" by
> LINKING the print file into the spool directory??? What if you
> make changes in the file between the queue time and the time it
> is actually printed? When I say "lpr foo" I assume that "foo" is
> conceptually being printed RIGHT NOW, and that the spooling
> mechanism exists only to make efficient use of a resource (the
> printer). I'd feel free to modify the file, secure in the
> knowledge that it would be printed in its original form.
> 
> Is this the standard System V printer spooler that does this?
> I understand the problem if you are running XENIX with floppy
> disks, but hopefully a REAL system spooler would never do this...

The spooler that comes with V7 and System III does this linking; it's
sort of a halfassed idea, considering it only works for files on the
same filesystem as the spool directory.

Most of the time when I'm printing something, it's the output of a program
so "lpr" had to read its standard input pipe and squirrel away a copy of
the file anyway.  Since the UNIX spooler doesn't do any pagination (which
it shouldn't do), I always use "pr" when printing files, so the original
copy isn't what's being printed.  If it's a document, either it's coming
from "nroff" or it's coming from our office automation system; in either
case it's a piped copy getting squirreled away.

Sometimes, you're printing such a huge job that it won't fit on /usr/spool,
in which case a strategy like storing the name of the file in the queue,
or making a symbolic link, is the only way to print the job (short of
seizing the printer and doing "cat file >/dev/lp").

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

lat@stcvax.UUCP (Larry Tepper) (10/10/84)

We have an 11/70 running V7 here.  Response on the system was
bad enough, and our users were getting frustrated having to wait
minutes just because they needed something like:

	pr *.c | lpr				or
	tbl bunch of files | nroff -ms > output; lpr output

So, we basically rewrote lpr, lpd (and added lpf, the filter which
does the real printing) to our V7 system.  We don't link to files,
but rather put the full pathname of each file into the daemon control
file.  I added a flag so that the line printer filter will do simple
pagination of files (as in the example above, but no columnation).
The line printer filter (lpf) has to be a root-owned setuid program.
Shortly after it starts up, it sets its uid/gid to the originator of
the printing job (using the owner and group of the daemon control
file for the job).  The system also handles multiple printers
and will print over our network (we've been running 3-COM's UNET
for years; and we have a ton of pdp-11's here).

Identical code runs on our 4.1 BSD systems.

I won't apologize to purists who insist that the line printer
shouldn't do pagination.  It already prints a (not so) fancy
banner for you.  95% of the line printer jobs that people used
to run were like the pr example above.  Now they look like

	lpr -p *.c

I would bet that the example I gave is also 95% of what pr is used
for.  Printer jobs now run a LOT faster, they don't bog down the
system when it's already slow, and the code to get it right cost us
all of 40 lines, including handling the -p flag in lpr, defining the
flag in a header file, etc.  In addition, we no longer have to worry
about running out of space in /usr.
-- 
Violence is the last refuge of the incompetent.

{ihnp4 hao philabs sdcrdcf ucbvax!nbires}!stcvax!lat	Larry Tepper
Storage Technology, MD-3T, Louisville, CO 80028		303-673-5435

tom@uwai.UUCP (10/11/84)

>      This is a strong argument against running utilities such as the
> line printer spooler as ``setuid to root''.  Such programs should
> open the file of interest while running as the requestor and then
> exec a second program which is set-uid to a service user id which owns
> the spooling directory, after which a copy can be performed.  This
> is a little more complex but much safer.

Why the added work of an extra exec?  Just make sure that the real uid
(not the effective one) can access the file.

Also: please make sure the subject line has *some* bearing on the content.
	  I don't see what setuid programs have to do with the hazards of
	  linking directories.

tom
-- 

Tom Christiansen
University of Wisconsin
Computer Science Systems Lab 
...!{allegra,heurikon,ihnp4,seismo,uwm-evax}!uwvax!tom
tom@wisc-crys.arpa

mcb%lll-tis.arpa@lll-tis.ARPA (10/13/84)

From:  "Michael C. Berch" <mcb%lll-tis.arpa@lll-tis.ARPA>

In the "old days" it was forbidden to link to directories. Now I
know why. Had the link been symbolic (as in 4BSD) the horror
would not have occurred.

But, more seriously: a line printer spooler that "spools" by
LINKING the print file into the spool directory??? What if you
make changes in the file between the queue time and the time it
is actually printed? When I say "lpr foo" I assume that "foo" is
conceptually being printed RIGHT NOW, and that the spooling
mechanism exists only to make efficient use of a resource (the
printer). I'd feel free to modify the file, secure in the
knowledge that it would be printed in its original form.

Is this the standard System V printer spooler that does this?
I understand the problem if you are running XENIX with floppy
disks, but hopefully a REAL system spooler would never do this...

				Michael C. Berch
				mcb@lll-tis.arpa
				...ucbvax!lbl-csam!lll-tis!mcb