capability.c 8.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * linux/kernel/capability.c
 *
 * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
 *
6
 * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@kernel.org>
L
Linus Torvalds 已提交
7
 * 30 May 2002:	Cleanup, Robert M. Love <rml@tech9.net>
8
 */
L
Linus Torvalds 已提交
9

10
#include <linux/audit.h>
11
#include <linux/capability.h>
L
Linus Torvalds 已提交
12 13 14 15
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/security.h>
#include <linux/syscalls.h>
16
#include <linux/pid_namespace.h>
L
Linus Torvalds 已提交
17
#include <asm/uaccess.h>
D
David Howells 已提交
18
#include "cred-internals.h"
L
Linus Torvalds 已提交
19

20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Leveraged for setting/resetting capabilities
 */

const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
const kernel_cap_t __cap_full_set = CAP_FULL_SET;
const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;

EXPORT_SYMBOL(__cap_empty_set);
EXPORT_SYMBOL(__cap_full_set);
EXPORT_SYMBOL(__cap_init_eff_set);

32 33 34 35 36 37 38 39 40 41 42
#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
int file_caps_enabled = 1;

static int __init file_caps_disable(char *str)
{
	file_caps_enabled = 0;
	return 1;
}
__setup("no_file_caps", file_caps_disable);
#endif

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
/*
 * More recent versions of libcap are available from:
 *
 *   http://www.kernel.org/pub/linux/libs/security/linux-privs/
 */

static void warn_legacy_capability_use(void)
{
	static int warned;
	if (!warned) {
		char name[sizeof(current->comm)];

		printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
		       " (legacy support in use)\n",
		       get_task_comm(name, current));
		warned = 1;
	}
}

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
/*
 * Version 2 capabilities worked fine, but the linux/capability.h file
 * that accompanied their introduction encouraged their use without
 * the necessary user-space source code changes. As such, we have
 * created a version 3 with equivalent functionality to version 2, but
 * with a header change to protect legacy source code from using
 * version 2 when it wanted to use version 1. If your system has code
 * that trips the following warning, it is using version 2 specific
 * capabilities and may be doing so insecurely.
 *
 * The remedy is to either upgrade your version of libcap (to 2.10+,
 * if the application is linked against it), or recompile your
 * application with modern kernel headers and this warning will go
 * away.
 */

static void warn_deprecated_v2(void)
{
	static int warned;

	if (!warned) {
		char name[sizeof(current->comm)];

		printk(KERN_INFO "warning: `%s' uses deprecated v2"
		       " capabilities in a way that may be insecure.\n",
		       get_task_comm(name, current));
		warned = 1;
	}
}

/*
 * Version check. Return the number of u32s in each capability flag
 * array, or a negative value on error.
 */
static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
{
	__u32 version;

	if (get_user(version, &header->version))
		return -EFAULT;

	switch (version) {
	case _LINUX_CAPABILITY_VERSION_1:
		warn_legacy_capability_use();
		*tocopy = _LINUX_CAPABILITY_U32S_1;
		break;
	case _LINUX_CAPABILITY_VERSION_2:
		warn_deprecated_v2();
		/*
		 * fall through - v3 is otherwise equivalent to v2.
		 */
	case _LINUX_CAPABILITY_VERSION_3:
		*tocopy = _LINUX_CAPABILITY_U32S_3;
		break;
	default:
		if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version))
			return -EFAULT;
		return -EINVAL;
	}

	return 0;
}

125
/*
D
David Howells 已提交
126 127 128 129 130
 * The only thing that can change the capabilities of the current
 * process is the current process. As such, we can't be in this code
 * at the same time as we are in the process of setting capabilities
 * in this process. The net result is that we can limit our use of
 * locks to when we are reading the caps of another process.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
 */
static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
				     kernel_cap_t *pIp, kernel_cap_t *pPp)
{
	int ret;

	if (pid && (pid != task_pid_vnr(current))) {
		struct task_struct *target;

		read_lock(&tasklist_lock);

		target = find_task_by_vpid(pid);
		if (!target)
			ret = -ESRCH;
		else
			ret = security_capget(target, pEp, pIp, pPp);

		read_unlock(&tasklist_lock);
	} else
		ret = security_capget(current, pEp, pIp, pPp);

	return ret;
}

155
/**
L
Linus Torvalds 已提交
156
 * sys_capget - get the capabilities of a given process.
157 158 159 160 161 162
 * @header: pointer to struct that contains capability version and
 *	target pid data
 * @dataptr: pointer to struct that contains the effective, permitted,
 *	and inheritable capabilities that are returned
 *
 * Returns 0 on success and < 0 on error.
L
Linus Torvalds 已提交
163 164 165
 */
asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{
166 167
	int ret = 0;
	pid_t pid;
168 169
	unsigned tocopy;
	kernel_cap_t pE, pI, pP;
170

171 172 173
	ret = cap_validate_magic(header, &tocopy);
	if (ret != 0)
		return ret;
L
Linus Torvalds 已提交
174

175 176
	if (get_user(pid, &header->pid))
		return -EFAULT;
L
Linus Torvalds 已提交
177

178 179
	if (pid < 0)
		return -EINVAL;
L
Linus Torvalds 已提交
180

181
	ret = cap_get_target_pid(pid, &pE, &pI, &pP);
182
	if (!ret) {
183
		struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
184 185 186 187 188 189 190 191 192
		unsigned i;

		for (i = 0; i < tocopy; i++) {
			kdata[i].effective = pE.cap[i];
			kdata[i].permitted = pP.cap[i];
			kdata[i].inheritable = pI.cap[i];
		}

		/*
193
		 * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S,
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
		 * we silently drop the upper capabilities here. This
		 * has the effect of making older libcap
		 * implementations implicitly drop upper capability
		 * bits when they perform a: capget/modify/capset
		 * sequence.
		 *
		 * This behavior is considered fail-safe
		 * behavior. Upgrading the application to a newer
		 * version of libcap will enable access to the newer
		 * capabilities.
		 *
		 * An alternative would be to return an error here
		 * (-ERANGE), but that causes legacy applications to
		 * unexpectidly fail; the capget/modify/capset aborts
		 * before modification is attempted and the application
		 * fails.
		 */
		if (copy_to_user(dataptr, kdata, tocopy
				 * sizeof(struct __user_cap_data_struct))) {
			return -EFAULT;
		}
	}
L
Linus Torvalds 已提交
216

217
	return ret;
L
Linus Torvalds 已提交
218 219
}

220
/**
221
 * sys_capset - set capabilities for a process or (*) a group of processes
222 223 224 225 226
 * @header: pointer to struct that contains capability version and
 *	target pid data
 * @data: pointer to struct that contains the effective, permitted,
 *	and inheritable capabilities
 *
D
David Howells 已提交
227 228
 * Set capabilities for the current process only.  The ability to any other
 * process(es) has been deprecated and removed.
L
Linus Torvalds 已提交
229 230 231
 *
 * The restrictions on setting capabilities are specified as:
 *
D
David Howells 已提交
232 233 234
 * I: any raised capabilities must be a subset of the old permitted
 * P: any raised capabilities must be a subset of the old permitted
 * E: must be set to a subset of new permitted
235 236
 *
 * Returns 0 on success and < 0 on error.
L
Linus Torvalds 已提交
237 238 239
 */
asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
{
240
	struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
241
	unsigned i, tocopy;
242
	kernel_cap_t inheritable, permitted, effective;
D
David Howells 已提交
243
	struct cred *new;
244 245 246
	int ret;
	pid_t pid;

247 248 249
	ret = cap_validate_magic(header, &tocopy);
	if (ret != 0)
		return ret;
250 251 252 253

	if (get_user(pid, &header->pid))
		return -EFAULT;

D
David Howells 已提交
254 255 256 257
	/* may only affect current now */
	if (pid != 0 && pid != task_pid_vnr(current))
		return -EPERM;

D
David Howells 已提交
258 259
	if (copy_from_user(&kdata, data,
			   tocopy * sizeof(struct __user_cap_data_struct)))
260
		return -EFAULT;
261 262 263 264 265 266

	for (i = 0; i < tocopy; i++) {
		effective.cap[i] = kdata[i].effective;
		permitted.cap[i] = kdata[i].permitted;
		inheritable.cap[i] = kdata[i].inheritable;
	}
267
	while (i < _KERNEL_CAPABILITY_U32S) {
268 269 270 271 272
		effective.cap[i] = 0;
		permitted.cap[i] = 0;
		inheritable.cap[i] = 0;
		i++;
	}
273

D
David Howells 已提交
274 275 276 277 278 279 280 281 282 283 284
	new = prepare_creds();
	if (!new)
		return -ENOMEM;

	ret = security_capset(new, current_cred(),
			      &effective, &inheritable, &permitted);
	if (ret < 0)
		goto error;

	ret = audit_log_capset(pid, new, current_cred());
	if (ret < 0)
285 286
		return ret;

D
David Howells 已提交
287 288 289 290
	return commit_creds(new);

error:
	abort_creds(new);
291
	return ret;
L
Linus Torvalds 已提交
292
}
293

294 295 296 297 298 299 300 301 302 303 304
/**
 * capable - Determine if the current task has a superior capability in effect
 * @cap: The capability to be tested for
 *
 * Return true if the current task has the given superior capability currently
 * available for use, false if not.
 *
 * This sets PF_SUPERPRIV on the task if the capability is available on the
 * assumption that it's about to be used.
 */
int capable(int cap)
305
{
306 307 308 309 310
	if (unlikely(!cap_valid(cap))) {
		printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
		BUG();
	}

311 312
	if (has_capability(current, cap)) {
		current->flags |= PF_SUPERPRIV;
313 314 315 316 317
		return 1;
	}
	return 0;
}
EXPORT_SYMBOL(capable);