
From: Andrey Borzenkov <arvidjaar@mail.ru>

The code that did proper check existed in 2.4 and was removed in 2.5 for 
whatever reason. The patch restores it slightly modified as below.

2.4 code looks somewhat unclean in that

- it traverses task list without lock. 

- it starts from current->real_parent but nothing prevents current be
  init_task itself.  This hung for me on 2.5 during boot.  May be 2.4 does
  something differently.

This is trivially reproduced under 2.5 by using devfsd.conf lines

LOOKUP  ^foo$   EXECUTE /home/bor/tmp/devfsd/handler /dev/bar
LOOKUP  ^bar$   EXECUTE /home/bor/tmp/devfsd/handler /dev/foo

and handler like

-------- cut here ----------
#include <unistd.h>

int
main(int argc, char **argv, char **envp)
{
        if (argc <= 1)
                return 0;

        setpgrp();
        return access(argv[1], R_OK);
}
-------- cut here ----------

and doing ls /dev/foo



 fs/devfs/base.c |   17 +++++++++++++++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff -puN fs/devfs/base.c~is_devfsd_or_child-lockup-fix fs/devfs/base.c
--- 25/fs/devfs/base.c~is_devfsd_or_child-lockup-fix	2003-07-13 21:54:06.000000000 -0700
+++ 25-akpm/fs/devfs/base.c	2003-07-13 21:54:06.000000000 -0700
@@ -676,6 +676,7 @@
 #include <linux/smp.h>
 #include <linux/version.h>
 #include <linux/rwsem.h>
+#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1325,8 +1326,20 @@ static void free_dentry (struct devfs_en
 
 static int is_devfsd_or_child (struct fs_info *fs_info)
 {
-    if (current == fs_info->devfsd_task) return (TRUE);
-    if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
+    struct task_struct *p = current;
+
+    if (p == fs_info->devfsd_task) return (TRUE);
+    if (p->pgrp == fs_info->devfsd_pgrp) return (TRUE);
+    read_lock(&tasklist_lock);
+    for ( ; p != &init_task; p = p->real_parent)
+    {
+	if (p == fs_info->devfsd_task)
+	{
+	    read_unlock (&tasklist_lock);
+	    return (TRUE);
+	}
+    }
+    read_unlock (&tasklist_lock);
     return (FALSE);
 }   /*  End Function is_devfsd_or_child  */
 

_
