From 0f3d2b0135f4bdbfe47a99753923a64efd373d11 Mon Sep 17 00:00:00 2001 From: Rafael Aquini Date: Mon, 27 Jan 2014 17:07:01 -0800 Subject: 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 Acked-by: Rik van Riel Acked-by: Greg Thelen Reviewed-by: Davidlohr Bueso Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/shm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'ipc/shm.c') 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; -- cgit v1.2.3