ia64/linux-2.6.18-xen.hg

annotate kernel/capability.c @ 562:66faefe721eb

pvSCSI backend driver

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