Why is chmod(2)?

Kristian Koehntopp (kris@koehntopp.de)
Wed, 22 Sep 1999 02:08:28 +0200


I was talking about Unix system security recently and came
across a strange question which you may be able to answer. The
question is: "Why is chmod(2)", i.e. why are there so many
kernel functions which take pathnames as parameters, when there
are similar functions which take an fd.

One obvious reason is of course compatibility. There are
binaries that call chmod(2) and they should continue to work.
But compatibility aside, can chmod(2) be implemented as chmod(3)
using open(2) and fchmod(2) and is the same true for all other
system calls which take pathnames as an argument?

a. Is this desireable?
b. Is it possible?

I think it is often desireable in security related programs to
use the f-version of a systemcall, because it ensures that you
are talking about the same file in a sequence of related calls
that are being done with the intention to check multiple things.
An open fd is the only way for a process to refer directly to an
inode (and a file offset, which is redundant in some cases, but
not harmful).

For example, in the suexec.c binary, which is part of the Apache
distribution, there is code along the lines of

cmd = argv[3];

if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) {
log_err("cannot stat program: (%s)\n", cmd);
exit(117);
}
/* more checks on the stat buffer */
/* the binary may be replaced, because these are nonatomic operations */

execv(cmd, &argv[3]);

Here, argv[3] may refer to different files because it is
resolved multiple times, once in the lstat() and once in the
execve() system calls. I think it would be desireable to be able
to open() the cmd and then use fstat() and fexecve() which would
ensure that we are at least talking about the same file each
time.

This would require r-right on cmd, though, because you cannot
open(2) an execute-only file. Alternatively, you would need
something like O_NULL and O_EXONLY as parameters to open(2),
along the lines of O_RDONLY and O_RDWR. O_NULL would indicate
that you want a file handle as a handle only, to be able to pass
it to fchown() and fchmod() which only require that you are the
owner of the file in question. O_EXONLY would require that you
have execute permission on the file on question and you could
use the resulting handle and pass it to fexecve().

Does this make sense or am I missing something here? If not, why
aren't chmod(2) and friends not implemented as library functions
instead?

Kristian

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/