capability.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/kernel/capability.c
  3.  *
  4.  * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
  5.  * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@transmeta.com>
  6.  */ 
  7. #include <linux/mm.h>
  8. #include <asm/uaccess.h>
  9. kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
  10. /* Note: never hold tasklist_lock while spinning for this one */
  11. spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED;
  12. /*
  13.  * For sys_getproccap() and sys_setproccap(), any of the three
  14.  * capability set pointers may be NULL -- indicating that that set is
  15.  * uninteresting and/or not to be changed.
  16.  */
  17. asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
  18. {
  19.      int error, pid;
  20.      __u32 version;
  21.      struct task_struct *target;
  22.      struct __user_cap_data_struct data;
  23.      if (get_user(version, &header->version))
  24.      return -EFAULT;
  25.      
  26.      error = -EINVAL; 
  27.      if (version != _LINUX_CAPABILITY_VERSION) {
  28.              version = _LINUX_CAPABILITY_VERSION;
  29.      if (put_user(version, &header->version))
  30.      error = -EFAULT; 
  31.              return error;
  32.      }
  33.      if (get_user(pid, &header->pid))
  34.      return -EFAULT; 
  35.      if (pid < 0) 
  36.              return -EINVAL;
  37.      error = 0;
  38.      spin_lock(&task_capability_lock);
  39.      if (pid && pid != current->pid) {
  40.      read_lock(&tasklist_lock); 
  41.              target = find_task_by_pid(pid);  /* identify target of query */
  42.              if (!target) 
  43.                      error = -ESRCH;
  44.      } else {
  45.              target = current;
  46.      }
  47.      if (!error) { 
  48.      data.permitted = cap_t(target->cap_permitted);
  49.      data.inheritable = cap_t(target->cap_inheritable); 
  50.      data.effective = cap_t(target->cap_effective);
  51.      }
  52.      if (target != current)
  53.      read_unlock(&tasklist_lock); 
  54.      spin_unlock(&task_capability_lock);
  55.      if (!error) {
  56.      if (copy_to_user(dataptr, &data, sizeof data))
  57.      return -EFAULT; 
  58.      }
  59.      return error;
  60. }
  61. /* set capabilities for all processes in a given process group */
  62. static void cap_set_pg(int pgrp,
  63.                     kernel_cap_t *effective,
  64.                     kernel_cap_t *inheritable,
  65.                     kernel_cap_t *permitted)
  66. {
  67.      struct task_struct *target;
  68.      /* FIXME: do we need to have a write lock here..? */
  69.      read_lock(&tasklist_lock);
  70.      for_each_task(target) {
  71.              if (target->pgrp != pgrp)
  72.                      continue;
  73.              target->cap_effective   = *effective;
  74.              target->cap_inheritable = *inheritable;
  75.              target->cap_permitted   = *permitted;
  76.      }
  77.      read_unlock(&tasklist_lock);
  78. }
  79. /* set capabilities for all processes other than 1 and self */
  80. static void cap_set_all(kernel_cap_t *effective,
  81.                      kernel_cap_t *inheritable,
  82.                      kernel_cap_t *permitted)
  83. {
  84.      struct task_struct *target;
  85.      /* FIXME: do we need to have a write lock here..? */
  86.      read_lock(&tasklist_lock);
  87.      /* ALL means everyone other than self or 'init' */
  88.      for_each_task(target) {
  89.              if (target == current || target->pid == 1)
  90.                      continue;
  91.              target->cap_effective   = *effective;
  92.              target->cap_inheritable = *inheritable;
  93.              target->cap_permitted   = *permitted;
  94.      }
  95.      read_unlock(&tasklist_lock);
  96. }
  97. /*
  98.  * The restrictions on setting capabilities are specified as:
  99.  *
  100.  * [pid is for the 'target' task.  'current' is the calling task.]
  101.  *
  102.  * I: any raised capabilities must be a subset of the (old current) Permitted
  103.  * P: any raised capabilities must be a subset of the (old current) permitted
  104.  * E: must be set to a subset of (new target) Permitted
  105.  */
  106. asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
  107. {
  108.      kernel_cap_t inheritable, permitted, effective;
  109.      __u32 version;
  110.      struct task_struct *target;
  111.      int error, pid;
  112.      if (get_user(version, &header->version))
  113.      return -EFAULT; 
  114.      if (version != _LINUX_CAPABILITY_VERSION) {
  115.              version = _LINUX_CAPABILITY_VERSION;
  116.      if (put_user(version, &header->version))
  117.      return -EFAULT; 
  118.              return -EINVAL;
  119.      }
  120.      if (get_user(pid, &header->pid))
  121.      return -EFAULT; 
  122.      if (pid && !capable(CAP_SETPCAP))
  123.              return -EPERM;
  124.      if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
  125.  copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
  126.  copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
  127.      return -EFAULT; 
  128.      error = -EPERM;
  129.      spin_lock(&task_capability_lock);
  130.      if (pid > 0 && pid != current->pid) {
  131.              read_lock(&tasklist_lock);
  132.              target = find_task_by_pid(pid);  /* identify target of query */
  133.              if (!target) {
  134.                      error = -ESRCH;
  135.      goto out;
  136.      }
  137.      } else {
  138.              target = current;
  139.      }
  140.      /* verify restrictions on target's new Inheritable set */
  141.      if (!cap_issubset(inheritable,
  142.                        cap_combine(target->cap_inheritable,
  143.                                    current->cap_permitted))) {
  144.              goto out;
  145.      }
  146.      /* verify restrictions on target's new Permitted set */
  147.      if (!cap_issubset(permitted,
  148.                        cap_combine(target->cap_permitted,
  149.                                    current->cap_permitted))) {
  150.              goto out;
  151.      }
  152.      /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
  153.      if (!cap_issubset(effective, permitted)) {
  154.              goto out;
  155.      }
  156.      /* having verified that the proposed changes are legal,
  157.            we now put them into effect. */
  158.      error = 0;
  159.      if (pid < 0) {
  160.              if (pid == -1)  /* all procs other than current and init */
  161.                      cap_set_all(&effective, &inheritable, &permitted);
  162.              else            /* all procs in process group */
  163.                      cap_set_pg(-pid, &effective, &inheritable, &permitted);
  164.              goto spin_out;
  165.      } else {
  166.              /* FIXME: do we need to have a write lock here..? */
  167.              target->cap_effective   = effective;
  168.              target->cap_inheritable = inheritable;
  169.              target->cap_permitted   = permitted;
  170.      }
  171. out:
  172.      if (target != current) {
  173.              read_unlock(&tasklist_lock);
  174.      }
  175. spin_out:
  176.      spin_unlock(&task_capability_lock);
  177.      return error;
  178. }