From: Chris Wright Date: Mon, 19 Jun 2006 19:12:09 +0000 (-0700) Subject: locking fix for namei.c fwd from Joe Korty X-Git-Tag: v2.6.16.21~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f556a31c2d8a0a5e277bc0fec078c10b02c2619e;p=thirdparty%2Fkernel%2Fstable-queue.git locking fix for namei.c fwd from Joe Korty --- diff --git a/queue-2.6.16/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch b/queue-2.6.16/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch new file mode 100644 index 00000000000..8a2e2e3bda4 --- /dev/null +++ b/queue-2.6.16/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch @@ -0,0 +1,97 @@ +From stable-bounces@linux.kernel.org Tue Jun 6 08:23:00 2006 +Date: Tue, 6 Jun 2006 11:19:35 -0400 +From: Joe Korty +To: stable@kernel.org +Cc: +Subject: fs/namei.c: Call to file_permission() under a spinlock in do_lookup_path() + +From: Trond Myklebust + +We're presently running lock_kernel() under fs_lock via nfs's ->permission +handler. That's a ranking bug and sometimes a sleep-in-spinlock bug. This +problem was introduced in the openat() patchset. + +We should not need to hold the current->fs->lock for a codepath that doesn't +use current->fs. + +[vsu@altlinux.ru: fix error path] +Signed-off-by: Trond Myklebust +Cc: Al Viro +Signed-off-by: Sergey Vlasov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Chris Wright +--- + + fs/namei.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +--- linux-2.6.16.20.orig/fs/namei.c ++++ linux-2.6.16.20/fs/namei.c +@@ -1077,8 +1077,8 @@ static int fastcall do_path_lookup(int d + nd->flags = flags; + nd->depth = 0; + +- read_lock(¤t->fs->lock); + if (*name=='/') { ++ read_lock(¤t->fs->lock); + if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { + nd->mnt = mntget(current->fs->altrootmnt); + nd->dentry = dget(current->fs->altroot); +@@ -1089,33 +1089,35 @@ static int fastcall do_path_lookup(int d + } + nd->mnt = mntget(current->fs->rootmnt); + nd->dentry = dget(current->fs->root); ++ read_unlock(¤t->fs->lock); + } else if (dfd == AT_FDCWD) { ++ read_lock(¤t->fs->lock); + nd->mnt = mntget(current->fs->pwdmnt); + nd->dentry = dget(current->fs->pwd); ++ read_unlock(¤t->fs->lock); + } else { + struct dentry *dentry; + + file = fget_light(dfd, &fput_needed); + retval = -EBADF; + if (!file) +- goto unlock_fail; ++ goto out_fail; + + dentry = file->f_dentry; + + retval = -ENOTDIR; + if (!S_ISDIR(dentry->d_inode->i_mode)) +- goto fput_unlock_fail; ++ goto fput_fail; + + retval = file_permission(file, MAY_EXEC); + if (retval) +- goto fput_unlock_fail; ++ goto fput_fail; + + nd->mnt = mntget(file->f_vfsmnt); + nd->dentry = dget(dentry); + + fput_light(file, fput_needed); + } +- read_unlock(¤t->fs->lock); + current->total_link_count = 0; + retval = link_path_walk(name, nd); + out: +@@ -1124,13 +1126,12 @@ out: + nd->dentry->d_inode)) + audit_inode(name, nd->dentry->d_inode, flags); + } ++out_fail: + return retval; + +-fput_unlock_fail: ++fput_fail: + fput_light(file, fput_needed); +-unlock_fail: +- read_unlock(¤t->fs->lock); +- return retval; ++ goto out_fail; + } + + int fastcall path_lookup(const char *name, unsigned int flags, diff --git a/queue-2.6.16/series b/queue-2.6.16/series index b729df0eb97..ed2de98304c 100644 --- a/queue-2.6.16/series +++ b/queue-2.6.16/series @@ -5,3 +5,4 @@ sparc64-fix-missing-fold-at-end-of-checksums.patch missed-error-checking-for-intent-s-filp-in-open_namei.patch tmpfs-time-granularity-fix-for-time-going-backwards.patch serial-parport_serial-should-depend-on-serial_8250_pci.patch +fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch