diff options
author | Manfred Spraul <manfred@colorfullife.com> | 2008-07-25 04:48:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:42 -0400 |
commit | 380af1b33b3ff92df5cda96329b58f5d1b6b5a53 (patch) | |
tree | 9a47d66c18e4aae2093a708a7509c0f188ee0bd1 /include/linux/sem.h | |
parent | a1193f8ec091cd8fd309cc2982abe4499f6f2b4d (diff) |
ipc/sem.c: rewrite undo list locking
The attached patch:
- reverses the locking order of ulp->lock and sem_lock:
Previously, it was first ulp->lock, then inside sem_lock.
Now it's the other way around.
- converts the undo structure to rcu.
Benefits:
- With the old locking order, IPC_RMID could not kfree the undo structures.
The stale entries remained in the linked lists and were released later.
- The patch fixes a a race in semtimedop(): if both IPC_RMID and a semget() that
recreates exactly the same id happen between find_alloc_undo() and sem_lock,
then semtimedop() would access already kfree'd memory.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Reviewed-by: Nadia Derbey <Nadia.Derbey@bull.net>
Cc: Pierre Peiffer <peifferp@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/sem.h')
-rw-r--r-- | include/linux/sem.h | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/include/linux/sem.h b/include/linux/sem.h index d42599395d79..1b191c176bcd 100644 --- a/include/linux/sem.h +++ b/include/linux/sem.h | |||
@@ -78,6 +78,7 @@ struct seminfo { | |||
78 | 78 | ||
79 | #ifdef __KERNEL__ | 79 | #ifdef __KERNEL__ |
80 | #include <asm/atomic.h> | 80 | #include <asm/atomic.h> |
81 | #include <linux/rcupdate.h> | ||
81 | 82 | ||
82 | struct task_struct; | 83 | struct task_struct; |
83 | 84 | ||
@@ -114,7 +115,10 @@ struct sem_queue { | |||
114 | * when the process exits. | 115 | * when the process exits. |
115 | */ | 116 | */ |
116 | struct sem_undo { | 117 | struct sem_undo { |
117 | struct list_head list_proc; /* per-process list: all undos from one process */ | 118 | struct list_head list_proc; /* per-process list: all undos from one process. */ |
119 | /* rcu protected */ | ||
120 | struct rcu_head rcu; /* rcu struct for sem_undo() */ | ||
121 | struct sem_undo_list *ulp; /* sem_undo_list for the process */ | ||
118 | struct list_head list_id; /* per semaphore array list: all undos for one array */ | 122 | struct list_head list_id; /* per semaphore array list: all undos for one array */ |
119 | int semid; /* semaphore set identifier */ | 123 | int semid; /* semaphore set identifier */ |
120 | short * semadj; /* array of adjustments, one per semaphore */ | 124 | short * semadj; /* array of adjustments, one per semaphore */ |