Blame view

security/commoncap.c 36.8 KB
3e1c2515a   James Morris   security: remove ...
1
  /* Common capabilities, needed by capability.o.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
   *
   *	This program is free software; you can redistribute it and/or modify
   *	it under the terms of the GNU General Public License as published by
   *	the Free Software Foundation; either version 2 of the License, or
   *	(at your option) any later version.
   *
   */
c59ede7b7   Randy.Dunlap   [PATCH] move capa...
9
  #include <linux/capability.h>
3fc689e96   Eric Paris   Any time fcaps or...
10
  #include <linux/audit.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
14
  #include <linux/lsm_hooks.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
  #include <linux/file.h>
  #include <linux/mm.h>
  #include <linux/mman.h>
  #include <linux/pagemap.h>
  #include <linux/swap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
  #include <linux/ptrace.h>
  #include <linux/xattr.h>
  #include <linux/hugetlb.h>
b53767719   Serge E. Hallyn   Implement file po...
25
  #include <linux/mount.h>
b460cbc58   Serge E. Hallyn   pid namespaces: d...
26
  #include <linux/sched.h>
3898b1b4e   Andrew G. Morgan   capabilities: imp...
27
28
  #include <linux/prctl.h>
  #include <linux/securebits.h>
3486740a4   Serge E. Hallyn   userns: security:...
29
  #include <linux/user_namespace.h>
404015308   Al Viro   security: trim se...
30
  #include <linux/binfmts.h>
51b79bee6   Jonghwan Choi   security: fix com...
31
  #include <linux/personality.h>
72c2d5823   Andrew Morgan   V3 file capabilit...
32

b5f22a59c   Serge E. Hallyn   don't raise all p...
33
34
35
36
37
38
39
40
41
42
43
  /*
   * If a non-root user executes a setuid-root binary in
   * !secure(SECURE_NOROOT) mode, then we raise capabilities.
   * However if fE is also set, then the intent is for only
   * the file capabilities to be applied, and the setuid-root
   * bit is left on either to change the uid (plausible) or
   * to get full privilege on a kernel without file capabilities
   * support.  So in that case we do not raise capabilities.
   *
   * Warn if that happens, once per boot.
   */
d7627467b   David Howells   Make do_execve() ...
44
  static void warn_setuid_and_fcaps_mixed(const char *fname)
b5f22a59c   Serge E. Hallyn   don't raise all p...
45
46
47
48
49
50
51
52
53
54
  {
  	static int warned;
  	if (!warned) {
  		printk(KERN_INFO "warning: `%s' has both setuid-root and"
  			" effective capabilities. Therefore not raising all"
  			" capabilities.
  ", fname);
  		warned = 1;
  	}
  }
1d045980e   David Howells   CRED: Prettify co...
55
56
  /**
   * cap_capable - Determine whether a task has a particular effective capability
3699c53c4   David Howells   CRED: Fix regress...
57
   * @cred: The credentials to use
3486740a4   Serge E. Hallyn   userns: security:...
58
   * @ns:  The user namespace in which we need the capability
1d045980e   David Howells   CRED: Prettify co...
59
60
61
62
63
64
   * @cap: The capability to check for
   * @audit: Whether to write an audit message or not
   *
   * Determine whether the nominated task has the specified capability amongst
   * its effective set, returning 0 if it does, -ve if it does not.
   *
3699c53c4   David Howells   CRED: Fix regress...
65
66
67
68
   * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable()
   * and has_capability() functions.  That is, it has the reverse semantics:
   * cap_has_capability() returns 0 when a task has a capability, but the
   * kernel's capable() and has_capability() returns 1 for this case.
a6dbb1ef2   Andrew G. Morgan   Fix filesystem ca...
69
   */
6a9de4911   Eric Paris   capabilities: rem...
70
71
  int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
  		int cap, int audit)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  {
520d9eabc   Eric W. Biederman   Fix cap_capable t...
73
  	struct user_namespace *ns = targ_ns;
3486740a4   Serge E. Hallyn   userns: security:...
74

520d9eabc   Eric W. Biederman   Fix cap_capable t...
75
76
77
78
79
  	/* See if cred has the capability in the target user namespace
  	 * by examining the target user namespace and all of the target
  	 * user namespace's parents.
  	 */
  	for (;;) {
3486740a4   Serge E. Hallyn   userns: security:...
80
  		/* Do we have the necessary capabilities? */
520d9eabc   Eric W. Biederman   Fix cap_capable t...
81
  		if (ns == cred->user_ns)
3486740a4   Serge E. Hallyn   userns: security:...
82
  			return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
64db4c7f4   Kirill Tkhai   security: Use use...
83
84
85
86
87
  		/*
  		 * If we're already at a lower level than we're looking for,
  		 * we're done searching.
  		 */
  		if (ns->level <= cred->user_ns->level)
3486740a4   Serge E. Hallyn   userns: security:...
88
  			return -EPERM;
520d9eabc   Eric W. Biederman   Fix cap_capable t...
89
90
91
92
93
94
  		/* 
  		 * The owner of the user namespace in the parent of the
  		 * user namespace has all caps.
  		 */
  		if ((ns->parent == cred->user_ns) && uid_eq(ns->owner, cred->euid))
  			return 0;
3486740a4   Serge E. Hallyn   userns: security:...
95
  		/*
520d9eabc   Eric W. Biederman   Fix cap_capable t...
96
  		 * If you have a capability in a parent user ns, then you have
3486740a4   Serge E. Hallyn   userns: security:...
97
98
  		 * it over all children user namespaces as well.
  		 */
520d9eabc   Eric W. Biederman   Fix cap_capable t...
99
  		ns = ns->parent;
3486740a4   Serge E. Hallyn   userns: security:...
100
101
102
  	}
  
  	/* We never get here */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  }
1d045980e   David Howells   CRED: Prettify co...
104
105
106
107
108
109
110
111
  /**
   * cap_settime - Determine whether the current process may set the system clock
   * @ts: The time to set
   * @tz: The timezone to set
   *
   * Determine whether the current process may set the system clock and timezone
   * information, returning 0 if permission granted, -ve if denied.
   */
457db29bf   Baolin Wang   security: Introdu...
112
  int cap_settime(const struct timespec64 *ts, const struct timezone *tz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
  {
  	if (!capable(CAP_SYS_TIME))
  		return -EPERM;
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
118
  /**
9e48858f7   Ingo Molnar   security: rename ...
119
   * cap_ptrace_access_check - Determine whether the current process may access
1d045980e   David Howells   CRED: Prettify co...
120
121
122
123
   *			   another
   * @child: The process to be accessed
   * @mode: The mode of attachment.
   *
8409cca70   Serge E. Hallyn   userns: allow ptr...
124
125
126
127
128
129
   * If we are in the same or an ancestor user_ns and have all the target
   * task's capabilities, then ptrace access is allowed.
   * If we have the ptrace capability to the target user_ns, then ptrace
   * access is allowed.
   * Else denied.
   *
1d045980e   David Howells   CRED: Prettify co...
130
131
132
   * Determine whether a process may access another, returning 0 if permission
   * granted, -ve if denied.
   */
9e48858f7   Ingo Molnar   security: rename ...
133
  int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
135
  	int ret = 0;
8409cca70   Serge E. Hallyn   userns: allow ptr...
136
  	const struct cred *cred, *child_cred;
caaee6234   Jann Horn   ptrace: use fsuid...
137
  	const kernel_cap_t *caller_caps;
c69e8d9c0   David Howells   CRED: Use RCU to ...
138
139
  
  	rcu_read_lock();
8409cca70   Serge E. Hallyn   userns: allow ptr...
140
141
  	cred = current_cred();
  	child_cred = __task_cred(child);
caaee6234   Jann Horn   ptrace: use fsuid...
142
143
144
145
  	if (mode & PTRACE_MODE_FSCREDS)
  		caller_caps = &cred->cap_effective;
  	else
  		caller_caps = &cred->cap_permitted;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
146
  	if (cred->user_ns == child_cred->user_ns &&
caaee6234   Jann Horn   ptrace: use fsuid...
147
  	    cap_issubset(child_cred->cap_permitted, *caller_caps))
8409cca70   Serge E. Hallyn   userns: allow ptr...
148
  		goto out;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
149
  	if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))
