CRED: Use RCU to access another task's creds and to release a task's own creds
[deliverable/linux.git] / fs / proc / base.c
index 486cf3fe7139949a0911e0e33f9cb99a06bfb8fb..cf42c42cbfbbf5db12491dc769585f4a0c7f4229 100644 (file)
@@ -1406,6 +1406,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
 {
        struct inode * inode;
        struct proc_inode *ei;
+       const struct cred *cred;
 
        /* We need a new inode */
 
@@ -1428,8 +1429,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
        inode->i_uid = 0;
        inode->i_gid = 0;
        if (task_dumpable(task)) {
-               inode->i_uid = task->euid;
-               inode->i_gid = task->egid;
+               rcu_read_lock();
+               cred = __task_cred(task);
+               inode->i_uid = cred->euid;
+               inode->i_gid = cred->egid;
+               rcu_read_unlock();
        }
        security_task_to_inode(task, inode);
 
@@ -1445,6 +1449,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
 {
        struct inode *inode = dentry->d_inode;
        struct task_struct *task;
+       const struct cred *cred;
+
        generic_fillattr(inode, stat);
 
        rcu_read_lock();
@@ -1454,8 +1460,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
        if (task) {
                if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
                    task_dumpable(task)) {
-                       stat->uid = task->euid;
-                       stat->gid = task->egid;
+                       cred = __task_cred(task);
+                       stat->uid = cred->euid;
+                       stat->gid = cred->egid;
                }
        }
        rcu_read_unlock();
@@ -1483,11 +1490,16 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        struct task_struct *task = get_proc_task(inode);
+       const struct cred *cred;
+
        if (task) {
                if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
                    task_dumpable(task)) {
-                       inode->i_uid = task->euid;
-                       inode->i_gid = task->egid;
+                       rcu_read_lock();
+                       cred = __task_cred(task);
+                       inode->i_uid = cred->euid;
+                       inode->i_gid = cred->egid;
+                       rcu_read_unlock();
                } else {
                        inode->i_uid = 0;
                        inode->i_gid = 0;
@@ -1649,6 +1661,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct task_struct *task = get_proc_task(inode);
        int fd = proc_fd(inode);
        struct files_struct *files;
+       const struct cred *cred;
 
        if (task) {
                files = get_files_struct(task);
@@ -1658,8 +1671,11 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
                                rcu_read_unlock();
                                put_files_struct(files);
                                if (task_dumpable(task)) {
-                                       inode->i_uid = task->euid;
-                                       inode->i_gid = task->egid;
+                                       rcu_read_lock();
+                                       cred = __task_cred(task);
+                                       inode->i_uid = cred->euid;
+                                       inode->i_gid = cred->egid;
+                                       rcu_read_unlock();
                                } else {
                                        inode->i_uid = 0;
                                        inode->i_gid = 0;
This page took 0.030412 seconds and 5 git commands to generate.