diff options
author | Rafael Aquini <aquini@redhat.com> | 2014-01-28 05:07:01 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-28 09:02:39 +0400 |
commit | 0f3d2b0135f4bdbfe47a99753923a64efd373d11 (patch) | |
tree | 4b211b7502e2412aedd94400bdcb012a2b5814b3 /ipc/shm.c | |
parent | 78f5009cc35eb5e52d276a046d90ee2f41b60f8c (diff) | |
download | linux-0f3d2b0135f4bdbfe47a99753923a64efd373d11.tar.xz |
ipc: introduce ipc_valid_object() helper to sort out IPC_RMID races
After the locking semantics for the SysV IPC API got improved, a couple
of IPC_RMID race windows were opened because we ended up dropping the
'kern_ipc_perm.deleted' check performed way down in ipc_lock(). The
spotted races got sorted out by re-introducing the old test within the
racy critical sections.
This patch introduces ipc_valid_object() to consolidate the way we cope
with IPC_RMID races by using the same abstraction across the API
implementation.
Signed-off-by: Rafael Aquini <aquini@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Acked-by: Greg Thelen <gthelen@google.com>
Reviewed-by: Davidlohr Bueso <davidlohr@hp.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/ipc/shm.c b/ipc/shm.c index 7a51443a51d6..1bc68f115842 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -975,6 +975,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) goto out_unlock1; ipc_lock_object(&shp->shm_perm); + + /* check if shm_destroy() is tearing down shp */ + if (!ipc_valid_object(&shp->shm_perm)) { + err = -EIDRM; + goto out_unlock0; + } + if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { kuid_t euid = current_euid(); if (!uid_eq(euid, shp->shm_perm.uid) && @@ -989,13 +996,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) } shm_file = shp->shm_file; - - /* check if shm_destroy() is tearing down shp */ - if (shm_file == NULL) { - err = -EIDRM; - goto out_unlock0; - } - if (is_file_hugepages(shm_file)) goto out_unlock0; @@ -1116,7 +1116,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, ipc_lock_object(&shp->shm_perm); /* check if shm_destroy() is tearing down shp */ - if (shp->shm_file == NULL) { + if (!ipc_valid_object(&shp->shm_perm)) { ipc_unlock_object(&shp->shm_perm); err = -EIDRM; goto out_unlock; |