8409cca70   Serge E. Hallyn   userns: allow ptr...
150
151
152
  		goto out;
  	ret = -EPERM;
  out:
c69e8d9c0   David Howells   CRED: Use RCU to ...
153
154
  	rcu_read_unlock();
  	return ret;
5cd9c58fb   David Howells   security: Fix set...
155
  }
1d045980e   David Howells   CRED: Prettify co...
156
157
158
159
  /**
   * cap_ptrace_traceme - Determine whether another process may trace the current
   * @parent: The task proposed to be the tracer
   *
8409cca70   Serge E. Hallyn   userns: allow ptr...
160
161
162
163
164
165
   * If parent is in the same or an ancestor user_ns and has all current's
   * capabilities, then ptrace access is allowed.
   * If parent has the ptrace capability to current's user_ns, then ptrace
   * access is allowed.
   * Else denied.
   *
1d045980e   David Howells   CRED: Prettify co...
166
167
168
   * Determine whether the nominated task is permitted to trace the current
   * process, returning 0 if permission is granted, -ve if denied.
   */
5cd9c58fb   David Howells   security: Fix set...
169
170
  int cap_ptrace_traceme(struct task_struct *parent)
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
171
  	int ret = 0;
8409cca70   Serge E. Hallyn   userns: allow ptr...
172
  	const struct cred *cred, *child_cred;
c69e8d9c0   David Howells   CRED: Use RCU to ...
173
174
  
  	rcu_read_lock();
8409cca70   Serge E. Hallyn   userns: allow ptr...
175
176
  	cred = __task_cred(parent);
  	child_cred = current_cred();
