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