From: Manfred Spraul <manfred@colorfullife.com>

Fixes a race between proc_pid_lookup and sys_exit.

- The inodes and dentries for /proc/<pid>/whatever are cached in the dentry
  cache.  d_revalidate is used to protect against stale data: d_revalidate
  returns invalid if the task exited.

  Additionally, sys_exit flushes the dentries for the task that died -
  otherwise the dentries would stay around until they arrive at the end of
  the LRU, which could take some time.  But there is one race:

  - proc_pid_lookup finds a task and prepares new dentries for it. It must 
    drop all locks for that operation.
  - the process exits, and the /proc/ dentries are flushed. Nothing 
    happens, because they are not yet in the hash tables.
  - proc_pid_lookup adds the task to the dentry cache.

  Result: dentry of a dead task in the hash tables.

  The patch fixes that problem by flushing again if proc_pid_lookup notices
  that the thread exited while it created the dentry.  The patch should go
  in, but it's not critical.


- task->proc_dentry must be the dentry of /proc/<pid>.  That way sys_exit
  can flush the whole subtree at exit time.  proc_task_lookup is a direct
  copy of proc_pid_lookup and handles /proc/<>/task/<pid>.  It contains the
  lines that set task->proc_dentry.  This is bogus, and must be removed.  

  This hunk is much more critical, because creates a de-facto dentry leak
  (they are recovered after flushing real dentries from the cache).



 fs/proc/base.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff -puN fs/proc/base.c~proc_pid_lookup-vs-exit-race-fix fs/proc/base.c
--- 25/fs/proc/base.c~proc_pid_lookup-vs-exit-race-fix	2003-11-19 10:43:11.000000000 -0800
+++ 25-akpm/fs/proc/base.c	2003-11-19 10:43:11.000000000 -0800
@@ -1524,6 +1524,7 @@ struct dentry *proc_pid_lookup(struct in
 	struct inode *inode;
 	struct proc_inode *ei;
 	unsigned tgid;
+	int died;
 
 	if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
 		inode = new_inode(dir->i_sb);
@@ -1567,12 +1568,21 @@ struct dentry *proc_pid_lookup(struct in
 
 	dentry->d_op = &pid_base_dentry_operations;
 
+	died = 0;
+	d_add(dentry, inode);
 	spin_lock(&task->proc_lock);
 	task->proc_dentry = dentry;
-	d_add(dentry, inode);
+	if (!pid_alive(task)) {
+		dentry = proc_pid_unhash(task);
+		died = 1;
+	}
 	spin_unlock(&task->proc_lock);
 
 	put_task_struct(task);
+	if (died) {
+		proc_pid_flush(dentry);
+		goto out;
+	}
 	return NULL;
 out:
 	return ERR_PTR(-ENOENT);
@@ -1612,10 +1622,7 @@ static struct dentry *proc_task_lookup(s
 
 	dentry->d_op = &pid_base_dentry_operations;
 
-	spin_lock(&task->proc_lock);
-	task->proc_dentry = dentry;
 	d_add(dentry, inode);
-	spin_unlock(&task->proc_lock);
 
 	put_task_struct(task);
 	return NULL;

_