c4a4d6037   Eric W. Biederman   userns: Use cred-...
177
  	if (cred->user_ns == child_cred->user_ns &&
8409cca70   Serge E. Hallyn   userns: allow ptr...
178
179
  	    cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
  		goto out;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
180
  	if (has_ns_capability(parent, child_cred->user_ns, CAP_SYS_PTRACE))
8409cca70   Serge E. Hallyn   userns: allow ptr...
181
182
183
  		goto out;
  	ret = -EPERM;
  out:
c69e8d9c0   David Howells   CRED: Use RCU to ...
184
185
  	rcu_read_unlock();
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  }
1d045980e   David Howells   CRED: Prettify co...
187
188
189
190
191
192
193
194
195
196
197
198
  /**
   * cap_capget - Retrieve a task's capability sets
   * @target: The task from which to retrieve the capability sets
   * @effective: The place to record the effective set
   * @inheritable: The place to record the inheritable set
   * @permitted: The place to record the permitted set
   *
   * This function retrieves the capabilities of the nominated task and returns
   * them to the caller.
   */
  int cap_capget(struct task_struct *target, kernel_cap_t *effective,
  	       kernel_cap_t *inheritable, kernel_cap_t *permitted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
200
  	const struct cred *cred;
b6dff3ec5   David Howells   CRED: Separate ta...
201

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	/* Derived from kernel/capability.c:sys_capget. */
c69e8d9c0   David Howells   CRED: Use RCU to ...
203
204
  	rcu_read_lock();
  	cred = __task_cred(target);
b6dff3ec5   David Howells   CRED: Separate ta...
205
206
207
  	*effective   = cred->cap_effective;
  	*inheritable = cred->cap_inheritable;
  	*permitted   = cred->cap_permitted;
c69e8d9c0   David Howells   CRED: Use RCU to ...
208
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
211
212
213
214
  /*
   * Determine whether the inheritable capabilities are limited to the old
   * permitted set.  Returns 1 if they are limited, 0 if they are not.
   */
72c2d5823   Andrew Morgan   V3 file capabilit...
215
216
  static inline int cap_inh_is_capped(void)
  {
72c2d5823   Andrew Morgan   V3 file capabilit...
217

1d045980e   David Howells   CRED: Prettify co...
218
219
220
  	/* they are so limited unless the current task has the CAP_SETPCAP
  	 * capability
  	 */
c4a4d6037   Eric W. Biederman   userns: Use cred-...
221
  	if (cap_capable(current_cred(), current_cred()->user_ns,
6a9de4911   Eric Paris   capabilities: rem...
222
  			CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
1d045980e   David Howells   CRED: Prettify co...
223
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
224
  	return 1;
1209726ce   Andrew G. Morgan   security: filesys...
225
  }
72c2d5823   Andrew Morgan   V3 file capabilit...
226

1d045980e   David Howells   CRED: Prettify co...
227
228
229
230
231
232
233
234
235
236
237
238
  /**
   * cap_capset - Validate and apply proposed changes to current's capabilities
   * @new: The proposed new credentials; alterations should be made here
   * @old: The current task's current credentials
   * @effective: A pointer to the proposed new effective capabilities set
   * @inheritable: A pointer to the proposed new inheritable capabilities set
   * @permitted: A pointer to the proposed new permitted capabilities set
   *
   * This function validates and applies a proposed mass change to the current
   * process's capability sets.  The changes are made to the proposed new
   * credentials, and assuming no error, will be committed by the caller of LSM.
   */
d84f4f992   David Howells   CRED: Inaugurate ...
239
240
241
242
243
  int cap_capset(struct cred *new,
  	       const struct cred *old,
  	       const kernel_cap_t *effective,
  	       const kernel_cap_t *inheritable,
  	       const kernel_cap_t *permitted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  {
d84f4f992   David Howells   CRED: Inaugurate ...
245
246
247
248
  	if (cap_inh_is_capped() &&
  	    !cap_issubset(*inheritable,
  			  cap_combine(old->cap_inheritable,
  				      old->cap_permitted)))
72c2d5823   Andrew Morgan   V3 file capabilit...
249
  		/* incapable of using this inheritable set */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  		return -EPERM;
d84f4f992   David Howells   CRED: Inaugurate ...
251

3b7391de6   Serge E. Hallyn   capabilities: int...
252
  	if (!cap_issubset(*inheritable,
d84f4f992   David Howells   CRED: Inaugurate ...
253
254
  			  cap_combine(old->cap_inheritable,
  				      old->cap_bset)))
3b7391de6   Serge E. Hallyn   capabilities: int...
255
256
  		/* no new pI capabilities outside bounding set */
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  
  	/* verify restrictions on target's new Permitted set */
d84f4f992   David Howells   CRED: Inaugurate ...
259
  	if (!cap_issubset(*permitted, old->cap_permitted))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
  
  	/* verify the _new_Effective_ is a subset of the _new_Permitted_ */
d84f4f992   David Howells   CRED: Inaugurate ...
263
  	if (!cap_issubset(*effective, *permitted))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

d84f4f992   David Howells   CRED: Inaugurate ...
266
267
268
  	new->cap_effective   = *effective;
  	new->cap_inheritable = *inheritable;
  	new->cap_permitted   = *permitted;
58319057b   Andy Lutomirski   capabilities: amb...
269
270
271
272
273
274
275
276
277
278
  
  	/*
  	 * Mask off ambient bits that are no longer both permitted and
  	 * inheritable.
  	 */
  	new->cap_ambient = cap_intersect(new->cap_ambient,
  					 cap_intersect(*permitted,
  						       *inheritable));
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
281
282
283
284
285
286
  /**
   * cap_inode_need_killpriv - Determine if inode change affects privileges
   * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV
   *
   * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV
   * affects the security markings on that inode, and if it is, should
ab5348c9c   Stefan Berger   security: fix des...
287
   * inode_killpriv() be invoked or the change rejected.
1d045980e   David Howells   CRED: Prettify co...
288
   *
ab5348c9c   Stefan Berger   security: fix des...
289
290
   * Returns 1 if security.capability has a value, meaning inode_killpriv()
   * is required, 0 otherwise, meaning inode_killpriv() is not required.
1d045980e   David Howells   CRED: Prettify co...
291
   */
b53767719   Serge E. Hallyn   Implement file po...
292
293
  int cap_inode_need_killpriv(struct dentry *dentry)
  {
c6f493d63   David Howells   VFS: security/: d...
294
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
295
  	int error;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
296
297
  	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
  	return error > 0;
b53767719   Serge E. Hallyn   Implement file po...
298
  }
1d045980e   David Howells   CRED: Prettify co...
299
300
301
302
303
304
305
306
  /**
   * cap_inode_killpriv - Erase the security markings on an inode
   * @dentry: The inode/dentry to alter
   *
   * Erase the privilege-enhancing security markings on an inode.
   *
   * Returns 0 if successful, -ve on error.
   */
b53767719   Serge E. Hallyn   Implement file po...
307
308
  int cap_inode_killpriv(struct dentry *dentry)
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
309
  	int error;
b53767719   Serge E. Hallyn   Implement file po...
310

5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
311
312
313
314
  	error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
  	if (error == -EOPNOTSUPP)
  		error = 0;
  	return error;
b53767719   Serge E. Hallyn   Implement file po...
315
  }
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  static bool rootid_owns_currentns(kuid_t kroot)
  {
  	struct user_namespace *ns;
  
  	if (!uid_valid(kroot))
  		return false;
  
  	for (ns = current_user_ns(); ; ns = ns->parent) {
  		if (from_kuid(ns, kroot) == 0)
  			return true;
  		if (ns == &init_user_ns)
  			break;
  	}
  
  	return false;
  }
  
  static __u32 sansflags(__u32 m)
  {
  	return m & ~VFS_CAP_FLAGS_EFFECTIVE;
  }
df4373c51   Eric Biggers   capabilities: fix...
337
  static bool is_v2header(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
338
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
339
340
  	if (size != XATTR_CAPS_SZ_2)
  		return false;
df4373c51   Eric Biggers   capabilities: fix...
341
  	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
342
  }
df4373c51   Eric Biggers   capabilities: fix...
343
  static bool is_v3header(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
344
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
345
346
  	if (size != XATTR_CAPS_SZ_3)
  		return false;
df4373c51   Eric Biggers   capabilities: fix...
347
  	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  }
  
  /*
   * getsecurity: We are called for security.* before any attempt to read the
   * xattr from the inode itself.
   *
   * This gives us a chance to read the on-disk value and convert it.  If we
   * return -EOPNOTSUPP, then vfs_getxattr() will call the i_op handler.
   *
   * Note we are not called by vfs_getxattr_alloc(), but that is only called
   * by the integrity subsystem, which really wants the unconverted values -
   * so that's good.
   */
  int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
  			  bool alloc)
  {
  	int size, ret;
  	kuid_t kroot;
  	uid_t root, mappedroot;
  	char *tmpbuf = NULL;
  	struct vfs_cap_data *cap;
  	struct vfs_ns_cap_data *nscap;
  	struct dentry *dentry;
  	struct user_namespace *fs_ns;
  
  	if (strcmp(name, "capability") != 0)
  		return -EOPNOTSUPP;
5a842ecca   Eddie.Horng   cap_inode_getsecu...
375
  	dentry = d_find_any_alias(inode);
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
376
377
378
379
380
381
382
383
384
385
386
387
388
  	if (!dentry)
  		return -EINVAL;
  
  	size = sizeof(struct vfs_ns_cap_data);
  	ret = (int) vfs_getxattr_alloc(dentry, XATTR_NAME_CAPS,
  				 &tmpbuf, size, GFP_NOFS);
  	dput(dentry);
  
  	if (ret < 0)
  		return ret;
  
  	fs_ns = inode->i_sb->s_user_ns;
  	cap = (struct vfs_cap_data *) tmpbuf;
df4373c51   Eric Biggers   capabilities: fix...
389
  	if (is_v2header((size_t) ret, cap)) {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
390
391
392
393
394
395
396
  		/* If this is sizeof(vfs_cap_data) then we're ok with the
  		 * on-disk value, so return that.  */
  		if (alloc)
  			*buffer = tmpbuf;
  		else
  			kfree(tmpbuf);
  		return ret;
df4373c51   Eric Biggers   capabilities: fix...
397
  	} else if (!is_v3header((size_t) ret, cap)) {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
  		kfree(tmpbuf);
  		return -EINVAL;
  	}
  
  	nscap = (struct vfs_ns_cap_data *) tmpbuf;
  	root = le32_to_cpu(nscap->rootid);
  	kroot = make_kuid(fs_ns, root);
  
  	/* If the root kuid maps to a valid uid in current ns, then return
  	 * this as a nscap. */
  	mappedroot = from_kuid(current_user_ns(), kroot);
  	if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) {
  		if (alloc) {
  			*buffer = tmpbuf;
  			nscap->rootid = cpu_to_le32(mappedroot);
  		} else
  			kfree(tmpbuf);
  		return size;
  	}
  
  	if (!rootid_owns_currentns(kroot)) {
  		kfree(tmpbuf);
  		return -EOPNOTSUPP;
  	}
  
  	/* This comes from a parent namespace.  Return as a v2 capability */
  	size = sizeof(struct vfs_cap_data);
  	if (alloc) {
  		*buffer = kmalloc(size, GFP_ATOMIC);
  		if (*buffer) {
  			struct vfs_cap_data *cap = *buffer;
  			__le32 nsmagic, magic;
  			magic = VFS_CAP_REVISION_2;
  			nsmagic = le32_to_cpu(nscap->magic_etc);
  			if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE)
  				magic |= VFS_CAP_FLAGS_EFFECTIVE;
  			memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
  			cap->magic_etc = cpu_to_le32(magic);
77df079be   Tetsuo Handa   commoncap: Handle...
436
437
  		} else {
  			size = -ENOMEM;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  		}
  	}
  	kfree(tmpbuf);
  	return size;
  }
  
  static kuid_t rootid_from_xattr(const void *value, size_t size,
  				struct user_namespace *task_ns)
  {
  	const struct vfs_ns_cap_data *nscap = value;
  	uid_t rootid = 0;
  
  	if (size == XATTR_CAPS_SZ_3)
  		rootid = le32_to_cpu(nscap->rootid);
  
  	return make_kuid(task_ns, rootid);
  }
df4373c51   Eric Biggers   capabilities: fix...
455
  static bool validheader(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
456
  {
df4373c51   Eric Biggers   capabilities: fix...
457
  	return is_v2header(size, cap) || is_v3header(size, cap);
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  }
  
  /*
   * User requested a write of security.capability.  If needed, update the
   * xattr to change from v2 to v3, or to fixup the v3 rootid.
   *
   * If all is ok, we return the new size, on error return < 0.
   */
  int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size)
  {
  	struct vfs_ns_cap_data *nscap;
  	uid_t nsrootid;
  	const struct vfs_cap_data *cap = *ivalue;
  	__u32 magic, nsmagic;
  	struct inode *inode = d_backing_inode(dentry);
  	struct user_namespace *task_ns = current_user_ns(),
  		*fs_ns = inode->i_sb->s_user_ns;
  	kuid_t rootid;
  	size_t newsize;
  
  	if (!*ivalue)
  		return -EINVAL;
df4373c51   Eric Biggers   capabilities: fix...
480
  	if (!validheader(size, cap))
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  		return -EINVAL;
  	if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
  		return -EPERM;
  	if (size == XATTR_CAPS_SZ_2)
  		if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP))
  			/* user is privileged, just write the v2 */
  			return size;
  
  	rootid = rootid_from_xattr(*ivalue, size, task_ns);
  	if (!uid_valid(rootid))
  		return -EINVAL;
  
  	nsrootid = from_kuid(fs_ns, rootid);
  	if (nsrootid == -1)
  		return -EINVAL;
  
  	newsize = sizeof(struct vfs_ns_cap_data);
  	nscap = kmalloc(newsize, GFP_ATOMIC);
  	if (!nscap)
  		return -ENOMEM;
  	nscap->rootid = cpu_to_le32(nsrootid);
  	nsmagic = VFS_CAP_REVISION_3;
  	magic = le32_to_cpu(cap->magic_etc);
  	if (magic & VFS_CAP_FLAGS_EFFECTIVE)
  		nsmagic |= VFS_CAP_FLAGS_EFFECTIVE;
  	nscap->magic_etc = cpu_to_le32(nsmagic);
  	memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
  
  	kvfree(*ivalue);
  	*ivalue = nscap;
  	return newsize;
  }
