linux/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/capability.h>
  11#include <linux/mm.h>
  12#include <linux/module.h>
  13#include <linux/security.h>
  14#include <linux/syscalls.h>
  15#include <asm/uaccess.h>
  16
  17unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
  18kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
  19
  20EXPORT_SYMBOL(securebits);
  21EXPORT_SYMBOL(cap_bset);
  22
  23/*
  24 * This lock protects task->cap_* for all tasks including current.
  25 * Locking rule: acquire this prior to tasklist_lock.
  26 */
  27static DEFINE_SPINLOCK(task_capability_lock);
  28
  29/*
  30 * For sys_getproccap() and sys_setproccap(), any of the three
  31 * capability set pointers may be NULL -- indicating that that set is
  32 * uninteresting and/or not to be changed.
  33 */
  34
  35/**
  36 * sys_capget - get the capabilities of a given process.
  37 * @header: pointer to struct that contains capability version and
  38 *      target pid data
  39 * @dataptr: pointer to struct that contains the effective, permitted,
  40 *      and inheritable capabilities that are returned
  41 *
  42 * Returns 0 on success and < 0 on error.
  43 */
  44asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
  45{
  46     int ret = 0;
  47     pid_t pid;
  48     __u32 version;
  49     struct task_struct *target;
  50     struct __user_cap_data_struct data;
  51
  52     if (get_user(version, &header->version))
  53             return -EFAULT;
  54
  55     if (version != _LINUX_CAPABILITY_VERSION) {
  56             if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
  57                     return -EFAULT; 
  58             return -EINVAL;
  59     }
  60
  61     if (get_user(pid, &header->pid))
  62             return -EFAULT;
  63
  64     if (pid < 0) 
  65             return -EINVAL;
  66
  67     spin_lock(&task_capability_lock);
  68     read_lock(&tasklist_lock); 
  69
  70     if (pid && pid != current->pid) {
  71             target = find_task_by_pid(pid);
  72             if (!target) {
  73                  ret = -ESRCH;
  74                  goto out;
  75             }
  76     } else
  77             target = current;
  78
  79     ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
  80
  81out:
  82     read_unlock(&tasklist_lock); 
  83     spin_unlock(&task_capability_lock);
  84
  85     if (!ret && copy_to_user(dataptr, &data, sizeof data))
  86          return -EFAULT; 
  87
  88     return ret;
  89}
  90
  91/*
  92 * cap_set_pg - set capabilities for all processes in a given process
  93 * group.  We call this holding task_capability_lock and tasklist_lock.
  94 */
  95static inline int cap_set_pg(int pgrp, kernel_cap_t *effective,
  96                              kernel_cap_t *inheritable,
  97                              kernel_cap_t *permitted)
  98{
  99        struct task_struct *g, *target;
 100        int ret = -EPERM;
 101        int found = 0;
 102
 103        do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
 104                target = g;
 105                while_each_thread(g, target) {
 106                        if (!security_capset_check(target, effective,
 107                                                        inheritable,
 108                                                        permitted)) {
 109                                security_capset_set(target, effective,
 110                                                        inheritable,
 111                                                        permitted);
 112                                ret = 0;
 113                        }
 114                        found = 1;
 115                }
 116        } while_each_task_pid(pgrp, PIDTYPE_PGID, g);
 117
 118        if (!found)
 119             ret = 0;
 120        return ret;
 121}
 122
 123/*
 124 * cap_set_all - set capabilities for all processes other than init
 125 * and self.  We call this holding task_capability_lock and tasklist_lock.
 126 */
 127static inline int cap_set_all(kernel_cap_t *effective,
 128                               kernel_cap_t *inheritable,
 129                               kernel_cap_t *permitted)
 130{
 131     struct task_struct *g, *target;
 132     int ret = -EPERM;
 133     int found = 0;
 134
 135     do_each_thread(g, target) {
 136             if (target == current || is_init(target))
 137                     continue;
 138             found = 1;
 139             if (security_capset_check(target, effective, inheritable,
 140                                                permitted))
 141                     continue;
 142             ret = 0;
 143             security_capset_set(target, effective, inheritable, permitted);
 144     } while_each_thread(g, target);
 145
 146     if (!found)
 147             ret = 0;
 148     return ret;
 149}
 150
 151/**
 152 * sys_capset - set capabilities for a process or a group of processes
 153 * @header: pointer to struct that contains capability version and
 154 *      target pid data
 155 * @data: pointer to struct that contains the effective, permitted,
 156 *      and inheritable capabilities
 157 *
 158 * Set capabilities for a given process, all processes, or all
 159 * processes in a given process group.
 160 *
 161 * The restrictions on setting capabilities are specified as:
 162 *
 163 * [pid is for the 'target' task.  'current' is the calling task.]
 164 *
 165 * I: any raised capabilities must be a subset of the (old current) permitted
 166 * P: any raised capabilities must be a subset of the (old current) permitted
 167 * E: must be set to a subset of (new target) permitted
 168 *
 169 * Returns 0 on success and < 0 on error.
 170 */
 171asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
 172{
 173     kernel_cap_t inheritable, permitted, effective;
 174     __u32 version;
 175     struct task_struct *target;
 176     int ret;
 177     pid_t pid;
 178
 179     if (get_user(version, &header->version))
 180             return -EFAULT; 
 181
 182     if (version != _LINUX_CAPABILITY_VERSION) {
 183             if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
 184                     return -EFAULT; 
 185             return -EINVAL;
 186     }
 187
 188     if (get_user(pid, &header->pid))
 189             return -EFAULT; 
 190
 191     if (pid && pid != current->pid && !capable(CAP_SETPCAP))
 192             return -EPERM;
 193
 194     if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
 195         copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
 196         copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
 197             return -EFAULT; 
 198
 199     spin_lock(&task_capability_lock);
 200     read_lock(&tasklist_lock);
 201
 202     if (pid > 0 && pid != current->pid) {
 203          target = find_task_by_pid(pid);
 204          if (!target) {
 205               ret = -ESRCH;
 206               goto out;
 207          }
 208     } else
 209               target = current;
 210
 211     ret = 0;
 212
 213     /* having verified that the proposed changes are legal,
 214           we now put them into effect. */
 215     if (pid < 0) {
 216             if (pid == -1)  /* all procs other than current and init */
 217                     ret = cap_set_all(&effective, &inheritable, &permitted);
 218
 219             else            /* all procs in process group */
 220                     ret = cap_set_pg(-pid, &effective, &inheritable,
 221                                                        &permitted);
 222     } else {
 223             ret = security_capset_check(target, &effective, &inheritable,
 224                                                        &permitted);
 225             if (!ret)
 226                     security_capset_set(target, &effective, &inheritable,
 227                                                        &permitted);
 228     }
 229
 230out:
 231     read_unlock(&tasklist_lock);
 232     spin_unlock(&task_capability_lock);
 233
 234     return ret;
 235}
 236
 237int __capable(struct task_struct *t, int cap)
 238{
 239        if (security_capable(t, cap) == 0) {
 240                t->flags |= PF_SUPERPRIV;
 241                return 1;
 242        }
 243        return 0;
 244}
 245EXPORT_SYMBOL(__capable);
 246
 247int capable(int cap)
 248{
 249        return __capable(current, cap);
 250}
 251EXPORT_SYMBOL(capable);
 252