Commit e8577d1f0329d4842e8302e289fb2c22156abef4

Authored by Manfred Spraul
Committed by Linus Torvalds
1 parent 92788ac1eb

ipc/sem.c: fully initialize sem_array before making it visible

ipc_addid() makes a new ipc identifier visible to everyone.  New objects
start as locked, so that the caller can complete the initialization
after the call.  Within struct sem_array, at least sma->sem_base and
sma->sem_nsems are accessed without any locks, therefore this approach
doesn't work.

Thus: Move the ipc_addid() to the end of the initialization.

Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Reported-by: Rik van Riel <riel@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Acked-by: Davidlohr Bueso <dave@stgolabs.net>
Acked-by: Rafael Aquini <aquini@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 8 additions and 7 deletions Side-by-side Diff

... ... @@ -507,13 +507,6 @@
507 507 return retval;
508 508 }
509 509  
510   - id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
511   - if (id < 0) {
512   - ipc_rcu_putref(sma, sem_rcu_free);
513   - return id;
514   - }
515   - ns->used_sems += nsems;
516   -
517 510 sma->sem_base = (struct sem *) &sma[1];
518 511  
519 512 for (i = 0; i < nsems; i++) {
... ... @@ -528,6 +521,14 @@
528 521 INIT_LIST_HEAD(&sma->list_id);
529 522 sma->sem_nsems = nsems;
530 523 sma->sem_ctime = get_seconds();
  524 +
  525 + id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
  526 + if (id < 0) {
  527 + ipc_rcu_putref(sma, sem_rcu_free);
  528 + return id;
  529 + }
  530 + ns->used_sems += nsems;
  531 +
531 532 sem_unlock(sma, -1);
532 533 rcu_read_unlock();
533 534