1d045980e   David Howells   CRED: Prettify co...
513
514
515
516
  /*
   * Calculate the new process capability sets from the capability sets attached
   * to a file.
   */
c0b004413   Eric Paris   This patch add a ...
517
  static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
a6f76f23d   David Howells   CRED: Make execve...
518
  					  struct linux_binprm *bprm,
4d49f6710   Zhi Li   capabilities: do ...
519
520
  					  bool *effective,
  					  bool *has_cap)
b53767719   Serge E. Hallyn   Implement file po...
521
  {
a6f76f23d   David Howells   CRED: Make execve...
522
  	struct cred *new = bprm->cred;
c0b004413   Eric Paris   This patch add a ...
523
524
525
526
  	unsigned i;
  	int ret = 0;
  
  	if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
a6f76f23d   David Howells   CRED: Make execve...
527
  		*effective = true;
c0b004413   Eric Paris   This patch add a ...
528

4d49f6710   Zhi Li   capabilities: do ...
529
530
  	if (caps->magic_etc & VFS_CAP_REVISION_MASK)
  		*has_cap = true;
c0b004413   Eric Paris   This patch add a ...
531
532
533
534
535
536
  	CAP_FOR_EACH_U32(i) {
  		__u32 permitted = caps->permitted.cap[i];
  		__u32 inheritable = caps->inheritable.cap[i];
  
  		/*
  		 * pP' = (X & fP) | (pI & fI)
58319057b   Andy Lutomirski   capabilities: amb...
537
  		 * The addition of pA' is handled later.
c0b004413   Eric Paris   This patch add a ...
538
  		 */
a6f76f23d   David Howells   CRED: Make execve...
539
540
541
  		new->cap_permitted.cap[i] =
  			(new->cap_bset.cap[i] & permitted) |
  			(new->cap_inheritable.cap[i] & inheritable);
c0b004413   Eric Paris   This patch add a ...
542

a6f76f23d   David Howells   CRED: Make execve...
543
544
  		if (permitted & ~new->cap_permitted.cap[i])
  			/* insufficient to execute correctly */
c0b004413   Eric Paris   This patch add a ...
545
  			ret = -EPERM;
c0b004413   Eric Paris   This patch add a ...
546
547
548
549
550
551
552
  	}
  
  	/*
  	 * For legacy apps, with no internal support for recognizing they
  	 * do not have enough capabilities, we return an error if they are
  	 * missing some "forced" (aka file-permitted) capabilities.
  	 */
a6f76f23d   David Howells   CRED: Make execve...
553
  	return *effective ? ret : 0;
c0b004413   Eric Paris   This patch add a ...
554
  }
1d045980e   David Howells   CRED: Prettify co...
555
556
557
  /*
   * Extract the on-exec-apply capability sets for an executable file.
   */
c0b004413   Eric Paris   This patch add a ...
558
559
  int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
  {
c6f493d63   David Howells   VFS: security/: d...
560
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
561
  	__u32 magic_etc;
e338d263a   Andrew Morgan   Add 64-bit capabi...
562
  	unsigned tocopy, i;
c0b004413   Eric Paris   This patch add a ...
563
  	int size;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
564
565
566
  	struct vfs_ns_cap_data data, *nscaps = &data;
  	struct vfs_cap_data *caps = (struct vfs_cap_data *) &data;
  	kuid_t rootkuid;
76ba89c76   Colin Ian King   commoncap: move a...
567
  	struct user_namespace *fs_ns;
c0b004413   Eric Paris   This patch add a ...
568
569
  
  	memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
570
  	if (!inode)
c0b004413   Eric Paris   This patch add a ...
571
  		return -ENODATA;
76ba89c76   Colin Ian King   commoncap: move a...
572
  	fs_ns = inode->i_sb->s_user_ns;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
573
  	size = __vfs_getxattr((struct dentry *)dentry, inode,
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
574
  			      XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ);
a6f76f23d   David Howells   CRED: Make execve...
575
  	if (size == -ENODATA || size == -EOPNOTSUPP)
c0b004413   Eric Paris   This patch add a ...
576
577
  		/* no data, that's ok */
  		return -ENODATA;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
578

c0b004413   Eric Paris   This patch add a ...
579
580
  	if (size < 0)
  		return size;
b53767719   Serge E. Hallyn   Implement file po...
581

e338d263a   Andrew Morgan   Add 64-bit capabi...
582
  	if (size < sizeof(magic_etc))
b53767719   Serge E. Hallyn   Implement file po...
583
  		return -EINVAL;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
584
  	cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps->magic_etc);
b53767719   Serge E. Hallyn   Implement file po...
585

8db6c34f1   Serge E. Hallyn   Introduce v3 name...
586
  	rootkuid = make_kuid(fs_ns, 0);
a6f76f23d   David Howells   CRED: Make execve...
587
  	switch (magic_etc & VFS_CAP_REVISION_MASK) {
e338d263a   Andrew Morgan   Add 64-bit capabi...
588
589
590
591
592
593
594
595
596
597
  	case VFS_CAP_REVISION_1:
  		if (size != XATTR_CAPS_SZ_1)
  			return -EINVAL;
  		tocopy = VFS_CAP_U32_1;
  		break;
  	case VFS_CAP_REVISION_2:
  		if (size != XATTR_CAPS_SZ_2)
  			return -EINVAL;
  		tocopy = VFS_CAP_U32_2;
  		break;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
598
599
600
601
602
603
  	case VFS_CAP_REVISION_3:
  		if (size != XATTR_CAPS_SZ_3)
  			return -EINVAL;
  		tocopy = VFS_CAP_U32_3;
  		rootkuid = make_kuid(fs_ns, le32_to_cpu(nscaps->rootid));
  		break;
b53767719   Serge E. Hallyn   Implement file po...
604
605
606
  	default:
  		return -EINVAL;
  	}
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
607
608
609
610
611
  	/* Limit the caps to the mounter of the filesystem
  	 * or the more limited uid specified in the xattr.
  	 */
  	if (!rootid_owns_currentns(rootkuid))
  		return -ENODATA;
e338d263a   Andrew Morgan   Add 64-bit capabi...
612

5459c164f   Andrew G. Morgan   security: protect...
613
  	CAP_FOR_EACH_U32(i) {
c0b004413   Eric Paris   This patch add a ...
614
615
  		if (i >= tocopy)
  			break;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
616
617
  		cpu_caps->permitted.cap[i] = le32_to_cpu(caps->data[i].permitted);
  		cpu_caps->inheritable.cap[i] = le32_to_cpu(caps->data[i].inheritable);
e338d263a   Andrew Morgan   Add 64-bit capabi...
618
  	}
a6f76f23d   David Howells   CRED: Make execve...
619

7d8b6c637   Eric Paris   CAPABILITIES: rem...
620
621
  	cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
  	cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
c0b004413   Eric Paris   This patch add a ...
622
  	return 0;
b53767719   Serge E. Hallyn   Implement file po...
623
  }
1d045980e   David Howells   CRED: Prettify co...
624
625
626
627
628
  /*
   * Attempt to get the on-exec apply capability sets for an executable file from
   * its xattrs and, if present, apply them to the proposed credentials being
   * constructed by execve().
   */
4d49f6710   Zhi Li   capabilities: do ...
629
  static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap)
