diff options
author | 2008-06-10 20:01:23 +0000 | |
---|---|---|
committer | 2008-06-10 20:01:23 +0000 | |
commit | 486142a0646b155a7771ae495cdb75011a72cc4b (patch) | |
tree | 42922c8a9c068b391c7b9ebc716ffd3473f6aedc /trunk/2.6.18/30066_fcntl_setlk-close-race.patch | |
parent | Update 2.6.18 Security patches to 2.6.18.dfsg.1-18etch3, thanks dannf. (diff) | |
download | xen-486142a0646b155a7771ae495cdb75011a72cc4b.tar.gz xen-486142a0646b155a7771ae495cdb75011a72cc4b.tar.bz2 xen-486142a0646b155a7771ae495cdb75011a72cc4b.zip |
Bumping 2.6.18 patchset to Debian 2.6.18.dfsg.1-18etch6
svn path=/patches/; revision=78
Diffstat (limited to 'trunk/2.6.18/30066_fcntl_setlk-close-race.patch')
-rw-r--r-- | trunk/2.6.18/30066_fcntl_setlk-close-race.patch | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/trunk/2.6.18/30066_fcntl_setlk-close-race.patch b/trunk/2.6.18/30066_fcntl_setlk-close-race.patch new file mode 100644 index 0000000..9292f22 --- /dev/null +++ b/trunk/2.6.18/30066_fcntl_setlk-close-race.patch @@ -0,0 +1,76 @@ +commit 0b2bac2f1ea0d33a3621b27ca68b9ae760fca2e9 +Author: Al Viro <viro@zeniv.linux.org.uk> +Date: Tue May 6 13:58:34 2008 -0400 + + [PATCH] fix SMP ordering hole in fcntl_setlk() + + fcntl_setlk()/close() race prevention has a subtle hole - we need to + make sure that if we *do* have an fcntl/close race on SMP box, the + access to descriptor table and inode->i_flock won't get reordered. + + As it is, we get STORE inode->i_flock, LOAD descriptor table entry vs. + STORE descriptor table entry, LOAD inode->i_flock with not a single + lock in common on both sides. We do have BKL around the first STORE, + but check in locks_remove_posix() is outside of BKL and for a good + reason - we don't want BKL on common path of close(2). + + Solution is to hold ->file_lock around fcheck() in there; that orders + us wrt removal from descriptor table that preceded locks_remove_posix() + on close path and we either come first (in which case eviction will be + handled by the close side) or we'll see the effect of close and do + eviction ourselves. Note that even though it's read-only access, + we do need ->file_lock here - rcu_read_lock() won't be enough to + order the things. + + Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> + +Adjusted to apply to Debian's 2.6.18 by dann frazier <dannf@hp.com> + +diff -urpN linux-source-2.6.18.orig/fs/locks.c linux-source-2.6.18/fs/locks.c +--- linux-source-2.6.18.orig/fs/locks.c 2006-09-19 21:42:06.000000000 -0600 ++++ linux-source-2.6.18/fs/locks.c 2008-05-06 17:02:29.000000000 -0600 +@@ -1680,6 +1680,7 @@ int fcntl_setlk(unsigned int fd, struct + struct file_lock *file_lock = locks_alloc_lock(); + struct flock flock; + struct inode *inode; ++ struct file *f; + int error; + + if (file_lock == NULL) +@@ -1754,7 +1755,15 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { ++ /* ++ * we need that spin_lock here - it prevents reordering between ++ * update of inode->i_flock and check for it done in close(). ++ * rcu_read_lock() wouldn't do. ++ */ ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (!error && f != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; + } +@@ -1823,6 +1832,7 @@ int fcntl_setlk64(unsigned int fd, struc + struct file_lock *file_lock = locks_alloc_lock(); + struct flock64 flock; + struct inode *inode; ++ struct file *f; + int error; + + if (file_lock == NULL) +@@ -1897,7 +1907,10 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (!error && f != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; + } |