kernel/capability.c
22460 /*
22461 * linux/kernel/capability.c
22462 *
22463 * Copyright (C) 1997 Andrew Main <zefram@fysh.org>
22464 * Integrated into 2.1.97+, Andrew G. Morgan
22465 * <morgan@transmeta.com>
22466 */
22467
22468 #include <linux/mm.h>
22469 #include <asm/uaccess.h>
22470
22471 /* Note: never hold tasklist_lock while spinning for this
22472 * one */
22473 spinlock_t task_capability_lock;
22474
22475 /* For sys_getproccap() and sys_setproccap(), any of the
22476 * three capability set pointers may be NULL --
22477 * indicating that that set is uninteresting and/or not
22478 * to be changed. */
22479
22480 asmlinkage int sys_capget(cap_user_header_t header,
22481 cap_user_data_t dataptr)
22482 {
22483 int error, pid;
22484 __u32 version;
22485 struct task_struct *target;
22486 struct __user_cap_data_struct data;
22487
22488 if (get_user(version, &header->version))
22489 return -EFAULT;
22490
22491 error = -EINVAL;
22492 if (version != _LINUX_CAPABILITY_VERSION) {
22493 version = _LINUX_CAPABILITY_VERSION;
22494 if (put_user(version, &header->version))
22495 error = -EFAULT;
22496 return error;
22497 }
22498
22499 if (get_user(pid, &header->pid))
22500 return -EFAULT;
22501
22502 if (pid < 0)
22503 return -EINVAL;
22504
22505 error = 0;
22506
22507 spin_lock(&task_capability_lock);
22508
22509 if (pid && pid != current->pid) {
22510 read_lock(&tasklist_lock);
22511 /* identify target of query */
22512 target = find_task_by_pid(pid);
22513 if (!target)
22514 error = -ESRCH;
22515 } else {
22516 target = current;
22517 }
22518
22519 if (!error) {
22520 data.permitted = cap_t(target->cap_permitted);
22521 data.inheritable = cap_t(target->cap_inheritable);
22522 data.effective = cap_t(target->cap_effective);
22523 }
22524
22525 if (target != current)
22526 read_unlock(&tasklist_lock);
22527 spin_unlock(&task_capability_lock);
22528
22529 if (!error) {
22530 if (copy_to_user(dataptr, &data, sizeof data))
22531 return -EFAULT;
22532 }
22533
22534 return error;
22535 }
22536
22537 /* set capabilities for all processes in a given process
22538 * group */
22539 static void cap_set_pg(int pgrp,
22540 kernel_cap_t *effective,
22541 kernel_cap_t *inheritable,
22542 kernel_cap_t *permitted)
22543 {
22544 struct task_struct *target;
22545
22546 /* FIXME: do we need to have a write lock here..? */
22547 read_lock(&tasklist_lock);
22548 for_each_task(target) {
22549 if (target->pgrp != pgrp)
22550 continue;
22551 target->cap_effective = *effective;
22552 target->cap_inheritable = *inheritable;
22553 target->cap_permitted = *permitted;
22554 }
22555 read_unlock(&tasklist_lock);
22556 }
22557
22558 /* set capabilities for all processes other than 1 and
22559 * self */
22560
22561 static void cap_set_all(kernel_cap_t *effective,
22562 kernel_cap_t *inheritable,
22563 kernel_cap_t *permitted)
22564 {
22565 struct task_struct *target;
22566
22567 /* FIXME: do we need to have a write lock here..? */
22568 read_lock(&tasklist_lock);
22569 /* ALL means everyone other than self or 'init' */
22570 for_each_task(target) {
22571 if (target == current || target->pid == 1)
22572 continue;
22573 target->cap_effective = *effective;
22574 target->cap_inheritable = *inheritable;
22575 target->cap_permitted = *permitted;
22576 }
22577 read_unlock(&tasklist_lock);
22578 }
22579
22580 /* The restrictions on setting capabilities are specified
22581 * as:
22582 *
22583 * [pid is for the 'target' task. 'current' is the
22584 * calling task.]
22585 *
22586 * I: any raised capabilities must be a subset of the
22587 * (old current) Permitted
22588 * P: any raised capabilities must be a subset of the
22589 * (old current) permitted
22590 * E: must be set to a subset of (new target) Permitted
22591 */
22592 asmlinkage int sys_capset(cap_user_header_t header,
22593 const cap_user_data_t data)
22594 {
22595 kernel_cap_t inheritable, permitted, effective;
22596 __u32 version;
22597 struct task_struct *target;
22598 int error, pid;
22599
22600 if (get_user(version, &header->version))
22601 return -EFAULT;
22602
22603 if (version != _LINUX_CAPABILITY_VERSION) {
22604 version = _LINUX_CAPABILITY_VERSION;
22605 if (put_user(version, &header->version))
22606 return -EFAULT;
22607 return -EINVAL;
22608 }
22609
22610 if (get_user(pid, &header->pid))
22611 return -EFAULT;
22612
22613 if (pid && !capable(CAP_SETPCAP))
22614 return -EPERM;
22615
22616 if (copy_from_user(&effective, &data->effective,
22617 sizeof(effective)) ||
22618 copy_from_user(&inheritable, &data->inheritable,
22619 sizeof(inheritable)) ||
22620 copy_from_user(&permitted, &data->permitted,
22621 sizeof(permitted)))
22622 return -EFAULT;
22623
22624 error = -EPERM;
22625 spin_lock(&task_capability_lock);
22626
22627 if (pid > 0 && pid != current->pid) {
22628 read_lock(&tasklist_lock);
22629 /* identify target of query */
22630 target = find_task_by_pid(pid);
22631 if (!target) {
22632 error = -ESRCH;
22633 goto out;
22634 }
22635 } else {
22636 target = current;
22637 }
22638
22639
22640 /* verify restrictions on target's new Inheritable
22641 * set */
22642 if (!cap_issubset(inheritable,
22643 cap_combine(target->cap_inheritable,
22644 current->cap_permitted))) {
22645 goto out;
22646 }
22647
22648 /* verify restrictions on target's new Permitted
22649 * set */
22650 if (!cap_issubset(permitted,
22651 cap_combine(target->cap_permitted,
22652 current->cap_permitted))) {
22653 goto out;
22654 }
22655
22656 /* verify the _new_Effective_ is a subset of the
22657 * _new_Permitted_ */
22658 if (!cap_issubset(effective, permitted)) {
22659 goto out;
22660 }
22661
22662 /* having verified that the proposed changes are
22663 * legal, we now put them into effect. */
22664 error = 0;
22665
22666 if (pid < 0) {
22667 if (pid == -1) /* all procs but current & init */
22668 cap_set_all(&effective,&inheritable,&permitted);
22669
22670 else /* all procs in process group */
22671 cap_set_pg(-pid, &effective, &inheritable,
22672 &permitted);
22673 goto spin_out;
22674 } else {
22675 /* FIXME: do we need a write lock here..? */
22676 target->cap_effective = effective;
22677 target->cap_inheritable = inheritable;
22678 target->cap_permitted = permitted;
22679 }
22680
22681 out:
22682 if (target != current) {
22683 read_unlock(&tasklist_lock);
22684 }
22685 spin_out:
22686 spin_unlock(&task_capability_lock);
22687 return error;
22688 }
Сайт управляется системой
uCoz