b53767719   Serge E. Hallyn   Implement file po...
630
  {
b53767719   Serge E. Hallyn   Implement file po...
631
  	int rc = 0;
c0b004413   Eric Paris   This patch add a ...
632
  	struct cpu_vfs_cap_data vcaps;
b53767719   Serge E. Hallyn   Implement file po...
633

ee67ae7ef   Kees Cook   commoncap: Move c...
634
  	cap_clear(bprm->cred->cap_permitted);
3318a386e   Serge Hallyn   file caps: always...
635

1f29fae29   Serge E. Hallyn   file capabilities...
636
637
  	if (!file_caps_enabled)
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
638
  	if (!mnt_may_suid(bprm->file->f_path.mnt))
b53767719   Serge E. Hallyn   Implement file po...
639
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
640
641
642
643
644
645
  
  	/*
  	 * This check is redundant with mnt_may_suid() but is kept to make
  	 * explicit that capability bits are limited to s_user_ns and its
  	 * descendants.
  	 */
d07b846f6   Seth Forshee   fs: Limit file ca...
646
647
  	if (!current_in_userns(bprm->file->f_path.mnt->mnt_sb->s_user_ns))
  		return 0;
b53767719   Serge E. Hallyn   Implement file po...
648

f4a4a8b12   Al Viro   file->f_path.dent...
649
  	rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
c0b004413   Eric Paris   This patch add a ...
650
651
  	if (rc < 0) {
  		if (rc == -EINVAL)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
652
653
654
  			printk(KERN_NOTICE "Invalid argument reading file caps for %s
  ",
  					bprm->filename);
c0b004413   Eric Paris   This patch add a ...
655
656
  		else if (rc == -ENODATA)
  			rc = 0;
b53767719   Serge E. Hallyn   Implement file po...
657
658
  		goto out;
  	}
b53767719   Serge E. Hallyn   Implement file po...
659

4d49f6710   Zhi Li   capabilities: do ...
660
  	rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_cap);
a6f76f23d   David Howells   CRED: Make execve...
661
662
663
664
  	if (rc == -EINVAL)
  		printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s
  ",
  		       __func__, rc, bprm->filename);
b53767719   Serge E. Hallyn   Implement file po...
665
666
  
  out:
b53767719   Serge E. Hallyn   Implement file po...
667
  	if (rc)
ee67ae7ef   Kees Cook   commoncap: Move c...
668
  		cap_clear(bprm->cred->cap_permitted);
b53767719   Serge E. Hallyn   Implement file po...
669
670
671
  
  	return rc;
  }
1d045980e   David Howells   CRED: Prettify co...
672
673
674
675
676
677
678
  /**
   * cap_bprm_set_creds - Set up the proposed credentials for execve().
   * @bprm: The execution parameters, including the proposed creds
   *
   * Set up the proposed credentials for a new execution context being
   * constructed by execve().  The proposed creds in @bprm->cred is altered,
   * which won't take effect immediately.  Returns 0 if successful, -ve on error.
a6f76f23d   David Howells   CRED: Make execve...
679
680
   */
  int cap_bprm_set_creds(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  {
a6f76f23d   David Howells   CRED: Make execve...
682
683
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
58319057b   Andy Lutomirski   capabilities: amb...
684
  	bool effective, has_cap = false, is_setid;
b53767719   Serge E. Hallyn   Implement file po...
685
  	int ret;
18815a180   Eric W. Biederman   userns: Convert c...
686
  	kuid_t root_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

58319057b   Andy Lutomirski   capabilities: amb...
688
689
  	if (WARN_ON(!cap_ambient_invariant_ok(old)))
  		return -EPERM;
a6f76f23d   David Howells   CRED: Make execve...
690
  	effective = false;
4d49f6710   Zhi Li   capabilities: do ...
691
  	ret = get_file_caps(bprm, &effective, &has_cap);
a6f76f23d   David Howells   CRED: Make execve...
692
693
  	if (ret < 0)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694

18815a180   Eric W. Biederman   userns: Convert c...
695
  	root_uid = make_kuid(new->user_ns, 0);
5459c164f   Andrew G. Morgan   security: protect...
696
697
  	if (!issecure(SECURE_NOROOT)) {
  		/*
b5f22a59c   Serge E. Hallyn   don't raise all p...
698
699
700
701
  		 * If the legacy file capability is set, then don't set privs
  		 * for a setuid root binary run by a non-root user.  Do set it
  		 * for a root user just to cause least surprise to an admin.
  		 */
18815a180   Eric W. Biederman   userns: Convert c...
702
  		if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) {
b5f22a59c   Serge E. Hallyn   don't raise all p...
703
704
705
706
  			warn_setuid_and_fcaps_mixed(bprm->filename);
  			goto skip;
  		}
  		/*
5459c164f   Andrew G. Morgan   security: protect...
707
708
709
710
  		 * To support inheritance of root-permissions and suid-root
  		 * executables under compatibility mode, we override the
  		 * capability sets for the file.
  		 *
a6f76f23d   David Howells   CRED: Make execve...
711
  		 * If only the real uid is 0, we do not set the effective bit.
5459c164f   Andrew G. Morgan   security: protect...
712
  		 */
18815a180   Eric W. Biederman   userns: Convert c...
713
  		if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) {
5459c164f   Andrew G. Morgan   security: protect...
714
  			/* pP' = (cap_bset & ~0) | (pI & ~0) */
a6f76f23d   David Howells   CRED: Make execve...
715
716
  			new->cap_permitted = cap_combine(old->cap_bset,
  							 old->cap_inheritable);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  		}
18815a180   Eric W. Biederman   userns: Convert c...
718
  		if (uid_eq(new->euid, root_uid))
a6f76f23d   David Howells   CRED: Make execve...
719
  			effective = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  	}
b5f22a59c   Serge E. Hallyn   don't raise all p...
721
  skip:
b53767719   Serge E. Hallyn   Implement file po...
722

d52fc5dde   Eric Paris   fcaps: clear the ...
723
724
725
  	/* if we have fs caps, clear dangerous personality flags */
  	if (!cap_issubset(new->cap_permitted, old->cap_permitted))
  		bprm->per_clear |= PER_CLEAR_ON_SETID;
a6f76f23d   David Howells   CRED: Make execve...
726
  	/* Don't let someone trace a set[ug]id/setpcap binary with the revised
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
727
728
729
  	 * credentials unless they have the appropriate permit.
  	 *
  	 * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
a6f76f23d   David Howells   CRED: Make execve...
730
  	 */
58319057b   Andy Lutomirski   capabilities: amb...
731
732
733
  	is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
  
  	if ((is_setid ||
a6f76f23d   David Howells   CRED: Make execve...
734
  	     !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
9227dd2a8   Eric W. Biederman   exec: Remove LSM_...
735
  	    ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) ||
20523132e   Eric W. Biederman   exec: Test the pt...
736
  	     !ptracer_capable(current, new->user_ns))) {
a6f76f23d   David Howells   CRED: Make execve...
737
  		/* downgrade; they get no more than they had, and maybe less */
70169420f   Eric W. Biederman   exec: Don't reset...
738
  		if (!ns_capable(new->user_ns, CAP_SETUID) ||
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
739
  		    (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
a6f76f23d   David Howells   CRED: Make execve...
740
741
  			new->euid = new->uid;
  			new->egid = new->gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  		}
b3a222e52   Serge E. Hallyn   remove CONFIG_SEC...
743
744
  		new->cap_permitted = cap_intersect(new->cap_permitted,
  						   old->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  	}
a6f76f23d   David Howells   CRED: Make execve...
746
747
  	new->suid = new->fsuid = new->euid;
  	new->sgid = new->fsgid = new->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748

58319057b   Andy Lutomirski   capabilities: amb...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  	/* File caps or setid cancels ambient. */
  	if (has_cap || is_setid)
  		cap_clear(new->cap_ambient);
  
  	/*
  	 * Now that we've computed pA', update pP' to give:
  	 *   pP' = (X & fP) | (pI & fI) | pA'
  	 */
  	new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient);
  
  	/*
  	 * Set pE' = (fE ? pP' : pA').  Because pA' is zero if fE is set,
  	 * this is the same as pE' = (fE ? pP' : 0) | pA'.
  	 */
4bf2ea77d   Eric Paris   capabilities: do ...
763
764
765
  	if (effective)
  		new->cap_effective = new->cap_permitted;
  	else
58319057b   Andy Lutomirski   capabilities: amb...
766
767
768
769
  		new->cap_effective = new->cap_ambient;
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
3fc689e96   Eric Paris   Any time fcaps or...
770
771
772
773
774
775
776
777
778
779
780
781
  	/*
  	 * Audit candidate if current->cap_effective is set
  	 *
  	 * We do not bother to audit if 3 things are true:
  	 *   1) cap_effective has all caps
  	 *   2) we are root
  	 *   3) root is supposed to have all caps (SECURE_NOROOT)
  	 * Since this is just a normal root execing a process.
  	 *
  	 * Number 1 above might fail if you don't have a full bset, but I think
  	 * that is interesting information to audit.
  	 */
58319057b   Andy Lutomirski   capabilities: amb...
782
  	if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
d84f4f992   David Howells   CRED: Inaugurate ...
783
  		if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
18815a180   Eric W. Biederman   userns: Convert c...
784
  		    !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
a6f76f23d   David Howells   CRED: Make execve...
785
786
787
788
789
  		    issecure(SECURE_NOROOT)) {
  			ret = audit_log_bprm_fcaps(bprm, new, old);
  			if (ret < 0)
  				return ret;
  		}
