summaryrefslogtreecommitdiff
blob: 66e4520909ed1a14415c45872371aa01e3abaca8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/12/13 08:30:17-08:00 hugh@veritas.com 
#   [PATCH] shmctl SHM_LOCK perms
#   
#   Michael Kerrisk has observed that at present any process can SHM_LOCK any
#   shm segment of size within process RLIMIT_MEMLOCK, despite having no
#   permissions on the segment: surprising, though not obviously evil.  And any
#   process can SHM_UNLOCK any shm segment, despite no permissions on it: that
#   is surely wrong.
#   
#   Unless CAP_IPC_LOCK, restrict both SHM_LOCK and SHM_UNLOCK to when the
#   process euid matches the shm owner or creator: that seems the least
#   surprising behaviour, which could be relaxed if a need appears later.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/shm.c
#   2004/12/13 02:47:27-08:00 hugh@veritas.com +10 -5
#   shmctl SHM_LOCK perms
# 
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	2004-12-20 10:32:59 -08:00
+++ b/ipc/shm.c	2004-12-20 10:32:59 -08:00
@@ -511,11 +511,6 @@
 	case SHM_LOCK:
 	case SHM_UNLOCK:
 	{
-		/* Allow superuser to lock segment in memory */
-		if (!can_do_mlock() && cmd == SHM_LOCK) {
-			err = -EPERM;
-			goto out;
-		}
 		shp = shm_lock(shmid);
 		if(shp==NULL) {
 			err = -EINVAL;
@@ -524,6 +519,16 @@
 		err = shm_checkid(shp,shmid);
 		if(err)
 			goto out_unlock;
+
+		if (!capable(CAP_IPC_LOCK)) {
+			err = -EPERM;
+			if (current->euid != shp->shm_perm.uid &&
+			    current->euid != shp->shm_perm.cuid)
+				goto out_unlock;
+			if (cmd == SHM_LOCK &&
+			    !current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+				goto out_unlock;
+		}
 
 		err = security_shm_shmctl(shp, cmd);
 		if (err)