Al Viro added to the CC, since he's one of the experts on this stuff and will probably whack me with a LART for explaining it all wrong, or something. :-D

On Aug 15, 2007, at 16:38:36, Phillip Susi wrote:
Kyle Moffett wrote:
We've *always* had to do this; that's what "chmod -R" or "setfacl - R" are for :-D. The major problem is that the locking and lookup overhead gets really significant if you have to look at the entire directory tree in order to determine the permissions for one single object. I definitely agree that we need better GUIs for managing file permissions, but I don't see how you could modify the kernel in this case to do what you want.

I am well aware of that, I'm simply saying that sucks. Doing a recursive chmod or setfacl on a large directory tree is slow as all hell.

Doing it in the kernel won't make it any faster.


As for hard links, your access would depend on which name you use to access the file. The file itself may still have an acl that grants or denies access to people no matter what name they use, but if it allows inheritance, then which name you access it by will modify the effective acl that it gets.

You can't safely preserve POSIX semantics that way. For example, even without *ANY* ability to read /etc/shadow, I can easily "ln /etc/ shadow /tmp/shadow", assuming they are on the same filesystem. If the /etc/shadow permissions depend on inherited ACLs to enforce access then that one little command just made your shadow file world- readable/writeable. Oops.

Think about it this way:
Permissions depend on *what* something is, not *where* it is. Under Linux you can leave the digital equivalent of a $10,000 piece of jewelry lying around in /var/www and not have to worry about it being compromised as long as you set your permissions properly (not that I recommend it). Moving the piece of jewelry around your house does not change what it *is* (and by extension does not change the protection required on it), any more than "ln /etc/shadow /tmp/ shadow" (or "mv") changes what *it* is. If your /house is really extraordinarily secure then you could leave the jewelry lying around as /house/gems.bin with permissions 0777, but if somebody had a back- door to /house (an open fd, a careless typo, etc) then you'd have the same issues.


As for performance implications, I hardly think it is worrisome. Each directory in the path has to be looked up anyhow so you already have their acls, so when you finally reach the file, you just have to take the union of the acls encountered on the way. Should only be a few cpu cycles.

Not necessarily. When I do "vim some-file-in-current-directory", for example, the kernel does *NOT* look up the path of my current directory. It does (in pseudocode):

if (starts_with_slash(filename)) {
        entry = task->cwd;
} else {
        entry = task->root;
}
while (have_components_left(filename)
        entry = lookup_next_component(filename);
return entry;


That's not even paying attention to functions like "fchdir" or their interactions with "chroot" and namespaces. I can probably have an open directory handle to a volume in a completely different namespace, a volume which isn't even *MOUNTED* in my current fs namespace. Using that file-handle I believe I can "fchdir", "openat", etc, in a completely different namespace. I can do the same thing with a chroot, except there I can even "escape":
  /* Switch into chroot.  Doesn't drop root privs */
  chdir("/some/dir/somewhere");
  chroot(".");

  /* Malicious code later on */
  chdir("/");
  chroot("another_dir");
  chdir("../../../../../../../../..");
  chroot(".");
  /* Now I'm back in the real root filesystem */


There's also the question of what to do about namespaces and bind mounts. If I run "mount --bind /foo /home/foo", then do I get different file permissions depending on what path I access the file by? What if I then run chroot("/foo"), do I get different file permissions then? What if I have two namespaces, each with their own root filesystem (say "root1" and "root2"), and I mount the other namespace's root filesystem in a subdir of each:
  NS1:  mount /dev/root2 /otherns
  NS2:  mount /dev/root1 /otherns
Now I have the following paths to the same file, do these get different permissions or the same?
  NS1:/foo == NS2:/otherns/foo
  NS2:/bar == NS1:/otherns/bar
If you answered that they get different permissions, then how do you handle the massive locking performance penalty due to the extra lookups? If you answered "same permissions", then how do you explain the obvious discrepancy to the admin?

Good question. I would say the bind mount should have a flag to specify. That way the admin can choose where it should inherit from. I also don't see where this locking penalty is.

The locking penalty is because the path-lookup is *not* implied. The above chroot example shows that in detail. If you have to do the lookup in *reverse* on every open operation then you have to either:

(A) Store lots of security context with every open directory (cwd included). When a directory you have open is moved, you still have full access to everything inside it since your handle's data hasn't changed.

OR

(B) Do a reverse-lookup on every operation, which means you are taking locks in the reverse order from the normal lookup order and you're either very inefficient and slow or you're deadlocky. This is also vulnerable to confusion when the "path" isn't visible from your namespace/chroot at all. This also causes problems with overmounted directories:
        [EMAIL PROTECTED]:/# mkdir -p /foo/bar
        [EMAIL PROTECTED]:/# cd /foo/bar
        [EMAIL PROTECTED]:/foo/bar# mount -t tmpfs tmpfs /foo
        [EMAIL PROTECTED]:/foo/bar# touch /foo/bar/baz
        touch: cannot touch `/foo/bar/baz': No such file or directory
        [EMAIL PROTECTED]:/foo/bar# pwd
        /foo/bar
        [EMAIL PROTECTED]:/foo/bar# ls -al
        total 4
        drwxr-xr-x 2 root root 4096 2007-08-15 17:04 .
        drwxrwxrwt 2 root root   40 2007-08-15 17:04 ..


The idea is nice, but as soon as you add multiple namespaces, chroots, or bind mounts the concept breaks down. For security- sensitive things like file permissions, you really do want determinate behavior regardless of the path used to access the data.

How does it break down? Chroots have absolutely no impact at all, and the bind mounts/namespaces can be handled as I mentioned above. If you really want to be sure of the effective permissions on the file, then you simply flag it to not inherit from its parent or use an inherited rights mask to block the specific inherited permissions you want.

See above. Linux has a very *very* powerful VFS nowadays. It also has support for shared subtrees across private namespaces, allowing things like polyinstantiation. For example you can configure a Linux box so every user gets their own empty /tmp directory created and mounted on their namespace's /tmp when they log in, but all the rest of the system mounts are all shared.

I'll be offline for a couple days, we can chat more when I get back.

Cheers,
Kyle Moffett

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to