3fc689e96   Eric Paris   Any time fcaps or...
790
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791

d84f4f992   David Howells   CRED: Inaugurate ...
792
  	new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
58319057b   Andy Lutomirski   capabilities: amb...
793
794
795
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
46d98eb4e   Kees Cook   commoncap: Refact...
796
  	/* Check for privilege-elevated exec. */
ee67ae7ef   Kees Cook   commoncap: Move c...
797
798
799
800
801
802
803
  	bprm->cap_elevated = 0;
  	if (is_setid) {
  		bprm->cap_elevated = 1;
  	} else if (!uid_eq(new->uid, root_uid)) {
  		if (effective ||
  		    !cap_issubset(new->cap_permitted, new->cap_ambient))
  			bprm->cap_elevated = 1;
b53767719   Serge E. Hallyn   Implement file po...
804
  	}
ee67ae7ef   Kees Cook   commoncap: Move c...
805
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  }
1d045980e   David Howells   CRED: Prettify co...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  /**
   * cap_inode_setxattr - Determine whether an xattr may be altered
   * @dentry: The inode/dentry being altered
   * @name: The name of the xattr to be changed
   * @value: The value that the xattr will be changed to
   * @size: The size of value
   * @flags: The replacement flag
   *
   * Determine whether an xattr may be altered or set on an inode, returning 0 if
   * permission is granted, -ve if denied.
   *
   * This is used to make sure security xattrs don't get updated or set by those
   * who aren't privileged to do so.
   */
