Commit d24db0a5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix /proc/pid/fd ownership across setuid()

From: "B. D. Elliott" <bde@nwlink.com>

There's a bug:

- Someone reads a (say) root-owned process's /proc/pid/fd directory

  The inodes are instantiated owned by root.

- That process does a setuid

- The /proc/pid/* files still have the old ownerships.

This happened because we are now caching the proc entries.

The patch rewrites the ownership of the inodes under /proc/pid in the
d_revalidate() handler.
parent e2d3b22c
...@@ -864,16 +864,24 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st ...@@ -864,16 +864,24 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
* Exceptional case: normally we are not allowed to unhash a busy * Exceptional case: normally we are not allowed to unhash a busy
* directory. In this case, however, we can do it - no aliasing problems * directory. In this case, however, we can do it - no aliasing problems
* due to the way we treat inodes. * due to the way we treat inodes.
*
* Rewrite the inode's ownerships here because the owning task may have
* performed a setuid(), etc.
*/ */
static int pid_revalidate(struct dentry * dentry, struct nameidata *nd) static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
{ {
if (pid_alive(proc_task(dentry->d_inode))) if (pid_alive(proc_task(dentry->d_inode))) {
struct task_struct *task = proc_task(dentry->d_inode);
dentry->d_inode->i_uid = task->euid;
dentry->d_inode->i_gid = task->egid;
return 1; return 1;
}
d_drop(dentry); d_drop(dentry);
return 0; return 0;
} }
static int pid_fd_revalidate(struct dentry * dentry, struct nameidata *nd) static int pid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
{ {
struct task_struct *task = proc_task(dentry->d_inode); struct task_struct *task = proc_task(dentry->d_inode);
int fd = proc_type(dentry->d_inode) - PROC_PID_FD_DIR; int fd = proc_type(dentry->d_inode) - PROC_PID_FD_DIR;
...@@ -889,6 +897,8 @@ static int pid_fd_revalidate(struct dentry * dentry, struct nameidata *nd) ...@@ -889,6 +897,8 @@ static int pid_fd_revalidate(struct dentry * dentry, struct nameidata *nd)
if (fcheck_files(files, fd)) { if (fcheck_files(files, fd)) {
spin_unlock(&files->file_lock); spin_unlock(&files->file_lock);
put_files_struct(files); put_files_struct(files);
dentry->d_inode->i_uid = task->euid;
dentry->d_inode->i_gid = task->egid;
return 1; return 1;
} }
spin_unlock(&files->file_lock); spin_unlock(&files->file_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment