Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Aug 2004 22:13:28 -0400 (EDT)
From:      Stephan Uphoff <ups@tree.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/69934: lockmgr can concurrently grant two exclusive locks
Message-ID:  <200408030213.i732DSxH097394@palm.tree.com>
Resent-Message-ID: <200408030220.i732KNRj035210@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         69934
>Category:       kern
>Synopsis:       lockmgr can concurrently grant two exclusive locks
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 03 02:20:23 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Stephan Uphoff
>Release:        FreeBSD 5.2.1-RELEASE-p5 i386
>Organization:
>Environment:
System: FreeBSD palm.tree.com 5.2.1-RELEASE-p5 FreeBSD 5.2.1-RELEASE-p5 #2: Fri May 7 20:06:27 EDT 2004 ups@palm.tree.com:/usr/obj/usr/src/sys/PALM i386


	
>Description:
Upgrading a lock does not play well together with acquiring
an exclusive lock and can lead to two threads being
granted exclusive access.

Problematic sequence:
Thread A acquires a previous unlocked lock in shared mode.
Thread B tries to acquire the same lock in exclusive mode
and blocks.
Thread A upgrades its lock - waking up thread B.
Thread B wakes up and also acquires the same lock as it only checks
if the lock is not shared or if someone wants to upgrade the lock
and not if someone already upgraded the lock to an exclusive lock.


>How-To-Repeat:
	
>Fix:

Minimal patch:
--------------

diff -u -r1.73 kern_lock.c
--- kern_lock.c	23 Jul 2004 20:12:56 -0000	1.73
+++ kern_lock.c	3 Aug 2004 01:38:07 -0000
@@ -389,7 +389,7 @@
 		/*
 		 * Wait for shared locks and upgrades to finish.
 		 */
-		error = acquire(&lkp, extflags, LK_WANT_UPGRADE | LK_SHARE_NONZERO);
+		error = acquire(&lkp, extflags, LK_HAVE_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO);
 		lkp->lk_flags &= ~LK_WANT_EXCL;
 		if (error)
 			break;


Better Patch:
-------------

diff -u -r1.73 kern_lock.c
--- kern_lock.c	23 Jul 2004 20:12:56 -0000	1.73
+++ kern_lock.c	3 Aug 2004 01:51:34 -0000
@@ -382,14 +382,14 @@
 		/*
 		 * Try to acquire the want_exclusive flag.
 		 */
-		error = acquire(&lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL));
+		error = acquire(&lkp, extflags,  LK_WANT_EXCL);
 		if (error)
 			break;
 		lkp->lk_flags |= LK_WANT_EXCL;
 		/*
 		 * Wait for shared locks and upgrades to finish.
 		 */
-		error = acquire(&lkp, extflags, LK_WANT_UPGRADE | LK_SHARE_NONZERO);
+		error = acquire(&lkp, extflags, LK_HAVE_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO);
 		lkp->lk_flags &= ~LK_WANT_EXCL;
 		if (error)
 			break;
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200408030213.i732DSxH097394>