linux-bk/kernel/capability.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/capability.c
   3 *
   4 * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
   5 *
   6 * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@transmeta.com>
   7 * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net>
   8 */ 
   9
  10#include <linux/mm.h>
  11#include <asm/uaccess.h>
  12
  13unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
  14kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
  15
  16/*
  17 * This global lock protects task->cap_* for all tasks including current.
  18 * Locking rule: acquire this prior to tasklist_lock.
  19 */
  20spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED;
  21
  22/*
  23 * For sys_getproccap() and sys_setproccap(), any of the three
  24 * capability set pointers may be NULL -- indicating that that set is
  25 * uninteresting and/or not to be changed.
  26 */
  27
  28/*
  29 * sys_capget - get the capabilities of a given process.
  30 */
  31asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
  32{
  33     int ret = 0;
  34     pid_t pid;
  35     __u32 version;
  36     task_t *target;
  37     struct __user_cap_data_struct data;
  38
  39     if (get_user(version, &header->version))
  40             return -EFAULT;
  41
  42     if (version != _LINUX_CAPABILITY_VERSION) {
  43             if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
  44                     return -EFAULT; 
  45             return -EINVAL;
  46     }
  47
  48     if (get_user(pid, &header->pid))
  49             return -EFAULT;
  50
  51     if (pid < 0) 
  52             return -EINVAL;
  53
  54     spin_lock(&task_capability_lock);
  55     read_lock(&tasklist_lock); 
  56
  57     target = find_task_by_pid(pid);
  58     if (!target) {
  59          ret = -ESRCH;
  60          goto out;
  61     }
  62
  63     data.permitted = cap_t(target->cap_permitted);
  64     data.inheritable = cap_t(target->cap_inheritable); 
  65     data.effective = cap_t(target->cap_effective);
  66     ret = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted);
  67
  68out:
  69     read_unlock(&tasklist_lock); 
  70     spin_unlock(&task_capability_lock);
  71
  72     if (!ret && copy_to_user(dataptr, &data, sizeof data))
  73          return -EFAULT; 
  74
  75     return ret;
  76}
  77
  78/*
  79 * cap_set_pg - set capabilities for all processes in a given process
  80 * group.  We call this holding task_capability_lock and tasklist_lock.
  81 */
  82static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
  83                              kernel_cap_t *inheritable,
  84                              kernel_cap_t *permitted)
  85{
  86     task_t *g, *target;
  87
  88     do_each_thread(g, target) {
  89             if (target->pgrp != pgrp)
  90                     continue;
  91             security_ops->capset_set(target, effective, inheritable, permitted);
  92     } while_each_thread(g, target);
  93}
  94
  95/*
  96 * cap_set_all - set capabilities for all processes other than init
  97 * and self.  We call this holding task_capability_lock and tasklist_lock.
  98 */
  99static inline void cap_set_all(kernel_cap_t *effective,
 100                               kernel_cap_t *inheritable,
 101                               kernel_cap_t *permitted)
 102{
 103     task_t *g, *target;
 104
 105     do_each_thread(g, target) {
 106             if (target == current || target->pid == 1)
 107                     continue;
 108             security_ops->capset_set(target, effective, inheritable, permitted);
 109     } while_each_thread(g, target);
 110}
 111
 112/*
 113 * sys_capset - set capabilities for a given process, all processes, or all
 114 * processes in a given process group.
 115 *
 116 * The restrictions on setting capabilities are specified as:
 117 *
 118 * [pid is for the 'target' task.  'current' is the calling task.]
 119 *
 120 * I: any raised capabilities must be a subset of the (old current) permitted
 121 * P: any raised capabilities must be a subset of the (old current) permitted
 122 * E: must be set to a subset of (new target) permitted
 123 */
 124asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
 125{
 126     kernel_cap_t inheritable, permitted, effective;
 127     __u32 version;
 128     task_t *target;
 129     int ret;
 130     pid_t pid;
 131
 132     if (get_user(version, &header->version))
 133             return -EFAULT; 
 134
 135     if (version != _LINUX_CAPABILITY_VERSION) {
 136             if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
 137                     return -EFAULT; 
 138             return -EINVAL;
 139     }
 140
 141     if (get_user(pid, &header->pid))
 142             return -EFAULT; 
 143
 144     if (pid && !capable(CAP_SETPCAP))
 145             return -EPERM;
 146
 147     if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
 148         copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
 149         copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
 150             return -EFAULT; 
 151
 152     spin_lock(&task_capability_lock);
 153     read_lock(&tasklist_lock);
 154
 155     if (pid > 0 && pid != current->pid) {
 156          target = find_task_by_pid(pid);
 157          if (!target) {
 158               ret = -ESRCH;
 159               goto out;
 160          }
 161     } else
 162               target = current;
 163
 164     ret = -EPERM;
 165
 166     if (security_ops->capset_check(target, &effective, &inheritable, &permitted))
 167             goto out;
 168
 169     if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,
 170                       current->cap_permitted)))
 171             goto out;
 172
 173     /* verify restrictions on target's new Permitted set */
 174     if (!cap_issubset(permitted, cap_combine(target->cap_permitted,
 175                       current->cap_permitted)))
 176             goto out;
 177
 178     /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
 179     if (!cap_issubset(effective, permitted))
 180             goto out;
 181
 182     ret = 0;
 183
 184     /* having verified that the proposed changes are legal,
 185           we now put them into effect. */
 186     if (pid < 0) {
 187             if (pid == -1)  /* all procs other than current and init */
 188                     cap_set_all(&effective, &inheritable, &permitted);
 189
 190             else            /* all procs in process group */
 191                     cap_set_pg(-pid, &effective, &inheritable, &permitted);
 192     } else {
 193             security_ops->capset_set(target, &effective, &inheritable, &permitted);
 194     }
 195
 196out:
 197     read_unlock(&tasklist_lock);
 198     spin_unlock(&task_capability_lock);
 199
 200     return ret;
 201}
 202
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.