mirror of
https://github.com/torvalds/linux.git
synced 2026-03-14 12:36:13 +01:00
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.
Fixes:
|
||
|---|---|---|
| .. | ||
| compat.c | ||
| compat_mq.c | ||
| ipc_sysctl.c | ||
| Makefile | ||
| mq_sysctl.c | ||
| mqueue.c | ||
| msg.c | ||
| msgutil.c | ||
| namespace.c | ||
| sem.c | ||
| shm.c | ||
| syscall.c | ||
| util.c | ||
| util.h | ||