8f0cfa52a   David Howells   xattr: add missin...
821
822
  int cap_inode_setxattr(struct dentry *dentry, const char *name,
  		       const void *value, size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
824
825
826
827
828
829
830
831
832
833
  	/* Ignore non-security xattrs */
  	if (strncmp(name, XATTR_SECURITY_PREFIX,
  			sizeof(XATTR_SECURITY_PREFIX) - 1) != 0)
  		return 0;
  
  	/*
  	 * For XATTR_NAME_CAPS the check will be done in
  	 * cap_convert_nscap(), called by setxattr()
  	 */
  	if (strcmp(name, XATTR_NAME_CAPS) == 0)
b53767719   Serge E. Hallyn   Implement file po...
834
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
835

8db6c34f1   Serge E. Hallyn   Introduce v3 name...
836
  	if (!capable(CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
838
839
  		return -EPERM;
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
840
841
842
843
844
845
846
847
848
849
850
  /**
   * cap_inode_removexattr - Determine whether an xattr may be removed
   * @dentry: The inode/dentry being altered
   * @name: The name of the xattr to be changed
   *
   * Determine whether an xattr may be removed from an inode, returning 0 if
   * permission is granted, -ve if denied.
   *
   * This is used to make sure security xattrs don't get removed by those who
   * aren't privileged to remove them.
   */
8f0cfa52a   David Howells   xattr: add missin...
851
  int cap_inode_removexattr(struct dentry *dentry, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
853
854
855
856
857
858
859
860
861
862
863
  	/* Ignore non-security xattrs */
  	if (strncmp(name, XATTR_SECURITY_PREFIX,
  			sizeof(XATTR_SECURITY_PREFIX) - 1) != 0)
  		return 0;
  
  	if (strcmp(name, XATTR_NAME_CAPS) == 0) {
  		/* security.capability gets namespaced */
  		struct inode *inode = d_backing_inode(dentry);
  		if (!inode)
  			return -EINVAL;
  		if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
b53767719   Serge E. Hallyn   Implement file po...
864
865
  			return -EPERM;
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
866
  	}
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
867
  	if (!capable(CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
870
  		return -EPERM;
  	return 0;
  }
a6f76f23d   David Howells   CRED: Make execve...
871
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
876
877
878
879
880
881
882
883
884
   * cap_emulate_setxuid() fixes the effective / permitted capabilities of
   * a process after a call to setuid, setreuid, or setresuid.
   *
   *  1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
   *  {r,e,s}uid != 0, the permitted and effective capabilities are
   *  cleared.
   *
   *  2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
   *  capabilities of the process are cleared.
   *
   *  3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
   *  capabilities are set to the permitted capabilities.
   *
a6f76f23d   David Howells   CRED: Make execve...
885
   *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
   *  never happen.
   *
a6f76f23d   David Howells   CRED: Make execve...
888
   *  -astor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
892
893
894
895
896
897
898
899
   *
   * cevans - New behaviour, Oct '99
   * A process may, via prctl(), elect to keep its capabilities when it
   * calls setuid() and switches away from uid==0. Both permitted and
   * effective sets will be retained.
   * Without this change, it was impossible for a daemon to drop only some
   * of its privilege. The call to setuid(!=0) would drop all privileges!
   * Keeping uid 0 is not an option because uid 0 owns too many vital
   * files..
   * Thanks to Olaf Kirch and Peter Benie for spotting this.
   */
d84f4f992   David Howells   CRED: Inaugurate ...
900
  static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
  {
18815a180   Eric W. Biederman   userns: Convert c...
902
903
904
905
906
907
908
  	kuid_t root_uid = make_kuid(old->user_ns, 0);
  
  	if ((uid_eq(old->uid, root_uid) ||
  	     uid_eq(old->euid, root_uid) ||
  	     uid_eq(old->suid, root_uid)) &&
  	    (!uid_eq(new->uid, root_uid) &&
  	     !uid_eq(new->euid, root_uid) &&
58319057b   Andy Lutomirski   capabilities: amb...
909
910
911
912
913
914
915
916
917
918
919
920
  	     !uid_eq(new->suid, root_uid))) {
  		if (!issecure(SECURE_KEEP_CAPS)) {
  			cap_clear(new->cap_permitted);
  			cap_clear(new->cap_effective);
  		}
  
  		/*
  		 * Pre-ambient programs expect setresuid to nonroot followed
  		 * by exec to drop capabilities.  We should make sure that
  		 * this remains the case.
  		 */
  		cap_clear(new->cap_ambient);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	}
18815a180   Eric W. Biederman   userns: Convert c...
922
  	if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
923
  		cap_clear(new->cap_effective);
18815a180   Eric W. Biederman   userns: Convert c...
924
  	if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
925
  		new->cap_effective = new->cap_permitted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  }
1d045980e   David Howells   CRED: Prettify co...
927
928
929
930
931
932
933
934
935
  /**
   * cap_task_fix_setuid - Fix up the results of setuid() call
   * @new: The proposed credentials
   * @old: The current task's current credentials
   * @flags: Indications of what has changed
   *
   * Fix up the results of setuid() call before the credential changes are
   * actually applied, returning 0 to grant the changes, -ve to deny them.
   */
d84f4f992   David Howells   CRED: Inaugurate ...
936
  int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
939
940
941
  {
  	switch (flags) {
  	case LSM_SETID_RE:
  	case LSM_SETID_ID:
  	case LSM_SETID_RES:
1d045980e   David Howells   CRED: Prettify co...
942
943
  		/* juggle the capabilities to follow [RES]UID changes unless
  		 * otherwise suppressed */
d84f4f992   David Howells   CRED: Inaugurate ...
944
945
  		if (!issecure(SECURE_NO_SETUID_FIXUP))
  			cap_emulate_setxuid(new, old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947

1d045980e   David Howells   CRED: Prettify co...
948
949
950
951
  	case LSM_SETID_FS:
  		/* juggle the capabilties to follow FSUID changes, unless
  		 * otherwise suppressed
  		 *
d84f4f992   David Howells   CRED: Inaugurate ...
952
953
954
955
  		 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
  		 *          if not, we might be a bit too harsh here.
  		 */
  		if (!issecure(SECURE_NO_SETUID_FIXUP)) {
18815a180   Eric W. Biederman   userns: Convert c...
956
957
  			kuid_t root_uid = make_kuid(old->user_ns, 0);
  			if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
958
959
  				new->cap_effective =
  					cap_drop_fs_set(new->cap_effective);
1d045980e   David Howells   CRED: Prettify co...
960

18815a180   Eric W. Biederman   userns: Convert c...
961
  			if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
962
963
964
  				new->cap_effective =
  					cap_raise_fs_set(new->cap_effective,
  							 new->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  		}
d84f4f992   David Howells   CRED: Inaugurate ...
966
  		break;
1d045980e   David Howells   CRED: Prettify co...
967

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
969
970
971
972
973
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
b53767719   Serge E. Hallyn   Implement file po...
974
975
976
977
978
979
980
981
982
983
  /*
   * Rationale: code calling task_setscheduler, task_setioprio, and
   * task_setnice, assumes that
   *   . if capable(cap_sys_nice), then those actions should be allowed
   *   . if not capable(cap_sys_nice), but acting on your own processes,
   *   	then those actions should be allowed
   * This is insufficient now since you can call code without suid, but
   * yet with increased caps.
   * So we check for increased caps on the target process.
   */
de45e806a   Serge E. Hallyn   file capabilities...
984
  static int cap_safe_nice(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
985
  {
f54fb863c   Serge Hallyn   capabilities: all...
986
  	int is_subset, ret = 0;
c69e8d9c0   David Howells   CRED: Use RCU to ...
987
988
989
990
  
  	rcu_read_lock();
  	is_subset = cap_issubset(__task_cred(p)->cap_permitted,
  				 current_cred()->cap_permitted);
f54fb863c   Serge Hallyn   capabilities: all...
991
992
  	if (!is_subset && !ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
  		ret = -EPERM;
c69e8d9c0   David Howells   CRED: Use RCU to ...
993
  	rcu_read_unlock();
f54fb863c   Serge Hallyn   capabilities: all...
994
  	return ret;
b53767719   Serge E. Hallyn   Implement file po...
995
  }
1d045980e   David Howells   CRED: Prettify co...
996
997
998
  /**
   * cap_task_setscheduler - Detemine if scheduler policy change is permitted
   * @p: The task to affect
1d045980e   David Howells   CRED: Prettify co...
999
1000
1001
1002
   *
   * Detemine if the requested scheduler policy change is permitted for the
   * specified task, returning 0 if permission is granted, -ve if denied.
   */
b0ae19811   KOSAKI Motohiro   security: remove ...
1003
  int cap_task_setscheduler(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
1004
1005
1006
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
1007
1008
1009
1010
1011
1012
1013
1014
1015
  /**
   * cap_task_ioprio - Detemine if I/O priority change is permitted
   * @p: The task to affect
   * @ioprio: The I/O priority to set
   *
   * Detemine if the requested I/O priority change is permitted for the specified
   * task, returning 0 if permission is granted, -ve if denied.
   */
  int cap_task_setioprio(struct task_struct *p, int ioprio)
b53767719   Serge E. Hallyn   Implement file po...
1016
1017
1018
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
1019
1020
1021
1022
1023
1024
1025
1026
1027
  /**
   * cap_task_ioprio - Detemine if task priority change is permitted
   * @p: The task to affect
   * @nice: The nice value to set
   *
   * Detemine if the requested task priority change is permitted for the
   * specified task, returning 0 if permission is granted, -ve if denied.
   */
  int cap_task_setnice(struct task_struct *p, int nice)
b53767719   Serge E. Hallyn   Implement file po...
1028
1029
1030
  {
  	return cap_safe_nice(p);
  }
3b7391de6   Serge E. Hallyn   capabilities: int...
1031
  /*
1d045980e   David Howells   CRED: Prettify co...
1032
1033
   * Implement PR_CAPBSET_DROP.  Attempt to remove the specified capability from
   * the current task's bounding set.  Returns 0 on success, -ve on error.
3b7391de6   Serge E. Hallyn   capabilities: int...
1034
   */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1035
  static int cap_prctl_drop(unsigned long cap)
3b7391de6   Serge E. Hallyn   capabilities: int...
1036
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
1037
  	struct cred *new;
160da84db   Eric W. Biederman   userns: Allow PR_...
1038
  	if (!ns_capable(current_user_ns(), CAP_SETPCAP))
3b7391de6   Serge E. Hallyn   capabilities: int...
1039
1040
1041
  		return -EPERM;
  	if (!cap_valid(cap))
  		return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
1042

6d6f33284   Tetsuo Handa   commoncap: don't ...
1043
1044
1045
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1046
  	cap_lower(new->cap_bset, cap);
6d6f33284   Tetsuo Handa   commoncap: don't ...
1047
  	return commit_creds(new);
3b7391de6   Serge E. Hallyn   capabilities: int...
1048
  }
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1049

1d045980e   David Howells   CRED: Prettify co...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  /**
   * cap_task_prctl - Implement process control functions for this security module
   * @option: The process control function requested
   * @arg2, @arg3, @arg4, @arg5: The argument data for this function
   *
   * Allow process control functions (sys_prctl()) to alter capabilities; may
   * also deny access to other functions not otherwise implemented here.
   *
   * Returns 0 or +ve on success, -ENOSYS if this function is not implemented
   * here, other -ve on error.  If -ENOSYS is returned, sys_prctl() and other LSM
   * modules will consider performing the function.
   */
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1062
  int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
d84f4f992   David Howells   CRED: Inaugurate ...
1063
  		   unsigned long arg4, unsigned long arg5)
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1064
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
1065
  	const struct cred *old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
1066
  	struct cred *new;
d84f4f992   David Howells   CRED: Inaugurate ...
1067

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1068
1069
1070
  	switch (option) {
  	case PR_CAPBSET_READ:
  		if (!cap_valid(arg2))
6d6f33284   Tetsuo Handa   commoncap: don't ...
1071
1072
  			return -EINVAL;
  		return !!cap_raised(old->cap_bset, arg2);
d84f4f992   David Howells   CRED: Inaugurate ...
1073

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1074
  	case PR_CAPBSET_DROP:
6d6f33284   Tetsuo Handa   commoncap: don't ...
1075
  		return cap_prctl_drop(arg2);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  
  	/*
  	 * The next four prctl's remain to assist with transitioning a
  	 * system from legacy UID=0 based privilege (when filesystem
  	 * capabilities are not in use) to a system using filesystem
  	 * capabilities only - as the POSIX.1e draft intended.
  	 *
  	 * Note:
  	 *
  	 *  PR_SET_SECUREBITS =
  	 *      issecure_mask(SECURE_KEEP_CAPS_LOCKED)
  	 *    | issecure_mask(SECURE_NOROOT)
  	 *    | issecure_mask(SECURE_NOROOT_LOCKED)
  	 *    | issecure_mask(SECURE_NO_SETUID_FIXUP)
  	 *    | issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)
  	 *
  	 * will ensure that the current process and all of its
  	 * children will be locked into a pure
  	 * capability-based-privilege environment.
  	 */
  	case PR_SET_SECUREBITS:
6d6f33284   Tetsuo Handa   commoncap: don't ...
1097
1098
1099
  		if ((((old->securebits & SECURE_ALL_LOCKS) >> 1)
  		     & (old->securebits ^ arg2))			/*[1]*/
  		    || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))	/*[2]*/
d84f4f992   David Howells   CRED: Inaugurate ...
1100
  		    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))	/*[3]*/
6a9de4911   Eric Paris   capabilities: rem...
1101
  		    || (cap_capable(current_cred(),
c4a4d6037   Eric W. Biederman   userns: Use cred-...
1102
  				    current_cred()->user_ns, CAP_SETPCAP,
3699c53c4   David Howells   CRED: Fix regress...
1103
  				    SECURITY_CAP_AUDIT) != 0)		/*[4]*/
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1104
1105
1106
1107
1108
1109
1110
  			/*
  			 * [1] no changing of bits that are locked
  			 * [2] no unlocking of locks
  			 * [3] no setting of unsupported bits
  			 * [4] doing anything requires privilege (go read about
  			 *     the "sendmail capabilities bug")
  			 */
d84f4f992   David Howells   CRED: Inaugurate ...
1111
1112
  		    )
  			/* cannot change a locked bit */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1113
1114
1115
1116
1117
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1118
  		new->securebits = arg2;
6d6f33284   Tetsuo Handa   commoncap: don't ...
1119
  		return commit_creds(new);
d84f4f992   David Howells   CRED: Inaugurate ...
1120

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1121
  	case PR_GET_SECUREBITS:
6d6f33284   Tetsuo Handa   commoncap: don't ...
1122
  		return old->securebits;
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1123

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1124
  	case PR_GET_KEEPCAPS:
6d6f33284   Tetsuo Handa   commoncap: don't ...
1125
  		return !!issecure(SECURE_KEEP_CAPS);
d84f4f992   David Howells   CRED: Inaugurate ...
1126

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1127
1128
  	case PR_SET_KEEPCAPS:
  		if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1129
  			return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
1130
  		if (issecure(SECURE_KEEP_CAPS_LOCKED))
6d6f33284   Tetsuo Handa   commoncap: don't ...
1131
1132
1133
1134
1135
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1136
1137
  		if (arg2)
  			new->securebits |= issecure_mask(SECURE_KEEP_CAPS);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1138
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
1139
  			new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
6d6f33284   Tetsuo Handa   commoncap: don't ...
1140
  		return commit_creds(new);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1141

58319057b   Andy Lutomirski   capabilities: amb...
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  	case PR_CAP_AMBIENT:
  		if (arg2 == PR_CAP_AMBIENT_CLEAR_ALL) {
  			if (arg3 | arg4 | arg5)
  				return -EINVAL;
  
  			new = prepare_creds();
  			if (!new)
  				return -ENOMEM;
  			cap_clear(new->cap_ambient);
  			return commit_creds(new);
  		}
  
  		if (((!cap_valid(arg3)) | arg4 | arg5))
  			return -EINVAL;
  
  		if (arg2 == PR_CAP_AMBIENT_IS_SET) {
  			return !!cap_raised(current_cred()->cap_ambient, arg3);
  		} else if (arg2 != PR_CAP_AMBIENT_RAISE &&
  			   arg2 != PR_CAP_AMBIENT_LOWER) {
  			return -EINVAL;
  		} else {
  			if (arg2 == PR_CAP_AMBIENT_RAISE &&
  			    (!cap_raised(current_cred()->cap_permitted, arg3) ||
  			     !cap_raised(current_cred()->cap_inheritable,
746bf6d64   Andy Lutomirski   capabilities: add...
1166
1167
  					 arg3) ||
  			     issecure(SECURE_NO_CAP_AMBIENT_RAISE)))
58319057b   Andy Lutomirski   capabilities: amb...
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  				return -EPERM;
  
  			new = prepare_creds();
  			if (!new)
  				return -ENOMEM;
  			if (arg2 == PR_CAP_AMBIENT_RAISE)
  				cap_raise(new->cap_ambient, arg3);
  			else
  				cap_lower(new->cap_ambient, arg3);
  			return commit_creds(new);
  		}
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1179
1180
  	default:
  		/* No functionality available - continue with default */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1181
  		return -ENOSYS;
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1182
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  }
1d045980e   David Howells   CRED: Prettify co...
1184
  /**
1d045980e   David Howells   CRED: Prettify co...
1185
1186
1187
1188
1189
   * cap_vm_enough_memory - Determine whether a new virtual mapping is permitted
   * @mm: The VM space in which the new mapping is to be made
   * @pages: The size of the mapping
   *
   * Determine whether the allocation of a new virtual mapping by the current
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1190
   * task is permitted, returning 1 if permission is granted, 0 if not.
1d045980e   David Howells   CRED: Prettify co...
1191
   */
34b4e4aa3   Alan Cox   fix NULL pointer ...
1192
  int cap_vm_enough_memory(struct mm_struct *mm, long pages)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
1194
  {
  	int cap_sys_admin = 0;
6a9de4911   Eric Paris   capabilities: rem...
1195
  	if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
3699c53c4   David Howells   CRED: Fix regress...
1196
  			SECURITY_CAP_NOAUDIT) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
  		cap_sys_admin = 1;
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1198
  	return cap_sys_admin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  }
7c73875e7   Eric Paris   Capabilities: mov...
1200
1201
  
  /*
d007794a1   Al Viro   split cap_mmap_ad...
1202
   * cap_mmap_addr - check if able to map given addr
7c73875e7   Eric Paris   Capabilities: mov...
1203
   * @addr: address attempting to be mapped
7c73875e7   Eric Paris   Capabilities: mov...
1204
   *
6f262d8e1   wzt.wzt@gmail.com   Security: Fix the...
1205
   * If the process is attempting to map memory below dac_mmap_min_addr they need
7c73875e7   Eric Paris   Capabilities: mov...
1206
1207
1208
1209
   * CAP_SYS_RAWIO.  The other parameters to this function are unused by the
   * capability security module.  Returns 0 if this mapping should be allowed
   * -EPERM if not.
   */
d007794a1   Al Viro   split cap_mmap_ad...
1210
  int cap_mmap_addr(unsigned long addr)
7c73875e7   Eric Paris   Capabilities: mov...
1211
1212
  {
  	int ret = 0;
a2551df7e   Eric Paris   Security/SELinux:...
1213
  	if (addr < dac_mmap_min_addr) {
6a9de4911   Eric Paris   capabilities: rem...
1214
  		ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
7c73875e7   Eric Paris   Capabilities: mov...
1215
1216
1217
1218
1219
1220
1221
  				  SECURITY_CAP_AUDIT);
  		/* set PF_SUPERPRIV if it turns out we allow the low mmap */
  		if (ret == 0)
  			current->flags |= PF_SUPERPRIV;
  	}
  	return ret;
  }
d007794a1   Al Viro   split cap_mmap_ad...
1222

e5467859f   Al Viro   split ->file_mmap...
1223
1224
  int cap_mmap_file(struct file *file, unsigned long reqprot,
  		  unsigned long prot, unsigned long flags)
d007794a1   Al Viro   split cap_mmap_ad...
1225
  {
e5467859f   Al Viro   split ->file_mmap...
1226
  	return 0;
d007794a1   Al Viro   split cap_mmap_ad...
1227
  }
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1228
1229
  
  #ifdef CONFIG_SECURITY
ca97d939d   James Morris   security: mark LS...
1230
  struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1231
1232
1233
1234
1235
1236
1237
  	LSM_HOOK_INIT(capable, cap_capable),
  	LSM_HOOK_INIT(settime, cap_settime),
  	LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
  	LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme),
  	LSM_HOOK_INIT(capget, cap_capget),
  	LSM_HOOK_INIT(capset, cap_capset),
  	LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1238
1239
  	LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
  	LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
1240
  	LSM_HOOK_INIT(inode_getsecurity, cap_inode_getsecurity),
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
  	LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
  	LSM_HOOK_INIT(mmap_file, cap_mmap_file),
  	LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
  	LSM_HOOK_INIT(task_prctl, cap_task_prctl),
  	LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
  	LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
  	LSM_HOOK_INIT(task_setnice, cap_task_setnice),
  	LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
  };
  
  void __init capability_add_hooks(void)
  {
d69dece5f   Casey Schaufler   LSM: Add /sys/ker...
1253
1254
  	security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
  				"capability");
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1255
1256
1257
  }
  
  #endif /* CONFIG_SECURITY */