Allow access to /proc/$PID/fd after setuid()
authorAlexey Dobriyan <[email protected]>
Tue, 8 May 2007 07:23:35 +0000 (00:23 -0700)
committerLinus Torvalds <[email protected]>
Tue, 8 May 2007 18:14:58 +0000 (11:14 -0700)
/proc/$PID/fd has r-x------ permissions, so if process does setuid(), it
will not be able to access /proc/*/fd/. This breaks fstatat() emulation
in glibc.

open("foo", O_RDONLY|O_DIRECTORY)       = 4
setuid32(65534)                         = 0
stat64("/proc/self/fd/4/bar", 0xbfafb298) = -1 EACCES (Permission denied)

Signed-off-by: Alexey Dobriyan <[email protected]>
Cc: "Eric W. Biederman" <[email protected]>
Cc: James Morris <[email protected]>
Cc: Chris Wright <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Acked-By: Kirill Korotaev <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
fs/proc/base.c

index ec158dd02b3ac2b758fbbf527820c1f0f83a486a..a721acfd4fdcd3a008befe2a8a185a863b5e0903 100644 (file)
@@ -1447,11 +1447,29 @@ static const struct file_operations proc_fd_operations = {
        .readdir        = proc_readfd,
 };
 
+/*
+ * /proc/pid/fd needs a special permission handler so that a process can still
+ * access /proc/self/fd after it has executed a setuid().
+ */
+static int proc_fd_permission(struct inode *inode, int mask,
+                               struct nameidata *nd)
+{
+       int rv;
+
+       rv = generic_permission(inode, mask, NULL);
+       if (rv == 0)
+               return 0;
+       if (task_pid(current) == proc_pid(inode))
+               rv = 0;
+       return rv;
+}
+
 /*
  * proc directories can do almost nothing..
  */
 static const struct inode_operations proc_fd_inode_operations = {
        .lookup         = proc_lookupfd,
+       .permission     = proc_fd_permission,
        .setattr        = proc_setattr,
 };