]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.11.6/ipc-shm-make-shmctl_nolock-lockless.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.11.6 / ipc-shm-make-shmctl_nolock-lockless.patch
1 From c97cb9ccab8c85428ec21eff690642ad2ce1fa8a Mon Sep 17 00:00:00 2001
2 From: Davidlohr Bueso <davidlohr.bueso@hp.com>
3 Date: Wed, 11 Sep 2013 14:26:20 -0700
4 Subject: ipc,shm: make shmctl_nolock lockless
5
6 From: Davidlohr Bueso <davidlohr.bueso@hp.com>
7
8 commit c97cb9ccab8c85428ec21eff690642ad2ce1fa8a upstream.
9
10 While the INFO cmd doesn't take the ipc lock, the STAT commands do acquire
11 it unnecessarily. We can do the permissions and security checks only
12 holding the rcu lock.
13
14 [akpm@linux-foundation.org: coding-style fixes]
15 Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
16 Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
17 Cc: Rik van Riel <riel@redhat.com>
18 Cc: Manfred Spraul <manfred@colorfullife.com>
19 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
20 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
21 Cc: Mike Galbraith <efault@gmx.de>
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24 ---
25 ipc/shm.c | 19 ++++++++++++-------
26 1 file changed, 12 insertions(+), 7 deletions(-)
27
28 --- a/ipc/shm.c
29 +++ b/ipc/shm.c
30 @@ -889,27 +889,31 @@ static int shmctl_nolock(struct ipc_name
31 struct shmid64_ds tbuf;
32 int result;
33
34 + rcu_read_lock();
35 if (cmd == SHM_STAT) {
36 - shp = shm_lock(ns, shmid);
37 + shp = shm_obtain_object(ns, shmid);
38 if (IS_ERR(shp)) {
39 err = PTR_ERR(shp);
40 - goto out;
41 + goto out_unlock;
42 }
43 result = shp->shm_perm.id;
44 } else {
45 - shp = shm_lock_check(ns, shmid);
46 + shp = shm_obtain_object_check(ns, shmid);
47 if (IS_ERR(shp)) {
48 err = PTR_ERR(shp);
49 - goto out;
50 + goto out_unlock;
51 }
52 result = 0;
53 }
54 +
55 err = -EACCES;
56 if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
57 goto out_unlock;
58 +
59 err = security_shm_shmctl(shp, cmd);
60 if (err)
61 goto out_unlock;
62 +
63 memset(&tbuf, 0, sizeof(tbuf));
64 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
65 tbuf.shm_segsz = shp->shm_segsz;
66 @@ -919,8 +923,9 @@ static int shmctl_nolock(struct ipc_name
67 tbuf.shm_cpid = shp->shm_cprid;
68 tbuf.shm_lpid = shp->shm_lprid;
69 tbuf.shm_nattch = shp->shm_nattch;
70 - shm_unlock(shp);
71 - if(copy_shmid_to_user (buf, &tbuf, version))
72 + rcu_read_unlock();
73 +
74 + if (copy_shmid_to_user(buf, &tbuf, version))
75 err = -EFAULT;
76 else
77 err = result;
78 @@ -931,7 +936,7 @@ static int shmctl_nolock(struct ipc_name
79 }
80
81 out_unlock:
82 - shm_unlock(shp);
83 + rcu_read_unlock();
84 out:
85 return err;
86 }