Writing to A NON-Existing File in \"C\"

der Mouse mouse at larry.mcrcim.mcgill.edu
Fri Apr 29 14:31:00 AEST 1988


>>> I propose enclosing the whole mess between two stat's, and testing
>>> whether the vital statistics match.

>> Well, you have to be very careful, and even then, I don't think it's
>> possible to get it right.  You can make the window much harder to
>> hit, but I don't think it's possible to get rid of it entirely.

> My idea is more explicitly

>	stat(path,&before)
>	if (access(path,how) == 0) { /*OK*/
>		fd = open(path,mode);
>		stat(path,&after);
> [compare after.xxx and before.xxx for appropriate xxx]
>	}

> [later in letter] Any problems with this approach?

Yes.  Suppose we pull a switch immediately before and after the open().
You can't catch it, and can easily wind up opening the wrong file.
Specifically:

user does		program does

% touch myfile.blah
% setuidpgm myfile.blah
			stat(path,&before)
			if (access(path,how) == 0) { /*OK*/
% mv myfile.blah myfile.save
% ln -s /etc/passwd myfile.blah
				fd = open(path,mode);
% rm -f myfile.blah
% mv myfile.save myfile.blah
				stat(path,&after);
		[compare after.xxx and before.xxx for appropriate xxx]
			}

(Of course, those wouldn't actually be typed commands; I'm just using
the commands to indicate the operations being performed.)  This is why
I recommend doing fstat() on the file descriptor returned by open(), to
ensure that the file you really opened is the one you were stat()ing.
But that's vulnerable too; think about something similar to the above
with the secure file in place at the beginning, replaced with an
innocuous file for the access() to see.

(You can see why I said the window is "much" harder to hit.  The bad
guy must time two operations exactly right instead of just one, and the
interval between the two is very short.)

> Good things to check would be inode number and creation date.

Do any recent systems maintain a creation date?  4.[23]BSD doesn't.
(st_ctime is the inode-change time, not the creation time.)

> Neither can easily be faked, except thru acces to the raw device.

If I wanted to patch a ctime field, I'd much rather change the clock
and touch the file than meddle with the raw disk.

> If [the file being open()ed] doesn't already exist, the job is a bit
> harder.

I claim it's impossible if the user has write access to any of the
ancestors of the directory the file is to be created in.

> BTW, while we're talking windows, mktemp et al suffer as well.

Hence mkstemp(3).

					der Mouse

			uucp: mouse at mcgill-vision.uucp
			arpa: mouse at larry.mcrcim.mcgill.edu



More information about the Comp.unix.wizards mailing list