From: Greg Kroah-Hartman Date: Tue, 15 Oct 2013 23:32:00 +0000 (-0700) Subject: 3.11-stable patches X-Git-Tag: v3.10.17~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d66c7e8f6ee1f6598633f6f6d07331d9da7e977d;p=thirdparty%2Fkernel%2Fstable-queue.git 3.11-stable patches added patches: ipc-drop-ipcctl_pre_down.patch ipc-shm-cleanup-do_shmat-pasta.patch ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch ipc-shm-introduce-shmctl_nolock.patch ipc-shm-make-shmctl_nolock-lockless.patch ipc-shm-shorten-critical-region-for-shmat.patch ipc-shm-shorten-critical-region-for-shmctl.patch ipc-shm-shorten-critical-region-in-shmctl_down.patch --- diff --git a/queue-3.11/ipc-drop-ipcctl_pre_down.patch b/queue-3.11/ipc-drop-ipcctl_pre_down.patch new file mode 100644 index 00000000000..4491dedaef3 --- /dev/null +++ b/queue-3.11/ipc-drop-ipcctl_pre_down.patch @@ -0,0 +1,83 @@ +From 3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:17 -0700 +Subject: ipc: drop ipcctl_pre_down + +From: Davidlohr Bueso + +commit 3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 upstream. + +Now that sem, msgque and shm, through *_down(), all use the lockless +variant of ipcctl_pre_down(), go ahead and delete it. + +[akpm@linux-foundation.org: fix function name in kerneldoc, cleanups] +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/util.c | 24 ++++-------------------- + ipc/util.h | 3 --- + 2 files changed, 4 insertions(+), 23 deletions(-) + +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -725,7 +725,7 @@ int ipc_update_perm(struct ipc64_perm *i + } + + /** +- * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd ++ * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd + * @ns: the ipc namespace + * @ids: the table of ids where to look for the ipc + * @id: the id of the ipc to retrieve +@@ -738,29 +738,13 @@ int ipc_update_perm(struct ipc64_perm *i + * It must be called without any lock held and + * - retrieves the ipc with the given id in the given table. + * - performs some audit and permission check, depending on the given cmd +- * - returns the ipc with the ipc lock held in case of success +- * or an err-code without any lock held otherwise. ++ * - returns a pointer to the ipc object or otherwise, the corresponding error. + * + * Call holding the both the rw_mutex and the rcu read lock. + */ +-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, +- struct ipc_ids *ids, int id, int cmd, +- struct ipc64_perm *perm, int extra_perm) +-{ +- struct kern_ipc_perm *ipcp; +- +- ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm); +- if (IS_ERR(ipcp)) +- goto out; +- +- spin_lock(&ipcp->lock); +-out: +- return ipcp; +-} +- + struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns, +- struct ipc_ids *ids, int id, int cmd, +- struct ipc64_perm *perm, int extra_perm) ++ struct ipc_ids *ids, int id, int cmd, ++ struct ipc64_perm *perm, int extra_perm) + { + kuid_t euid; + int err = -EPERM; +--- a/ipc/util.h ++++ b/ipc/util.h +@@ -139,9 +139,6 @@ int ipc_update_perm(struct ipc64_perm *i + struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns, + struct ipc_ids *ids, int id, int cmd, + struct ipc64_perm *perm, int extra_perm); +-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, +- struct ipc_ids *ids, int id, int cmd, +- struct ipc64_perm *perm, int extra_perm); + + #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION + /* On IA-64, we always use the "64-bit version" of the IPC structures. */ diff --git a/queue-3.11/ipc-shm-cleanup-do_shmat-pasta.patch b/queue-3.11/ipc-shm-cleanup-do_shmat-pasta.patch new file mode 100644 index 00000000000..807f8d2f9cb --- /dev/null +++ b/queue-3.11/ipc-shm-cleanup-do_shmat-pasta.patch @@ -0,0 +1,85 @@ +From f42569b1388b1408b574a5e93a23a663647d4181 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:22 -0700 +Subject: ipc,shm: cleanup do_shmat pasta + +From: Davidlohr Bueso + +commit f42569b1388b1408b574a5e93a23a663647d4181 upstream. + +Clean up some of the messy do_shmat() spaghetti code, getting rid of +out_free and out_put_dentry labels. This makes shortening the critical +region of this function in the next patch a little easier to do and read. + +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1115,16 +1115,21 @@ long do_shmat(int shmid, char __user *sh + + err = -ENOMEM; + sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); +- if (!sfd) +- goto out_put_dentry; ++ if (!sfd) { ++ path_put(&path); ++ goto out_nattch; ++ } + + file = alloc_file(&path, f_mode, + is_file_hugepages(shp->shm_file) ? + &shm_file_operations_huge : + &shm_file_operations); + err = PTR_ERR(file); +- if (IS_ERR(file)) +- goto out_free; ++ if (IS_ERR(file)) { ++ kfree(sfd); ++ path_put(&path); ++ goto out_nattch; ++ } + + file->private_data = sfd; + file->f_mapping = shp->shm_file->f_mapping; +@@ -1150,7 +1155,7 @@ long do_shmat(int shmid, char __user *sh + addr > current->mm->start_stack - size - PAGE_SIZE * 5) + goto invalid; + } +- ++ + addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate); + *raddr = addr; + err = 0; +@@ -1174,19 +1179,12 @@ out_nattch: + else + shm_unlock(shp); + up_write(&shm_ids(ns).rw_mutex); +- +-out: + return err; + + out_unlock: + shm_unlock(shp); +- goto out; +- +-out_free: +- kfree(sfd); +-out_put_dentry: +- path_put(&path); +- goto out_nattch; ++out: ++ return err; + } + + SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) diff --git a/queue-3.11/ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch b/queue-3.11/ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch new file mode 100644 index 00000000000..e1b7b9c4566 --- /dev/null +++ b/queue-3.11/ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch @@ -0,0 +1,81 @@ +From 8b8d52ac382b17a19906b930cd69e2edb0aca8ba Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:15 -0700 +Subject: ipc,shm: introduce lockless functions to obtain the ipc object + +From: Davidlohr Bueso + +commit 8b8d52ac382b17a19906b930cd69e2edb0aca8ba upstream. + +This is the third and final patchset that deals with reducing the amount +of contention we impose on the ipc lock (kern_ipc_perm.lock). These +changes mostly deal with shared memory, previous work has already been +done for semaphores and message queues: + + http://lkml.org/lkml/2013/3/20/546 (sems) + http://lkml.org/lkml/2013/5/15/584 (mqueues) + +With these patches applied, a custom shm microbenchmark stressing shmctl +doing IPC_STAT with 4 threads a million times, reduces the execution +time by 50%. A similar run, this time with IPC_SET, reduces the +execution time from 3 mins and 35 secs to 27 seconds. + +Patches 1-8: replaces blindly taking the ipc lock for a smarter +combination of rcu and ipc_obtain_object, only acquiring the spinlock +when updating. + +Patch 9: renames the ids rw_mutex to rwsem, which is what it already was. + +Patch 10: is a trivial mqueue leftover cleanup + +Patch 11: adds a brief lock scheme description, requested by Andrew. + +This patch: + +Add shm_obtain_object() and shm_obtain_object_check(), which will allow us +to get the ipc object without acquiring the lock. Just as with other +forms of ipc, these functions are basically wrappers around +ipc_obtain_object*(). + +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -124,6 +124,26 @@ void __init shm_init (void) + IPC_SHM_IDS, sysvipc_shm_proc_show); + } + ++static inline struct shmid_kernel *shm_obtain_object(struct ipc_namespace *ns, int id) ++{ ++ struct kern_ipc_perm *ipcp = ipc_obtain_object(&shm_ids(ns), id); ++ ++ if (IS_ERR(ipcp)) ++ return ERR_CAST(ipcp); ++ ++ return container_of(ipcp, struct shmid_kernel, shm_perm); ++} ++ ++static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace *ns, int id) ++{ ++ struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&shm_ids(ns), id); ++ ++ if (IS_ERR(ipcp)) ++ return ERR_CAST(ipcp); ++ ++ return container_of(ipcp, struct shmid_kernel, shm_perm); ++} ++ + /* + * shm_lock_(check_) routines are called in the paths where the rw_mutex + * is not necessarily held. diff --git a/queue-3.11/ipc-shm-introduce-shmctl_nolock.patch b/queue-3.11/ipc-shm-introduce-shmctl_nolock.patch new file mode 100644 index 00000000000..0f402b3dd67 --- /dev/null +++ b/queue-3.11/ipc-shm-introduce-shmctl_nolock.patch @@ -0,0 +1,118 @@ +From 68eccc1dc345539d589ae78ee43b835c1a06a134 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:18 -0700 +Subject: ipc,shm: introduce shmctl_nolock + +From: Davidlohr Bueso + +commit 68eccc1dc345539d589ae78ee43b835c1a06a134 upstream. + +Similar to semctl and msgctl, when calling msgctl, the *_INFO and *_STAT +commands can be performed without acquiring the ipc object. + +Add a shmctl_nolock() function and move the logic of *_INFO and *_STAT out +of msgctl(). Since we are just moving functionality, this change still +takes the lock and it will be properly lockless in the next patch. + +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 57 +++++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 39 insertions(+), 18 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -827,29 +827,24 @@ out_up: + return err; + } + +-SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) ++static int shmctl_nolock(struct ipc_namespace *ns, int shmid, ++ int cmd, int version, void __user *buf) + { ++ int err; + struct shmid_kernel *shp; +- int err, version; +- struct ipc_namespace *ns; + +- if (cmd < 0 || shmid < 0) { +- err = -EINVAL; +- goto out; ++ /* preliminary security checks for *_INFO */ ++ if (cmd == IPC_INFO || cmd == SHM_INFO) { ++ err = security_shm_shmctl(NULL, cmd); ++ if (err) ++ return err; + } + +- version = ipc_parse_version(&cmd); +- ns = current->nsproxy->ipc_ns; +- +- switch (cmd) { /* replace with proc interface ? */ ++ switch (cmd) { + case IPC_INFO: + { + struct shminfo64 shminfo; + +- err = security_shm_shmctl(NULL, cmd); +- if (err) +- return err; +- + memset(&shminfo, 0, sizeof(shminfo)); + shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; + shminfo.shmmax = ns->shm_ctlmax; +@@ -871,10 +866,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, + { + struct shm_info shm_info; + +- err = security_shm_shmctl(NULL, cmd); +- if (err) +- return err; +- + memset(&shm_info, 0, sizeof(shm_info)); + down_read(&shm_ids(ns).rw_mutex); + shm_info.used_ids = shm_ids(ns).in_use; +@@ -935,6 +926,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, + err = result; + goto out; + } ++ default: ++ return -EINVAL; ++ } ++ ++out_unlock: ++ shm_unlock(shp); ++out: ++ return err; ++} ++ ++SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) ++{ ++ struct shmid_kernel *shp; ++ int err, version; ++ struct ipc_namespace *ns; ++ ++ if (cmd < 0 || shmid < 0) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ version = ipc_parse_version(&cmd); ++ ns = current->nsproxy->ipc_ns; ++ ++ switch (cmd) { ++ case IPC_INFO: ++ case SHM_INFO: ++ case SHM_STAT: ++ case IPC_STAT: ++ return shmctl_nolock(ns, shmid, cmd, version, buf); + case SHM_LOCK: + case SHM_UNLOCK: + { diff --git a/queue-3.11/ipc-shm-make-shmctl_nolock-lockless.patch b/queue-3.11/ipc-shm-make-shmctl_nolock-lockless.patch new file mode 100644 index 00000000000..587f936b023 --- /dev/null +++ b/queue-3.11/ipc-shm-make-shmctl_nolock-lockless.patch @@ -0,0 +1,86 @@ +From c97cb9ccab8c85428ec21eff690642ad2ce1fa8a Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:20 -0700 +Subject: ipc,shm: make shmctl_nolock lockless + +From: Davidlohr Bueso + +commit c97cb9ccab8c85428ec21eff690642ad2ce1fa8a upstream. + +While the INFO cmd doesn't take the ipc lock, the STAT commands do acquire +it unnecessarily. We can do the permissions and security checks only +holding the rcu lock. + +[akpm@linux-foundation.org: coding-style fixes] +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -889,27 +889,31 @@ static int shmctl_nolock(struct ipc_name + struct shmid64_ds tbuf; + int result; + ++ rcu_read_lock(); + if (cmd == SHM_STAT) { +- shp = shm_lock(ns, shmid); ++ shp = shm_obtain_object(ns, shmid); + if (IS_ERR(shp)) { + err = PTR_ERR(shp); +- goto out; ++ goto out_unlock; + } + result = shp->shm_perm.id; + } else { +- shp = shm_lock_check(ns, shmid); ++ shp = shm_obtain_object_check(ns, shmid); + if (IS_ERR(shp)) { + err = PTR_ERR(shp); +- goto out; ++ goto out_unlock; + } + result = 0; + } ++ + err = -EACCES; + if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) + goto out_unlock; ++ + err = security_shm_shmctl(shp, cmd); + if (err) + goto out_unlock; ++ + memset(&tbuf, 0, sizeof(tbuf)); + kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); + tbuf.shm_segsz = shp->shm_segsz; +@@ -919,8 +923,9 @@ static int shmctl_nolock(struct ipc_name + tbuf.shm_cpid = shp->shm_cprid; + tbuf.shm_lpid = shp->shm_lprid; + tbuf.shm_nattch = shp->shm_nattch; +- shm_unlock(shp); +- if(copy_shmid_to_user (buf, &tbuf, version)) ++ rcu_read_unlock(); ++ ++ if (copy_shmid_to_user(buf, &tbuf, version)) + err = -EFAULT; + else + err = result; +@@ -931,7 +936,7 @@ static int shmctl_nolock(struct ipc_name + } + + out_unlock: +- shm_unlock(shp); ++ rcu_read_unlock(); + out: + return err; + } diff --git a/queue-3.11/ipc-shm-shorten-critical-region-for-shmat.patch b/queue-3.11/ipc-shm-shorten-critical-region-for-shmat.patch new file mode 100644 index 00000000000..d1bc7744f08 --- /dev/null +++ b/queue-3.11/ipc-shm-shorten-critical-region-for-shmat.patch @@ -0,0 +1,77 @@ +From c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:23 -0700 +Subject: ipc,shm: shorten critical region for shmat + +From: Davidlohr Bueso + +commit c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 upstream. + +Similar to other system calls, acquire the kern_ipc_perm lock after doing +the initial permission and security checks. + +[sasha.levin@oracle.com: dont leave do_shmat with rcu lock held] +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Sasha Levin +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -19,6 +19,9 @@ + * namespaces support + * OpenVZ, SWsoft Inc. + * Pavel Emelianov ++ * ++ * Better ipc lock (kern_ipc_perm.lock) handling ++ * Davidlohr Bueso , June 2013. + */ + + #include +@@ -1093,10 +1096,11 @@ long do_shmat(int shmid, char __user *sh + * additional creator id... + */ + ns = current->nsproxy->ipc_ns; +- shp = shm_lock_check(ns, shmid); ++ rcu_read_lock(); ++ shp = shm_obtain_object_check(ns, shmid); + if (IS_ERR(shp)) { + err = PTR_ERR(shp); +- goto out; ++ goto out_unlock; + } + + err = -EACCES; +@@ -1107,11 +1111,13 @@ long do_shmat(int shmid, char __user *sh + if (err) + goto out_unlock; + ++ ipc_lock_object(&shp->shm_perm); + path = shp->shm_file->f_path; + path_get(&path); + shp->shm_nattch++; + size = i_size_read(path.dentry->d_inode); +- shm_unlock(shp); ++ ipc_unlock_object(&shp->shm_perm); ++ rcu_read_unlock(); + + err = -ENOMEM; + sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); +@@ -1182,7 +1188,7 @@ out_nattch: + return err; + + out_unlock: +- shm_unlock(shp); ++ rcu_read_unlock(); + out: + return err; + } diff --git a/queue-3.11/ipc-shm-shorten-critical-region-for-shmctl.patch b/queue-3.11/ipc-shm-shorten-critical-region-for-shmctl.patch new file mode 100644 index 00000000000..6a5a7349f40 --- /dev/null +++ b/queue-3.11/ipc-shm-shorten-critical-region-for-shmctl.patch @@ -0,0 +1,135 @@ +From 2caacaa82a51b78fc0c800e206473874094287ed Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:21 -0700 +Subject: ipc,shm: shorten critical region for shmctl + +From: Davidlohr Bueso + +commit 2caacaa82a51b78fc0c800e206473874094287ed upstream. + +With the *_INFO, *_STAT, IPC_RMID and IPC_SET commands already optimized, +deal with the remaining SHM_LOCK and SHM_UNLOCK commands. Take the +shm_perm lock after doing the initial auditing and security checks. The +rest of the logic remains unchanged. + +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 49 +++++++++++++++++++++++++------------------------ + 1 file changed, 25 insertions(+), 24 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -947,10 +947,8 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, + int err, version; + struct ipc_namespace *ns; + +- if (cmd < 0 || shmid < 0) { +- err = -EINVAL; +- goto out; +- } ++ if (cmd < 0 || shmid < 0) ++ return -EINVAL; + + version = ipc_parse_version(&cmd); + ns = current->nsproxy->ipc_ns; +@@ -961,36 +959,40 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, + case SHM_STAT: + case IPC_STAT: + return shmctl_nolock(ns, shmid, cmd, version, buf); ++ case IPC_RMID: ++ case IPC_SET: ++ return shmctl_down(ns, shmid, cmd, buf, version); + case SHM_LOCK: + case SHM_UNLOCK: + { + struct file *shm_file; + +- shp = shm_lock_check(ns, shmid); ++ rcu_read_lock(); ++ shp = shm_obtain_object_check(ns, shmid); + if (IS_ERR(shp)) { + err = PTR_ERR(shp); +- goto out; ++ goto out_unlock1; + } + + audit_ipc_obj(&(shp->shm_perm)); ++ err = security_shm_shmctl(shp, cmd); ++ if (err) ++ goto out_unlock1; + ++ ipc_lock_object(&shp->shm_perm); + if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { + kuid_t euid = current_euid(); + err = -EPERM; + if (!uid_eq(euid, shp->shm_perm.uid) && + !uid_eq(euid, shp->shm_perm.cuid)) +- goto out_unlock; ++ goto out_unlock0; + if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) +- goto out_unlock; ++ goto out_unlock0; + } + +- err = security_shm_shmctl(shp, cmd); +- if (err) +- goto out_unlock; +- + shm_file = shp->shm_file; + if (is_file_hugepages(shm_file)) +- goto out_unlock; ++ goto out_unlock0; + + if (cmd == SHM_LOCK) { + struct user_struct *user = current_user(); +@@ -999,32 +1001,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, + shp->shm_perm.mode |= SHM_LOCKED; + shp->mlock_user = user; + } +- goto out_unlock; ++ goto out_unlock0; + } + + /* SHM_UNLOCK */ + if (!(shp->shm_perm.mode & SHM_LOCKED)) +- goto out_unlock; ++ goto out_unlock0; + shmem_lock(shm_file, 0, shp->mlock_user); + shp->shm_perm.mode &= ~SHM_LOCKED; + shp->mlock_user = NULL; + get_file(shm_file); +- shm_unlock(shp); ++ ipc_unlock_object(&shp->shm_perm); ++ rcu_read_unlock(); + shmem_unlock_mapping(shm_file->f_mapping); ++ + fput(shm_file); +- goto out; +- } +- case IPC_RMID: +- case IPC_SET: +- err = shmctl_down(ns, shmid, cmd, buf, version); + return err; ++ } + default: + return -EINVAL; + } + +-out_unlock: +- shm_unlock(shp); +-out: ++out_unlock0: ++ ipc_unlock_object(&shp->shm_perm); ++out_unlock1: ++ rcu_read_unlock(); + return err; + } + diff --git a/queue-3.11/ipc-shm-shorten-critical-region-in-shmctl_down.patch b/queue-3.11/ipc-shm-shorten-critical-region-in-shmctl_down.patch new file mode 100644 index 00000000000..a2cb60b8f7c --- /dev/null +++ b/queue-3.11/ipc-shm-shorten-critical-region-in-shmctl_down.patch @@ -0,0 +1,68 @@ +From 79ccf0f8c8e04e8b9eda6645ba0f63b0915a3075 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 11 Sep 2013 14:26:16 -0700 +Subject: ipc,shm: shorten critical region in shmctl_down + +From: Davidlohr Bueso + +commit 79ccf0f8c8e04e8b9eda6645ba0f63b0915a3075 upstream. + +Instead of holding the ipc lock for the entire function, use the +ipcctl_pre_down_nolock and only acquire the lock for specific commands: +RMID and SET. + +Signed-off-by: Davidlohr Bueso +Tested-by: Sedat Dilek +Cc: Rik van Riel +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/shm.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -787,11 +787,10 @@ static int shmctl_down(struct ipc_namesp + down_write(&shm_ids(ns).rw_mutex); + rcu_read_lock(); + +- ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd, +- &shmid64.shm_perm, 0); ++ ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, ++ &shmid64.shm_perm, 0); + if (IS_ERR(ipcp)) { + err = PTR_ERR(ipcp); +- /* the ipc lock is not held upon failure */ + goto out_unlock1; + } + +@@ -799,14 +798,16 @@ static int shmctl_down(struct ipc_namesp + + err = security_shm_shmctl(shp, cmd); + if (err) +- goto out_unlock0; ++ goto out_unlock1; + + switch (cmd) { + case IPC_RMID: ++ ipc_lock_object(&shp->shm_perm); + /* do_shm_rmid unlocks the ipc object and rcu */ + do_shm_rmid(ns, ipcp); + goto out_up; + case IPC_SET: ++ ipc_lock_object(&shp->shm_perm); + err = ipc_update_perm(&shmid64.shm_perm, ipcp); + if (err) + goto out_unlock0; +@@ -814,6 +815,7 @@ static int shmctl_down(struct ipc_namesp + break; + default: + err = -EINVAL; ++ goto out_unlock1; + } + + out_unlock0: diff --git a/queue-3.11/series b/queue-3.11/series index 56c3201fe74..4b1e035ee5b 100644 --- a/queue-3.11/series +++ b/queue-3.11/series @@ -29,3 +29,11 @@ drm-radeon-dpm-off-by-one-in-si_set_mc_special_registers.patch drm-radeon-forever-loop-on-error-in-radeon_do_test_moves.patch drm-radeon-fix-typo-in-cp-dma-register-headers.patch drm-radeon-fix-hw-contexts-for-sumo2-asics.patch +ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch +ipc-shm-shorten-critical-region-in-shmctl_down.patch +ipc-drop-ipcctl_pre_down.patch +ipc-shm-introduce-shmctl_nolock.patch +ipc-shm-make-shmctl_nolock-lockless.patch +ipc-shm-shorten-critical-region-for-shmctl.patch +ipc-shm-cleanup-do_shmat-pasta.patch +ipc-shm-shorten-critical-region-for-shmat.patch