* ipc: BUG: sem_unlock unlocks non-locked lock
@ 2016-12-16 9:33 Dmitry Vyukov
2016-12-18 16:28 ` Davidlohr Bueso
0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Vyukov @ 2016-12-16 9:33 UTC (permalink / raw)
To: Andrew Morton, Davidlohr Bueso, Ingo Molnar, manfred,
Peter Zijlstra, fabf, kernel, LKML
Cc: syzkaller
Hello,
The following program causes BUG: bad unlock balance detected!
https://gist.githubusercontent.com/dvyukov/d0e5efefe4d7d6daed829f5c3ca26a40/raw/08d0a261fe3c987bed04fbf267e08ba04bd533ea/gistfile1.txt
On commit 5cc60aeedf315a7513f92e98314e86d515b986d1 (Dec 14).
[ BUG: bad unlock balance detected! ]
4.9.0+ #89 Not tainted
-------------------------------------
a.out/6330 is trying to release lock (&(&new->lock)->rlock) at:
[<ffffffff8316d150>] spin_unlock include/linux/spinlock.h:347 [inline]
[<ffffffff8316d150>] ipc_unlock_object ipc/util.h:175 [inline]
[<ffffffff8316d150>] sem_unlock ipc/sem.c:404 [inline]
[<ffffffff8316d150>] SYSC_semtimedop+0x22f0/0x4410 ipc/sem.c:2004
but there are no more locks to release!
other info that might help us debug this:
2 locks held by a.out/6330:
#0: (rcu_read_lock){......}, at: [<ffffffff8316c9c2>]
SYSC_semtimedop+0x1b62/0x4410 ipc/sem.c:1968
#1: (&(&sma->sem_base[i].lock)->rlock){+.+...}, at:
[<ffffffff8316d1e4>] spin_lock include/linux/spinlock.h:302 [inline]
#1: (&(&sma->sem_base[i].lock)->rlock){+.+...}, at:
[<ffffffff8316d1e4>] sem_lock ipc/sem.c:362 [inline]
#1: (&(&sma->sem_base[i].lock)->rlock){+.+...}, at:
[<ffffffff8316d1e4>] SYSC_semtimedop+0x2384/0x4410 ipc/sem.c:1980
stack backtrace:
CPU: 1 PID: 6330 Comm: a.out Not tainted 4.9.0+ #89
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:15 [inline]
dump_stack+0x2ee/0x3ef lib/dump_stack.c:51
print_unlock_imbalance_bug+0x12f/0x140 kernel/locking/lockdep.c:3391
__lock_release kernel/locking/lockdep.c:3533 [inline]
lock_release+0xa21/0xf00 kernel/locking/lockdep.c:3772
__raw_spin_unlock include/linux/spinlock_api_smp.h:152 [inline]
_raw_spin_unlock+0x1f/0x40 kernel/locking/spinlock.c:183
spin_unlock include/linux/spinlock.h:347 [inline]
ipc_unlock_object ipc/util.h:175 [inline]
sem_unlock ipc/sem.c:404 [inline]
SYSC_semtimedop+0x22f0/0x4410 ipc/sem.c:2004
SyS_semtimedop ipc/sem.c:1755 [inline]
SYSC_semop ipc/sem.c:2015 [inline]
SyS_semop+0x2b/0x40 ipc/sem.c:2012
entry_SYSCALL_64_fastpath+0x23/0xc6
RIP: 0033:0x44dc19
RSP: 002b:00007fa18086ec88 EFLAGS: 00000206 ORIG_RAX: 0000000000000041
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000000000044dc19
RDX: 0000000000000001 RSI: 0000000020002ff0 RDI: 0000000000008001
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000206 R12: 0000000000000000
R13: 0000000000000000 R14: 00007fa18086f9c0 R15: 00007fa18086f700
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: ipc: BUG: sem_unlock unlocks non-locked lock 2016-12-16 9:33 ipc: BUG: sem_unlock unlocks non-locked lock Dmitry Vyukov @ 2016-12-18 16:28 ` Davidlohr Bueso 2016-12-18 16:29 ` Davidlohr Bueso 0 siblings, 1 reply; 8+ messages in thread From: Davidlohr Bueso @ 2016-12-18 16:28 UTC (permalink / raw) To: Dmitry Vyukov Cc: Andrew Morton, Ingo Molnar, manfred, Peter Zijlstra, fabf, kernel, LKML, syzkaller On Fri, 16 Dec 2016, Dmitry Vyukov wrote: >[ BUG: bad unlock balance detected! ] >4.9.0+ #89 Not tainted Thanks for the report, I can reproduce the issue as of (which I obviously should have tested with lockdep): 370b262c896 (ipc/sem: avoid idr tree lookup for interrupted semop) I need to think more about it this evening, but I believe the issue to be the potentially bogus locknum in the unlock path, as we are calling sem_lock without updating the variable. I'll send a patch after more testing. This fixes it for me: diff --git a/ipc/sem.c b/ipc/sem.c index e08b94851922..fba6139e7208 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } rcu_read_lock(); - sem_lock(sma, sops, nsops); + sem_lock(sma, sops, nsops); if (!ipc_valid_object(&sma->sem_perm)) goto out_unlock_free; Thanks, Davidlohr ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: ipc: BUG: sem_unlock unlocks non-locked lock 2016-12-18 16:28 ` Davidlohr Bueso @ 2016-12-18 16:29 ` Davidlohr Bueso 2016-12-18 18:32 ` Manfred Spraul 0 siblings, 1 reply; 8+ messages in thread From: Davidlohr Bueso @ 2016-12-18 16:29 UTC (permalink / raw) To: Dmitry Vyukov Cc: Andrew Morton, Ingo Molnar, manfred, Peter Zijlstra, fabf, kernel, LKML, syzkaller On Sun, 18 Dec 2016, Bueso wrote: >On Fri, 16 Dec 2016, Dmitry Vyukov wrote: > >>[ BUG: bad unlock balance detected! ] >>4.9.0+ #89 Not tainted > >Thanks for the report, I can reproduce the issue as of (which I obviously >should have tested with lockdep): > >370b262c896 (ipc/sem: avoid idr tree lookup for interrupted semop) > >I need to think more about it this evening, but I believe the issue to be >the potentially bogus locknum in the unlock path, as we are calling sem_lock >without updating the variable. I'll send a patch after more testing. This >fixes it for me: > >diff --git a/ipc/sem.c b/ipc/sem.c >index e08b94851922..fba6139e7208 100644 >--- a/ipc/sem.c >+++ b/ipc/sem.c >@@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, > } > > rcu_read_lock(); >- sem_lock(sma, sops, nsops); >+ sem_lock(sma, sops, nsops); *sigh*, that would be: locknum = sem_lock(sma, sops, nsops); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: ipc: BUG: sem_unlock unlocks non-locked lock 2016-12-18 16:29 ` Davidlohr Bueso @ 2016-12-18 18:32 ` Manfred Spraul 2016-12-18 18:38 ` [PATCH] ipc/sem.c: fix semop()/semop() locking failure Manfred Spraul 2016-12-20 6:34 ` [PATCH v2] ipc/sem.c: fix incorrect sem_lock pairing Manfred Spraul 0 siblings, 2 replies; 8+ messages in thread From: Manfred Spraul @ 2016-12-18 18:32 UTC (permalink / raw) To: Davidlohr Bueso, Dmitry Vyukov Cc: Andrew Morton, Ingo Molnar, Peter Zijlstra, fabf, kernel, LKML, syzkaller On 12/18/2016 05:29 PM, Davidlohr Bueso wrote: > On Sun, 18 Dec 2016, Bueso wrote: > >> On Fri, 16 Dec 2016, Dmitry Vyukov wrote: >> >>> [ BUG: bad unlock balance detected! ] >>> 4.9.0+ #89 Not tainted >> >> Thanks for the report, I can reproduce the issue as of (which I >> obviously >> should have tested with lockdep): >> >> 370b262c896 (ipc/sem: avoid idr tree lookup for interrupted semop) >> >> I need to think more about it this evening, but I believe the issue >> to be >> the potentially bogus locknum in the unlock path, as we are calling >> sem_lock >> without updating the variable. I'll send a patch after more testing. >> This >> fixes it for me: >> >> diff --git a/ipc/sem.c b/ipc/sem.c >> index e08b94851922..fba6139e7208 100644 >> --- a/ipc/sem.c >> +++ b/ipc/sem.c >> @@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct >> sembuf __user *, tsops, >> } >> >> rcu_read_lock(); >> - sem_lock(sma, sops, nsops); >> + sem_lock(sma, sops, nsops); > > *sigh*, that would be: > locknum = sem_lock(sma, sops, nsops); Yes, I can confirm that this fixes the issue. Reproducing is simple: - task A: single semop semop(), sleeps - task B: multi semop semop(), sleeps - task A woken up by signal/timeout I'll send a patch. -- Manfred ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] ipc/sem.c: fix semop()/semop() locking failure 2016-12-18 18:32 ` Manfred Spraul @ 2016-12-18 18:38 ` Manfred Spraul 2016-12-19 3:45 ` Davidlohr Bueso 2016-12-20 6:34 ` [PATCH v2] ipc/sem.c: fix incorrect sem_lock pairing Manfred Spraul 1 sibling, 1 reply; 8+ messages in thread From: Manfred Spraul @ 2016-12-18 18:38 UTC (permalink / raw) To: LKML, Andrew Morton, Davidlohr Bueso Cc: 1vier1, dvyukov, mingo, peterz, fabf, kernel, syzkaller, Manfred Spraul Based on the syzcaller test case from dvyukov: https://gist.githubusercontent.com/dvyukov/d0e5efefe4d7d6daed829f5c3ca26a40/raw/08d0a261fe3c987bed04fbf267e08ba04bd533ea/gistfile1.txt The slow (i.e.: failure to acquire) syscall exit from semtimedop() incorrectly assumed that the the same lock is acquired as it was at the initial syscall entry. This is wrong: - thread A: single semop semop(), sleeps - thread B: multi semop semop(), sleeps - thread A: woken up by signal/timeout With this sequence, the initial sem_lock() call locks the per-semaphore spinlock, the call at the syscall return locks the global spinlock. The fix is trivial: Use the return value from sem_lock. Reported-by: dvyukov@google.com Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Fixes: 370b262c896e ("ipc/sem: avoid idr tree lookup for interrupted semop") Cc: dave@stgolabs.net --- ipc/sem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/sem.c b/ipc/sem.c index e08b948..3ec5742 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } rcu_read_lock(); - sem_lock(sma, sops, nsops); + locknum = sem_lock(sma, sops, nsops); if (!ipc_valid_object(&sma->sem_perm)) goto out_unlock_free; -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] ipc/sem.c: fix semop()/semop() locking failure 2016-12-18 18:38 ` [PATCH] ipc/sem.c: fix semop()/semop() locking failure Manfred Spraul @ 2016-12-19 3:45 ` Davidlohr Bueso 2017-01-07 4:45 ` Mike Galbraith 0 siblings, 1 reply; 8+ messages in thread From: Davidlohr Bueso @ 2016-12-19 3:45 UTC (permalink / raw) To: Manfred Spraul Cc: LKML, Andrew Morton, 1vier1, dvyukov, mingo, peterz, fabf, kernel, syzkaller Nit: the title is a bit unclear. How about: ipc/sem.: fix semop() locking imbalance Otherwise, Ack. Thanks, Davidlohr ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ipc/sem.c: fix semop()/semop() locking failure 2016-12-19 3:45 ` Davidlohr Bueso @ 2017-01-07 4:45 ` Mike Galbraith 0 siblings, 0 replies; 8+ messages in thread From: Mike Galbraith @ 2017-01-07 4:45 UTC (permalink / raw) To: Davidlohr Bueso, Manfred Spraul Cc: LKML, Andrew Morton, 1vier1, dvyukov, mingo, peterz, fabf, kernel, syzkaller On Sun, 2016-12-18 at 19:45 -0800, Davidlohr Bueso wrote: > Nit: the title is a bit unclear. How about: > > ipc/sem.: fix semop() locking imbalance > > Otherwise, Ack. (notices patchlet _not_ flying upstream... s/failure/imbalance?) ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2] ipc/sem.c: fix incorrect sem_lock pairing 2016-12-18 18:32 ` Manfred Spraul 2016-12-18 18:38 ` [PATCH] ipc/sem.c: fix semop()/semop() locking failure Manfred Spraul @ 2016-12-20 6:34 ` Manfred Spraul 1 sibling, 0 replies; 8+ messages in thread From: Manfred Spraul @ 2016-12-20 6:34 UTC (permalink / raw) To: LKML, Andrew Morton, Davidlohr Bueso Cc: 1vier1, dvyukov, mingo, peterz, fabf, kernel, syzkaller, Manfred Spraul Based on the syzcaller test case from dvyukov: https://gist.githubusercontent.com/dvyukov/d0e5efefe4d7d6daed829f5c3ca26a40/raw/08d0a261fe3c987bed04fbf267e08ba04bd533ea/gistfile1.txt The slow (i.e.: failure to acquire) syscall exit from semtimedop() incorrectly assumed that the the same lock is acquired as it was at the initial syscall entry. This is wrong: - thread A: single semop semop(), sleeps - thread B: multi semop semop(), sleeps - thread A: woken up by signal/timeout With this sequence, the initial sem_lock() call locks the per-semaphore spinlock, and it is unlocked with sem_unlock(). The call at the syscall return locks the global spinlock. Because locknum is not updated, the following sem_unlock() call unlocks the per-semaphore spinlock, which is actually not locked. The fix is trivial: Use the return value from sem_lock. Reported-by: dvyukov@google.com Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Fixes: 370b262c896e ("ipc/sem: avoid idr tree lookup for interrupted semop") Cc: dave@stgolabs.net --- Patch V2: - subject line updated - documentation slightly updated ipc/sem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/sem.c b/ipc/sem.c index e08b948..3ec5742 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } rcu_read_lock(); - sem_lock(sma, sops, nsops); + locknum = sem_lock(sma, sops, nsops); if (!ipc_valid_object(&sma->sem_perm)) goto out_unlock_free; -- 2.7.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2017-01-07 4:45 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-12-16 9:33 ipc: BUG: sem_unlock unlocks non-locked lock Dmitry Vyukov 2016-12-18 16:28 ` Davidlohr Bueso 2016-12-18 16:29 ` Davidlohr Bueso 2016-12-18 18:32 ` Manfred Spraul 2016-12-18 18:38 ` [PATCH] ipc/sem.c: fix semop()/semop() locking failure Manfred Spraul 2016-12-19 3:45 ` Davidlohr Bueso 2017-01-07 4:45 ` Mike Galbraith 2016-12-20 6:34 ` [PATCH v2] ipc/sem.c: fix incorrect sem_lock pairing Manfred Spraul
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox