From: Greg Kroah-Hartman Date: Fri, 4 Mar 2016 01:30:26 +0000 (-0800) Subject: 3.10-stable patches X-Git-Tag: v3.10.100~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c2947bb6241e665dc8c34dc14a2a731d05ab0e40;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch --- diff --git a/queue-3.10/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch b/queue-3.10/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch new file mode 100644 index 00000000000..e7f1fd73af5 --- /dev/null +++ b/queue-3.10/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch @@ -0,0 +1,121 @@ +From 7f3697e24dc3820b10f445a4a7d914fc356012d1 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 7 Jan 2016 16:38:10 -0500 +Subject: locks: fix unlock when fcntl_setlk races with a close + +From: Jeff Layton + +commit 7f3697e24dc3820b10f445a4a7d914fc356012d1 upstream. + +Dmitry reported that he was able to reproduce the WARN_ON_ONCE that +fires in locks_free_lock_context when the flc_posix list isn't empty. + +The problem turns out to be that we're basically rebuilding the +file_lock from scratch in fcntl_setlk when we discover that the setlk +has raced with a close. If the l_whence field is SEEK_CUR or SEEK_END, +then we may end up with fl_start and fl_end values that differ from +when the lock was initially set, if the file position or length of the +file has changed in the interim. + +Fix this by just reusing the same lock request structure, and simply +override fl_type value with F_UNLCK as appropriate. That ensures that +we really are unlocking the lock that was initially set. + +While we're there, make sure that we do pop a WARN_ON_ONCE if the +removal ever fails. Also return -EBADF in this event, since that's +what we would have returned if the close had happened earlier. + +Cc: Alexander Viro +Fixes: c293621bbf67 (stale POSIX lock handling) +Reported-by: Dmitry Vyukov +Signed-off-by: Jeff Layton +Acked-by: "J. Bruce Fields" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/locks.c | 51 ++++++++++++++++++++++++++++++--------------------- + 1 file changed, 30 insertions(+), 21 deletions(-) + +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -1852,7 +1852,6 @@ int fcntl_setlk(unsigned int fd, struct + goto out; + } + +-again: + error = flock_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -1883,19 +1882,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- /* +- * 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; ++ if (!error && file_lock->fl_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 (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; +@@ -1970,7 +1972,6 @@ int fcntl_setlk64(unsigned int fd, struc + goto out; + } + +-again: + error = flock64_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -2001,14 +2002,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- 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; ++ if (!error && file_lock->fl_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 (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; diff --git a/queue-3.10/series b/queue-3.10/series new file mode 100644 index 00000000000..2f9ecde15e1 --- /dev/null +++ b/queue-3.10/series @@ -0,0 +1 @@ +locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch diff --git a/queue-3.14/series b/queue-3.14/series new file mode 100644 index 00000000000..18b7bd94c8e --- /dev/null +++ b/queue-3.14/series @@ -0,0 +1,2 @@ +bio-return-eintr-if-copying-to-user-space-got-interrupted.patch +locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..aa442a6486b --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,7 @@ +use-d_seq-to-get-coherency-between-d_inode-and-d_flags.patch +drivers-sh-restore-legacy-clock-domain-on-superh-platforms.patch +btrfs-fix-deadlock-running-delayed-iputs-at-transaction-commit-time.patch +btrfs-fix-no_space-in-write-and-rm-loop.patch +btrfs-async-thread-fix-a-use-after-free-error-for-trace.patch +drm-amdgpu-mask-out-wc-from-bo-on-unsupported-arches.patch +block-initialize-max_dev_sectors-to-0.patch