diff options
Diffstat (limited to 'kernel/capability.c')
-rw-r--r-- | kernel/capability.c | 195 |
1 files changed, 96 insertions, 99 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 4e350a36ed6a..cbc5fd60c0f3 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -3,9 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997 Andrew Main <zefram@fysh.org> | 4 | * Copyright (C) 1997 Andrew Main <zefram@fysh.org> |
5 | * | 5 | * |
6 | * Integrated into 2.1.97+, Andrew G. Morgan <morgan@transmeta.com> | 6 | * Integrated into 2.1.97+, Andrew G. Morgan <morgan@kernel.org> |
7 | * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> | 7 | * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
@@ -14,9 +14,6 @@ | |||
14 | #include <linux/syscalls.h> | 14 | #include <linux/syscalls.h> |
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | 16 | ||
17 | unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ | ||
18 | kernel_cap_t cap_bset = CAP_INIT_EFF_SET; | ||
19 | |||
20 | /* | 17 | /* |
21 | * This lock protects task->cap_* for all tasks including current. | 18 | * This lock protects task->cap_* for all tasks including current. |
22 | * Locking rule: acquire this prior to tasklist_lock. | 19 | * Locking rule: acquire this prior to tasklist_lock. |
@@ -40,49 +37,49 @@ static DEFINE_SPINLOCK(task_capability_lock); | |||
40 | */ | 37 | */ |
41 | asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) | 38 | asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) |
42 | { | 39 | { |
43 | int ret = 0; | 40 | int ret = 0; |
44 | pid_t pid; | 41 | pid_t pid; |
45 | __u32 version; | 42 | __u32 version; |
46 | struct task_struct *target; | 43 | struct task_struct *target; |
47 | struct __user_cap_data_struct data; | 44 | struct __user_cap_data_struct data; |
48 | 45 | ||
49 | if (get_user(version, &header->version)) | 46 | if (get_user(version, &header->version)) |
50 | return -EFAULT; | 47 | return -EFAULT; |
51 | 48 | ||
52 | if (version != _LINUX_CAPABILITY_VERSION) { | 49 | if (version != _LINUX_CAPABILITY_VERSION) { |
53 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | 50 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) |
54 | return -EFAULT; | 51 | return -EFAULT; |
55 | return -EINVAL; | 52 | return -EINVAL; |
56 | } | 53 | } |
57 | 54 | ||
58 | if (get_user(pid, &header->pid)) | 55 | if (get_user(pid, &header->pid)) |
59 | return -EFAULT; | 56 | return -EFAULT; |
60 | 57 | ||
61 | if (pid < 0) | 58 | if (pid < 0) |
62 | return -EINVAL; | 59 | return -EINVAL; |
63 | 60 | ||
64 | spin_lock(&task_capability_lock); | 61 | spin_lock(&task_capability_lock); |
65 | read_lock(&tasklist_lock); | 62 | read_lock(&tasklist_lock); |
66 | 63 | ||
67 | if (pid && pid != current->pid) { | 64 | if (pid && pid != current->pid) { |
68 | target = find_task_by_pid(pid); | 65 | target = find_task_by_pid(pid); |
69 | if (!target) { | 66 | if (!target) { |
70 | ret = -ESRCH; | 67 | ret = -ESRCH; |
71 | goto out; | 68 | goto out; |
72 | } | 69 | } |
73 | } else | 70 | } else |
74 | target = current; | 71 | target = current; |
75 | 72 | ||
76 | ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted); | 73 | ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted); |
77 | 74 | ||
78 | out: | 75 | out: |
79 | read_unlock(&tasklist_lock); | 76 | read_unlock(&tasklist_lock); |
80 | spin_unlock(&task_capability_lock); | 77 | spin_unlock(&task_capability_lock); |
81 | 78 | ||
82 | if (!ret && copy_to_user(dataptr, &data, sizeof data)) | 79 | if (!ret && copy_to_user(dataptr, &data, sizeof data)) |
83 | return -EFAULT; | 80 | return -EFAULT; |
84 | 81 | ||
85 | return ret; | 82 | return ret; |
86 | } | 83 | } |
87 | 84 | ||
88 | /* | 85 | /* |
@@ -115,7 +112,7 @@ static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective, | |||
115 | } while_each_pid_task(pgrp, PIDTYPE_PGID, g); | 112 | } while_each_pid_task(pgrp, PIDTYPE_PGID, g); |
116 | 113 | ||
117 | if (!found) | 114 | if (!found) |
118 | ret = 0; | 115 | ret = 0; |
119 | return ret; | 116 | return ret; |
120 | } | 117 | } |
121 | 118 | ||
@@ -169,68 +166,68 @@ static inline int cap_set_all(kernel_cap_t *effective, | |||
169 | */ | 166 | */ |
170 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) | 167 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) |
171 | { | 168 | { |
172 | kernel_cap_t inheritable, permitted, effective; | 169 | kernel_cap_t inheritable, permitted, effective; |
173 | __u32 version; | 170 | __u32 version; |
174 | struct task_struct *target; | 171 | struct task_struct *target; |
175 | int ret; | 172 | int ret; |
176 | pid_t pid; | 173 | pid_t pid; |
177 | 174 | ||
178 | if (get_user(version, &header->version)) | 175 | if (get_user(version, &header->version)) |
179 | return -EFAULT; | 176 | return -EFAULT; |
180 | 177 | ||
181 | if (version != _LINUX_CAPABILITY_VERSION) { | 178 | if (version != _LINUX_CAPABILITY_VERSION) { |
182 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | 179 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) |
183 | return -EFAULT; | 180 | return -EFAULT; |
184 | return -EINVAL; | 181 | return -EINVAL; |
185 | } | 182 | } |
186 | 183 | ||
187 | if (get_user(pid, &header->pid)) | 184 | if (get_user(pid, &header->pid)) |
188 | return -EFAULT; | 185 | return -EFAULT; |
189 | 186 | ||
190 | if (pid && pid != current->pid && !capable(CAP_SETPCAP)) | 187 | if (pid && pid != current->pid && !capable(CAP_SETPCAP)) |
191 | return -EPERM; | 188 | return -EPERM; |
192 | 189 | ||
193 | if (copy_from_user(&effective, &data->effective, sizeof(effective)) || | 190 | if (copy_from_user(&effective, &data->effective, sizeof(effective)) || |
194 | copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || | 191 | copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || |
195 | copy_from_user(&permitted, &data->permitted, sizeof(permitted))) | 192 | copy_from_user(&permitted, &data->permitted, sizeof(permitted))) |
196 | return -EFAULT; | 193 | return -EFAULT; |
197 | 194 | ||
198 | spin_lock(&task_capability_lock); | 195 | spin_lock(&task_capability_lock); |
199 | read_lock(&tasklist_lock); | 196 | read_lock(&tasklist_lock); |
200 | 197 | ||
201 | if (pid > 0 && pid != current->pid) { | 198 | if (pid > 0 && pid != current->pid) { |
202 | target = find_task_by_pid(pid); | 199 | target = find_task_by_pid(pid); |
203 | if (!target) { | 200 | if (!target) { |
204 | ret = -ESRCH; | 201 | ret = -ESRCH; |
205 | goto out; | 202 | goto out; |
206 | } | 203 | } |
207 | } else | 204 | } else |
208 | target = current; | 205 | target = current; |
209 | 206 | ||
210 | ret = 0; | 207 | ret = 0; |
211 | 208 | ||
212 | /* having verified that the proposed changes are legal, | 209 | /* having verified that the proposed changes are legal, |
213 | we now put them into effect. */ | 210 | we now put them into effect. */ |
214 | if (pid < 0) { | 211 | if (pid < 0) { |
215 | if (pid == -1) /* all procs other than current and init */ | 212 | if (pid == -1) /* all procs other than current and init */ |
216 | ret = cap_set_all(&effective, &inheritable, &permitted); | 213 | ret = cap_set_all(&effective, &inheritable, &permitted); |
217 | 214 | ||
218 | else /* all procs in process group */ | 215 | else /* all procs in process group */ |
219 | ret = cap_set_pg(-pid, &effective, &inheritable, | 216 | ret = cap_set_pg(-pid, &effective, &inheritable, |
220 | &permitted); | 217 | &permitted); |
221 | } else { | 218 | } else { |
222 | ret = security_capset_check(target, &effective, &inheritable, | 219 | ret = security_capset_check(target, &effective, &inheritable, |
223 | &permitted); | 220 | &permitted); |
224 | if (!ret) | 221 | if (!ret) |
225 | security_capset_set(target, &effective, &inheritable, | 222 | security_capset_set(target, &effective, &inheritable, |
226 | &permitted); | 223 | &permitted); |
227 | } | 224 | } |
228 | 225 | ||
229 | out: | 226 | out: |
230 | read_unlock(&tasklist_lock); | 227 | read_unlock(&tasklist_lock); |
231 | spin_unlock(&task_capability_lock); | 228 | spin_unlock(&task_capability_lock); |
232 | 229 | ||
233 | return ret; | 230 | return ret; |
234 | } | 231 | } |
235 | 232 | ||
236 | int __capable(struct task_struct *t, int cap) | 233 | int __capable(struct task_struct *t, int cap) |