summaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2008-11-20 00:36:08 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-20 03:49:57 +0100
commite00b4ff7ebf098b11b11be403921c1cf41d9e321 (patch)
treeca0b085b803128efea92ab98723adcefb35556fc /ipc/util.c
parentdrivers/video: bad error test before a dereference (diff)
downloadlinux-e00b4ff7ebf098b11b11be403921c1cf41d9e321.tar.xz
linux-e00b4ff7ebf098b11b11be403921c1cf41d9e321.zip
sysvipc: fix the ipc structures initialization
A problem was found while reviewing the code after Bugzilla bug http://bugzilla.kernel.org/show_bug.cgi?id=11796. In ipc_addid(), the newly allocated ipc structure is inserted into the ipcs tree (i.e made visible to readers) without locking it. This is not correct since its initialization continues after it has been inserted in the tree. This patch moves the ipc structure lock initialization + locking before the actual insertion. Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net> Reported-by: Clement Calmels <cboulte@gmail.com> Cc: Manfred Spraul <manfred@colorfullife.com> Cc: <stable@kernel.org> [2.6.27.x] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 49b3ea615dc5..361fd1c96fcf 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -266,9 +266,17 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
if (ids->in_use >= size)
return -ENOSPC;
+ spin_lock_init(&new->lock);
+ new->deleted = 0;
+ rcu_read_lock();
+ spin_lock(&new->lock);
+
err = idr_get_new(&ids->ipcs_idr, new, &id);
- if (err)
+ if (err) {
+ spin_unlock(&new->lock);
+ rcu_read_unlock();
return err;
+ }
ids->in_use++;
@@ -280,10 +288,6 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
ids->seq = 0;
new->id = ipc_buildid(id, new->seq);
- spin_lock_init(&new->lock);
- new->deleted = 0;
- rcu_read_lock();
- spin_lock(&new->lock);
return id;
}