aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/capability.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:14 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:14 -0500
commit1cdcbec1a3372c0c49c59d292e708fd07b509f18 (patch)
treed1bd302c8d66862da45b494cbc766fb4caa5e23e /kernel/capability.c
parent8bbf4976b59fc9fc2861e79cab7beb3f6d647640 (diff)
CRED: Neuter sys_capset()
Take away the ability for sys_capset() to affect processes other than current. This means that current will not need to lock its own credentials when reading them against interference by other processes. This has effectively been the case for a while anyway, since: (1) Without LSM enabled, sys_capset() is disallowed. (2) With file-based capabilities, sys_capset() is neutered. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Acked-by: Andrew G. Morgan <morgan@kernel.org> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/capability.c')
-rw-r--r--kernel/capability.c227
1 files changed, 23 insertions, 204 deletions
diff --git a/kernel/capability.c b/kernel/capability.c
index adb262f83de1..58b00519624a 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -127,160 +127,6 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
127 return 0; 127 return 0;
128} 128}
129 129
130#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
131
132/*
133 * Without filesystem capability support, we nominally support one process
134 * setting the capabilities of another
135 */
136static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
137 kernel_cap_t *pIp, kernel_cap_t *pPp)
138{
139 struct task_struct *target;
140 int ret;
141
142 spin_lock(&task_capability_lock);
143 read_lock(&tasklist_lock);
144
145 if (pid && pid != task_pid_vnr(current)) {
146 target = find_task_by_vpid(pid);
147 if (!target) {
148 ret = -ESRCH;
149 goto out;
150 }
151 } else
152 target = current;
153
154 ret = security_capget(target, pEp, pIp, pPp);
155
156out:
157 read_unlock(&tasklist_lock);
158 spin_unlock(&task_capability_lock);
159
160 return ret;
161}
162
163/*
164 * cap_set_pg - set capabilities for all processes in a given process
165 * group. We call this holding task_capability_lock and tasklist_lock.
166 */
167static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
168 kernel_cap_t *inheritable,
169 kernel_cap_t *permitted)
170{
171 struct task_struct *g, *target;
172 int ret = -EPERM;
173 int found = 0;
174 struct pid *pgrp;
175
176 spin_lock(&task_capability_lock);
177 read_lock(&tasklist_lock);
178
179 pgrp = find_vpid(pgrp_nr);
180 do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
181 target = g;
182 while_each_thread(g, target) {
183 if (!security_capset_check(target, effective,
184 inheritable, permitted)) {
185 security_capset_set(target, effective,
186 inheritable, permitted);
187 ret = 0;
188 }
189 found = 1;
190 }
191 } while_each_pid_task(pgrp, PIDTYPE_PGID, g);
192
193 read_unlock(&tasklist_lock);
194 spin_unlock(&task_capability_lock);
195
196 if (!found)
197 ret = 0;
198 return ret;
199}
200
201/*
202 * cap_set_all - set capabilities for all processes other than init
203 * and self. We call this holding task_capability_lock and tasklist_lock.
204 */
205static inline int cap_set_all(kernel_cap_t *effective,
206 kernel_cap_t *inheritable,
207 kernel_cap_t *permitted)
208{
209 struct task_struct *g, *target;
210 int ret = -EPERM;
211 int found = 0;
212
213 spin_lock(&task_capability_lock);
214 read_lock(&tasklist_lock);
215
216 do_each_thread(g, target) {
217 if (target == current
218 || is_container_init(target->group_leader))
219 continue;
220 found = 1;
221 if (security_capset_check(target, effective, inheritable,
222 permitted))
223 continue;
224 ret = 0;
225 security_capset_set(target, effective, inheritable, permitted);
226 } while_each_thread(g, target);
227
228 read_unlock(&tasklist_lock);
229 spin_unlock(&task_capability_lock);
230
231 if (!found)
232 ret = 0;
233
234 return ret;
235}
236
237/*
238 * Given the target pid does not refer to the current process we
239 * need more elaborate support... (This support is not present when
240 * filesystem capabilities are configured.)
241 */
242static inline int do_sys_capset_other_tasks(pid_t pid, kernel_cap_t *effective,
243 kernel_cap_t *inheritable,
244 kernel_cap_t *permitted)
245{
246 struct task_struct *target;
247 int ret;
248
249 if (!capable(CAP_SETPCAP))
250 return -EPERM;
251
252 if (pid == -1) /* all procs other than current and init */
253 return cap_set_all(effective, inheritable, permitted);
254
255 else if (pid < 0) /* all procs in process group */
256 return cap_set_pg(-pid, effective, inheritable, permitted);
257
258 /* target != current */
259 spin_lock(&task_capability_lock);
260 read_lock(&tasklist_lock);
261
262 target = find_task_by_vpid(pid);
263 if (!target)
264 ret = -ESRCH;
265 else {
266 ret = security_capset_check(target, effective, inheritable,
267 permitted);
268
269 /* having verified that the proposed changes are legal,
270 we now put them into effect. */
271 if (!ret)
272 security_capset_set(target, effective, inheritable,
273 permitted);
274 }
275
276 read_unlock(&tasklist_lock);
277 spin_unlock(&task_capability_lock);
278
279 return ret;
280}
281
282#else /* ie., def CONFIG_SECURITY_FILE_CAPABILITIES */
283
284/* 130/*
285 * If we have configured with filesystem capability support, then the 131 * If we have configured with filesystem capability support, then the
286 * only thing that can change the capabilities of the current process 132 * only thing that can change the capabilities of the current process
@@ -315,22 +161,6 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
315} 161}
316 162
317/* 163/*
318 * With filesystem capability support configured, the kernel does not
319 * permit the changing of capabilities in one process by another
320 * process. (CAP_SETPCAP has much less broad semantics when configured
321 * this way.)
322 */
323static inline int do_sys_capset_other_tasks(pid_t pid,
324 kernel_cap_t *effective,
325 kernel_cap_t *inheritable,
326 kernel_cap_t *permitted)
327{
328 return -EPERM;
329}
330
331#endif /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
332
333/*
334 * Atomically modify the effective capabilities returning the original 164 * Atomically modify the effective capabilities returning the original
335 * value. No permission check is performed here - it is assumed that the 165 * value. No permission check is performed here - it is assumed that the
336 * caller is permitted to set the desired effective capabilities. 166 * caller is permitted to set the desired effective capabilities.
@@ -424,16 +254,14 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
424 * @data: pointer to struct that contains the effective, permitted, 254 * @data: pointer to struct that contains the effective, permitted,
425 * and inheritable capabilities 255 * and inheritable capabilities
426 * 256 *
427 * Set capabilities for a given process, all processes, or all 257 * Set capabilities for the current process only. The ability to any other
428 * processes in a given process group. 258 * process(es) has been deprecated and removed.
429 * 259 *
430 * The restrictions on setting capabilities are specified as: 260 * The restrictions on setting capabilities are specified as:
431 * 261 *
432 * [pid is for the 'target' task. 'current' is the calling task.] 262 * I: any raised capabilities must be a subset of the old permitted
433 * 263 * P: any raised capabilities must be a subset of the old permitted
434 * I: any raised capabilities must be a subset of the (old current) permitted 264 * E: must be set to a subset of new permitted
435 * P: any raised capabilities must be a subset of the (old current) permitted
436 * E: must be set to a subset of (new target) permitted
437 * 265 *
438 * Returns 0 on success and < 0 on error. 266 * Returns 0 on success and < 0 on error.
439 */ 267 */
@@ -452,10 +280,13 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
452 if (get_user(pid, &header->pid)) 280 if (get_user(pid, &header->pid))
453 return -EFAULT; 281 return -EFAULT;
454 282
283 /* may only affect current now */
284 if (pid != 0 && pid != task_pid_vnr(current))
285 return -EPERM;
286
455 if (copy_from_user(&kdata, data, tocopy 287 if (copy_from_user(&kdata, data, tocopy
456 * sizeof(struct __user_cap_data_struct))) { 288 * sizeof(struct __user_cap_data_struct)))
457 return -EFAULT; 289 return -EFAULT;
458 }
459 290
460 for (i = 0; i < tocopy; i++) { 291 for (i = 0; i < tocopy; i++) {
461 effective.cap[i] = kdata[i].effective; 292 effective.cap[i] = kdata[i].effective;
@@ -473,32 +304,20 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
473 if (ret) 304 if (ret)
474 return ret; 305 return ret;
475 306
476 if (pid && (pid != task_pid_vnr(current))) 307 /* This lock is required even when filesystem capability support is
477 ret = do_sys_capset_other_tasks(pid, &effective, &inheritable, 308 * configured - it protects the sys_capget() call from returning
478 &permitted); 309 * incorrect data in the case that the targeted process is not the
479 else { 310 * current one.
480 /* 311 */
481 * This lock is required even when filesystem 312 spin_lock(&task_capability_lock);
482 * capability support is configured - it protects the
483 * sys_capget() call from returning incorrect data in
484 * the case that the targeted process is not the
485 * current one.
486 */
487 spin_lock(&task_capability_lock);
488
489 ret = security_capset_check(current, &effective, &inheritable,
490 &permitted);
491 /*
492 * Having verified that the proposed changes are
493 * legal, we now put them into effect.
494 */
495 if (!ret)
496 security_capset_set(current, &effective, &inheritable,
497 &permitted);
498 spin_unlock(&task_capability_lock);
499 }
500
501 313
314 ret = security_capset_check(&effective, &inheritable, &permitted);
315 /* Having verified that the proposed changes are legal, we now put them
316 * into effect.
317 */
318 if (!ret)
319 security_capset_set(&effective, &inheritable, &permitted);
320 spin_unlock(&task_capability_lock);
502 return ret; 321 return ret;
503} 322}
504 323