LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* linux-next: Signed-off-by missing for commit in the file-locks tree
@ 2020-03-11 14:18 Stephen Rothwell
  2020-03-11 20:06 ` Jeff Layton
  0 siblings, 1 reply; 3+ messages in thread
From: Stephen Rothwell @ 2020-03-11 14:18 UTC (permalink / raw)
  To: Jeff Layton; +Cc: Linux Next Mailing List, Linux Kernel Mailing List, NeilBrown

[-- Attachment #1: Type: text/plain, Size: 168 bytes --]

Hi all,

Commit

  e2de130a568c ("locks: reintroduce locks_delete_lock shortcut")

is missing a Signed-off-by from its author.

-- 
Cheers,
Stephen Rothwell

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: linux-next: Signed-off-by missing for commit in the file-locks tree
  2020-03-11 14:18 linux-next: Signed-off-by missing for commit in the file-locks tree Stephen Rothwell
@ 2020-03-11 20:06 ` Jeff Layton
  2020-03-11 21:50   ` [PATCH] locks: restore locks_delete_lock optimization NeilBrown
  0 siblings, 1 reply; 3+ messages in thread
From: Jeff Layton @ 2020-03-11 20:06 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Linux Next Mailing List, Linux Kernel Mailing List, NeilBrown

On Thu, 2020-03-12 at 01:18 +1100, Stephen Rothwell wrote:
> Hi all,
> 
> Commit
> 
>   e2de130a568c ("locks: reintroduce locks_delete_lock shortcut")
> 
> is missing a Signed-off-by from its author.
> 

Yes, sorry. Neil sent a draft patch and I went ahead and pulled it in
before he had a chance to fix up the changelog and add his SoB. Once he
does we'll get that fixed (and before I send this up to Linus).

Thanks,
Jeff


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] locks: restore locks_delete_lock optimization
  2020-03-11 20:06 ` Jeff Layton
@ 2020-03-11 21:50   ` NeilBrown
  0 siblings, 0 replies; 3+ messages in thread
From: NeilBrown @ 2020-03-11 21:50 UTC (permalink / raw)
  To: Jeff Layton, Stephen Rothwell
  Cc: Linux Next Mailing List, Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 3410 bytes --]


A recent patch (see Fixes: below) removed an optimization which is
important as it avoids taking a lock in a common case.

The comment justifying the optimisation was correct as far as it went,
in that if the tests succeeded, then the values would remain stable and the
test result will remain valid even without a lock.

However after the test succeeds the lock can be freed while some other
thread might have only just set ->blocker to NULL (thus allowing the
test to succeed) but has not yet called wake_up() on the wq in the lock.
If the wake_up happens after the lock is freed, a use-after-free error occurs.

This patch restores the optimization and adds sufficient locking to avoid
the use-after-free.  Rather than using the global lock - which is too
expensive - the waitq lock is used instead.  We make use of
wake_up_locked() which allows wake_up to be called while the lock is held.

Now ->blocker is set to NULL and the wq is woken all while protected by
the wq spinlock.  Before the lock is freed, ->blockers is tested for
NULL under the same spinlock.  That test must now happen before
->blocker is set to NULL, or after it is safe to free the lock.

Fixes: 6d390e4b5d48 ("locks: fix a potential use-after-free problem when wakeup a waiter")
Signed-off-by: NeilBrown <neilb@suse.de>
---
 fs/locks.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/fs/locks.c b/fs/locks.c
index 426b55d333d5..8aa04d5ac8b3 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -735,11 +735,13 @@ static void __locks_wake_up_blocks(struct file_lock *blocker)
 
 		waiter = list_first_entry(&blocker->fl_blocked_requests,
 					  struct file_lock, fl_blocked_member);
+		spin_lock(&waiter->fl_wait.lock);
 		__locks_delete_block(waiter);
 		if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
 			waiter->fl_lmops->lm_notify(waiter);
 		else
-			wake_up(&waiter->fl_wait);
+			wake_up_locked(&waiter->fl_wait);
+		spin_unlock(&waiter->fl_wait.lock);
 	}
 }
 
@@ -753,6 +755,31 @@ int locks_delete_block(struct file_lock *waiter)
 {
 	int status = -ENOENT;
 
+	/*
+	 * If fl_blocker is NULL, it won't be set again as this thread
+	 * "owns" the lock and is the only one that might try to claim
+	 * the lock.  So it is safe to test fl_blocker locklessly.
+	 * Also if fl_blocker is NULL, this waiter is not listed on
+	 * fl_blocked_requests for some lock, so no other request can
+	 * be added to the list of fl_blocked_requests for this
+	 * request.  So if fl_blocker is NULL, it is safe to
+	 * locklessly check if fl_blocked_requests is empty.  If both
+	 * of these checks succeed, there is no need to take the lock.
+	 * However, some other thread might have only *just* set
+	 * fl_blocker to NULL and it about to send a wakeup on
+	 * fl_wait, so we mustn't return too soon or we might free waiter
+	 * before that wakeup can be sent.  So take the fl_wait.lock
+	 * to serialize with the wakeup in __locks_wake_up_blocks().
+	 */
+	if (waiter->fl_blocker == NULL) {
+		spin_lock(&waiter->fl_wait.lock);
+		if (waiter->fl_blocker == NULL &&
+		    list_empty(&waiter->fl_blocked_requests)) {
+			spin_unlock(&waiter->fl_wait.lock);
+			return status;
+		}
+		spin_unlock(&waiter->fl_wait.lock);
+	}
 	spin_lock(&blocked_lock_lock);
 	if (waiter->fl_blocker)
 		status = 0;
-- 
2.25.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-03-11 21:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 14:18 linux-next: Signed-off-by missing for commit in the file-locks tree Stephen Rothwell
2020-03-11 20:06 ` Jeff Layton
2020-03-11 21:50   ` [PATCH] locks: restore locks_delete_lock optimization NeilBrown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).