| From: Davidlohr Bueso <dave@stgolabs.net> |
| Date: Tue, 22 Mar 2016 14:27:48 -0700 |
| Subject: ipc/sem: make semctl setting sempid consistent |
| |
| commit a5f4db877177d2a3d7ae62a7bac3a5a27e083d7f upstream. |
| |
| As indicated by bug#112271, Linux sets the sempid value upon semctl, and |
| not only for semop calls. However, within semctl we only do this for |
| SETVAL, leaving SETALL without updating the field, and therefore rather |
| inconsistent behavior when compared to other Unices. |
| |
| There is really no documentation regarding this and therefore users |
| should not make assumptions. With this patch, along with updating |
| semctl.2 manpages, this scenario should become less ambiguous As such, |
| set sempid on SETALL cmd. |
| |
| Also update some in-code documentation, specifying where the sempid is |
| set. |
| |
| Passes ltp and custom testcase where a child (fork) does SETALL to the |
| set. |
| |
| Signed-off-by: Davidlohr Bueso <dbueso@suse.de> |
| Reported-by: Philip Semanchuk <linux_kernel.20.ick@spamgourmet.com> |
| Cc: Michael Kerrisk <mtk.manpages@gmail.com> |
| Cc: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com> |
| Cc: Manfred Spraul <manfred@colorfullife.com> |
| Cc: Herton R. Krzesinski <herton@redhat.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| ipc/sem.c | 13 +++++++++++-- |
| 1 file changed, 11 insertions(+), 2 deletions(-) |
| |
| --- a/ipc/sem.c |
| +++ b/ipc/sem.c |
| @@ -92,7 +92,14 @@ |
| /* One semaphore structure for each semaphore in the system. */ |
| struct sem { |
| int semval; /* current value */ |
| - int sempid; /* pid of last operation */ |
| + /* |
| + * PID of the process that last modified the semaphore. For |
| + * Linux, specifically these are: |
| + * - semop |
| + * - semctl, via SETVAL and SETALL. |
| + * - at task exit when performing undo adjustments (see exit_sem). |
| + */ |
| + int sempid; |
| spinlock_t lock; /* spinlock for fine-grained semtimedop */ |
| struct list_head pending_alter; /* pending single-sop operations */ |
| /* that alter the semaphore */ |
| @@ -1469,8 +1476,10 @@ static int semctl_main(struct ipc_namesp |
| goto out_unlock; |
| } |
| |
| - for (i = 0; i < nsems; i++) |
| + for (i = 0; i < nsems; i++) { |
| sma->sem_base[i].semval = sem_io[i]; |
| + sma->sem_base[i].sempid = task_tgid_vnr(current); |
| + } |
| |
| ipc_assert_locked_object(&sma->sem_perm); |
| list_for_each_entry(un, &sma->list_id, list_id) { |