i missed a case while SMP-threading exec(). The window is very small but
present, under very high exec() load this bug results in negative d_count
asserts in dput(). Attached patch is against pre-2.3.50-2.

(the patch also includes a fix to binfmt_elf.c, although i cannot see how
that #ifdef-ed code could possibly get compiled in. Plus the patch updates
em86 binformat to the new binary loader SMP locking semantics. Dynamic
loading of binary formats into the kernel is still SMP-unsafe.)

Tested ELF and script binformats under load, and they are ok.

-- mingo
--- linux/fs/exec.c.orig        Mon Mar  6 02:59:18 2000
+++ linux/fs/exec.c     Mon Mar  6 03:19:47 2000
@@ -84,6 +84,7 @@
        struct list_head * l = NULL;
        int fd, error;
 
+       lock_kernel();
        if (inode->i_sb)
                l = &inode->i_sb->s_files;
 
@@ -111,6 +112,7 @@
                fd_install(fd, f);
                dget(dentry);
        }
+       unlock_kernel();
        return fd;
 
 out_filp:
@@ -120,6 +122,7 @@
 out_fd:
        put_unused_fd(fd);
 out:
+       unlock_kernel();
        return error;
 }
 
--- linux/fs/binfmt_elf.c.orig  Mon Mar  6 03:32:24 2000
+++ linux/fs/binfmt_elf.c       Mon Mar  6 03:31:19 2000
@@ -707,7 +707,9 @@
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
 #ifndef VM_STACK_FLAGS
+       lock_kernel();
        current->executable = dget(bprm->dentry);
+       unlock_kernel();
 #endif
        compute_creds(bprm);
        current->flags &= ~PF_FORKNOEXEC;
--- linux/fs/binfmt_em86.c.orig Mon Mar  6 03:35:06 2000
+++ linux/fs/binfmt_em86.c      Mon Mar  6 03:36:20 2000
@@ -42,7 +42,9 @@
        }
 
        bprm->sh_bang++;        /* Well, the bang-shell is implicit... */
+       lock_kernel();
        dput(bprm->dentry);
+       unlock_kernel();
        bprm->dentry = NULL;
 
        /* Unlike in the script case, we don't have to do any hairy
@@ -78,7 +80,9 @@
         * Note that we use open_namei() as the name is now in kernel
         * space, and we don't need to copy it.
         */
+       lock_kernel();
        dentry = open_namei(interp, 0, 0);
+       unlock_kernel();
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 

Reply via email to