@@ -1968,6 +1968,20 @@ void pid_update_inode(struct task_struct *task, struct inode *inode)
security_task_to_inode(task, inode);
}
+/* See if we can avoid the above call. Assumes RCU lock held */
+static bool pid_inode_needs_update(struct task_struct *task, struct inode *inode)
+{
+ kuid_t uid;
+ kgid_t gid;
+
+ if (inode->i_mode & (S_ISUID | S_ISGID))
+ return true;
+ task_dump_owner(task, inode->i_mode, &uid, &gid);
+ if (!uid_eq(uid, inode->i_uid) || !gid_eq(gid, inode->i_gid))
+ return true;
+ return false;
+}
+
/*
* Rewrite the inode's ownerships here because the owning task may have
* performed a setuid(), etc.
@@ -1977,19 +1991,20 @@ static int pid_revalidate(struct dentry *dentry, unsigned int flags)
{
struct inode *inode;
struct task_struct *task;
+ int rv = 0;
- if (flags & LOOKUP_RCU)
- return -ECHILD;
-
- inode = d_inode(dentry);
- task = get_proc_task(inode);
-
+ rcu_read_lock();
+ inode = d_inode_rcu(dentry);
+ task = pid_task(proc_pid(inode), PIDTYPE_PID);
if (task) {
- pid_update_inode(task, inode);
- put_task_struct(task);
- return 1;
+ rv = 1;
+ if ((flags & LOOKUP_RCU) && pid_inode_needs_update(task, inode))
+ rv = -ECHILD;
+ else if (!(flags & LOOKUP_RCU))
+ pid_update_inode(task, inode);
}
- return 0;
+ rcu_read_unlock();
+ return rv;
}
static inline bool proc_inode_is_dead(struct inode *inode)