Blame view

security/commoncap.c 38.9 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
3e1c2515a   James Morris   security: remove ...
2
  /* Common capabilities, needed by capability.o.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   */
c59ede7b7   Randy.Dunlap   [PATCH] move capa...
4
  #include <linux/capability.h>
3fc689e96   Eric Paris   Any time fcaps or...
5
  #include <linux/audit.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
  #include <linux/init.h>
  #include <linux/kernel.h>
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
8
  #include <linux/lsm_hooks.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
  #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
14
15
16
17
18
  #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...
19
  #include <linux/mount.h>
b460cbc58   Serge E. Hallyn   pid namespaces: d...
20
  #include <linux/sched.h>
3898b1b4e   Andrew G. Morgan   capabilities: imp...
21
22
  #include <linux/prctl.h>
  #include <linux/securebits.h>
3486740a4   Serge E. Hallyn   userns: security:...
23
  #include <linux/user_namespace.h>
404015308   Al Viro   security: trim se...
24
  #include <linux/binfmts.h>
51b79bee6   Jonghwan Choi   security: fix com...
25
  #include <linux/personality.h>
72c2d5823   Andrew Morgan   V3 file capabilit...
26

b5f22a59c   Serge E. Hallyn   don't raise all p...
27
28
29
30
31
32
33
34
35
36
37
  /*
   * 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() ...
38
  static void warn_setuid_and_fcaps_mixed(const char *fname)
b5f22a59c   Serge E. Hallyn   don't raise all p...
39
40
41
42
43
44
45
46
47
48
  {
  	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...
49
50
  /**
   * cap_capable - Determine whether a task has a particular effective capability
3699c53c4   David Howells   CRED: Fix regress...
51
   * @cred: The credentials to use
3486740a4   Serge E. Hallyn   userns: security:...
52
   * @ns:  The user namespace in which we need the capability
1d045980e   David Howells   CRED: Prettify co...
53
   * @cap: The capability to check for
e88ed488a   Micah Morton   LSM: Update funct...
54
   * @opts: Bitmask of options defined in include/linux/security.h
1d045980e   David Howells   CRED: Prettify co...
55
56
57
58
   *
   * 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...
59
60
61
62
   * 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...
63
   */
6a9de4911   Eric Paris   capabilities: rem...
64
  int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
c1a85a00e   Micah Morton   LSM: generalize f...
65
  		int cap, unsigned int opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  {
520d9eabc   Eric W. Biederman   Fix cap_capable t...
67
  	struct user_namespace *ns = targ_ns;
3486740a4   Serge E. Hallyn   userns: security:...
68

520d9eabc   Eric W. Biederman   Fix cap_capable t...
69
70
71
72
73
  	/* 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:...
74
  		/* Do we have the necessary capabilities? */
520d9eabc   Eric W. Biederman   Fix cap_capable t...
75
  		if (ns == cred->user_ns)
3486740a4   Serge E. Hallyn   userns: security:...
76
  			return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
64db4c7f4   Kirill Tkhai   security: Use use...
77
78
79
80
81
  		/*
  		 * 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:...
82
  			return -EPERM;
520d9eabc   Eric W. Biederman   Fix cap_capable t...
83
84
85
86
87
88
  		/* 
  		 * 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:...
89
  		/*
520d9eabc   Eric W. Biederman   Fix cap_capable t...
90
  		 * If you have a capability in a parent user ns, then you have
3486740a4   Serge E. Hallyn   userns: security:...
91
92
  		 * it over all children user namespaces as well.
  		 */
520d9eabc   Eric W. Biederman   Fix cap_capable t...
93
  		ns = ns->parent;
3486740a4   Serge E. Hallyn   userns: security:...
94
95
96
  	}
  
  	/* We never get here */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  }
1d045980e   David Howells   CRED: Prettify co...
98
99
100
101
102
103
104
105
  /**
   * 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...
106
  int cap_settime(const struct timespec64 *ts, const struct timezone *tz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
  {
  	if (!capable(CAP_SYS_TIME))
  		return -EPERM;
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
112
  /**
9e48858f7   Ingo Molnar   security: rename ...
113
   * cap_ptrace_access_check - Determine whether the current process may access
1d045980e   David Howells   CRED: Prettify co...
114
115
116
117
   *			   another
   * @child: The process to be accessed
   * @mode: The mode of attachment.
   *
8409cca70   Serge E. Hallyn   userns: allow ptr...
118
119
120
121
122
123
   * 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...
124
125
126
   * Determine whether a process may access another, returning 0 if permission
   * granted, -ve if denied.
   */
9e48858f7   Ingo Molnar   security: rename ...
127
  int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
129
  	int ret = 0;
8409cca70   Serge E. Hallyn   userns: allow ptr...
130
  	const struct cred *cred, *child_cred;
caaee6234   Jann Horn   ptrace: use fsuid...
131
  	const kernel_cap_t *caller_caps;
c69e8d9c0   David Howells   CRED: Use RCU to ...
132
133
  
  	rcu_read_lock();
8409cca70   Serge E. Hallyn   userns: allow ptr...
134
135
  	cred = current_cred();
  	child_cred = __task_cred(child);
caaee6234   Jann Horn   ptrace: use fsuid...
136
137
138
139
  	if (mode & PTRACE_MODE_FSCREDS)
  		caller_caps = &cred->cap_effective;
  	else
  		caller_caps = &cred->cap_permitted;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
140
  	if (cred->user_ns == child_cred->user_ns &&
caaee6234   Jann Horn   ptrace: use fsuid...
141
  	    cap_issubset(child_cred->cap_permitted, *caller_caps))
8409cca70   Serge E. Hallyn   userns: allow ptr...
142
  		goto out;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
143
  	if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))
8409cca70   Serge E. Hallyn   userns: allow ptr...
144
145
146
  		goto out;
  	ret = -EPERM;
  out:
c69e8d9c0   David Howells   CRED: Use RCU to ...
147
148
  	rcu_read_unlock();
  	return ret;
5cd9c58fb   David Howells   security: Fix set...
149
  }
1d045980e   David Howells   CRED: Prettify co...
150
151
152
153
  /**
   * 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...
154
155
156
157
158
159
   * 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...
160
161
162
   * 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...
163
164
  int cap_ptrace_traceme(struct task_struct *parent)
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
165
  	int ret = 0;
8409cca70   Serge E. Hallyn   userns: allow ptr...
166
  	const struct cred *cred, *child_cred;
c69e8d9c0   David Howells   CRED: Use RCU to ...
167
168
  
  	rcu_read_lock();
8409cca70   Serge E. Hallyn   userns: allow ptr...
169
170
  	cred = __task_cred(parent);
  	child_cred = current_cred();
c4a4d6037   Eric W. Biederman   userns: Use cred-...
171
  	if (cred->user_ns == child_cred->user_ns &&
8409cca70   Serge E. Hallyn   userns: allow ptr...
172
173
  	    cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
  		goto out;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
174
  	if (has_ns_capability(parent, child_cred->user_ns, CAP_SYS_PTRACE))
8409cca70   Serge E. Hallyn   userns: allow ptr...
175
176
177
  		goto out;
  	ret = -EPERM;
  out:
c69e8d9c0   David Howells   CRED: Use RCU to ...
178
179
  	rcu_read_unlock();
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  }
1d045980e   David Howells   CRED: Prettify co...
181
182
183
184
185
186
187
188
189
190
191
192
  /**
   * 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
193
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
194
  	const struct cred *cred;
b6dff3ec5   David Howells   CRED: Separate ta...
195

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  	/* Derived from kernel/capability.c:sys_capget. */
c69e8d9c0   David Howells   CRED: Use RCU to ...
197
198
  	rcu_read_lock();
  	cred = __task_cred(target);
b6dff3ec5   David Howells   CRED: Separate ta...
199
200
201
  	*effective   = cred->cap_effective;
  	*inheritable = cred->cap_inheritable;
  	*permitted   = cred->cap_permitted;
c69e8d9c0   David Howells   CRED: Use RCU to ...
202
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
205
206
207
208
  /*
   * 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...
209
210
  static inline int cap_inh_is_capped(void)
  {
1d045980e   David Howells   CRED: Prettify co...
211
212
213
  	/* they are so limited unless the current task has the CAP_SETPCAP
  	 * capability
  	 */
c4a4d6037   Eric W. Biederman   userns: Use cred-...
214
  	if (cap_capable(current_cred(), current_cred()->user_ns,
c1a85a00e   Micah Morton   LSM: generalize f...
215
  			CAP_SETPCAP, CAP_OPT_NONE) == 0)
1d045980e   David Howells   CRED: Prettify co...
216
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
217
  	return 1;
1209726ce   Andrew G. Morgan   security: filesys...
218
  }
72c2d5823   Andrew Morgan   V3 file capabilit...
219

1d045980e   David Howells   CRED: Prettify co...
220
221
222
223
224
225
226
227
228
229
230
231
  /**
   * 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 ...
232
233
234
235
236
  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
237
  {
d84f4f992   David Howells   CRED: Inaugurate ...
238
239
240
241
  	if (cap_inh_is_capped() &&
  	    !cap_issubset(*inheritable,
  			  cap_combine(old->cap_inheritable,
  				      old->cap_permitted)))
72c2d5823   Andrew Morgan   V3 file capabilit...
242
  		/* incapable of using this inheritable set */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  		return -EPERM;
d84f4f992   David Howells   CRED: Inaugurate ...
244

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

d84f4f992   David Howells   CRED: Inaugurate ...
259
260
261
  	new->cap_effective   = *effective;
  	new->cap_inheritable = *inheritable;
  	new->cap_permitted   = *permitted;
58319057b   Andy Lutomirski   capabilities: amb...
262
263
264
265
266
267
268
269
270
271
  
  	/*
  	 * 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
272
273
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
274
275
276
277
278
279
  /**
   * 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...
280
   * inode_killpriv() be invoked or the change rejected.
1d045980e   David Howells   CRED: Prettify co...
281
   *
ab5348c9c   Stefan Berger   security: fix des...
282
283
   * 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...
284
   */
b53767719   Serge E. Hallyn   Implement file po...
285
286
  int cap_inode_need_killpriv(struct dentry *dentry)
  {
c6f493d63   David Howells   VFS: security/: d...
287
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
288
  	int error;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
289
290
  	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
  	return error > 0;
b53767719   Serge E. Hallyn   Implement file po...
291
  }
1d045980e   David Howells   CRED: Prettify co...
292
293
294
295
296
297
298
299
  /**
   * 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...
300
301
  int cap_inode_killpriv(struct dentry *dentry)
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
302
  	int error;
b53767719   Serge E. Hallyn   Implement file po...
303

5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
304
305
306
307
  	error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
  	if (error == -EOPNOTSUPP)
  		error = 0;
  	return error;
b53767719   Serge E. Hallyn   Implement file po...
308
  }
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  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;
  }
dc32b5c3e   Eric Biggers   capabilities: fix...
330
  static bool is_v2header(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
331
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
332
333
  	if (size != XATTR_CAPS_SZ_2)
  		return false;
dc32b5c3e   Eric Biggers   capabilities: fix...
334
  	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
335
  }
dc32b5c3e   Eric Biggers   capabilities: fix...
336
  static bool is_v3header(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
337
  {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
338
339
  	if (size != XATTR_CAPS_SZ_3)
  		return false;
dc32b5c3e   Eric Biggers   capabilities: fix...
340
  	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  }
  
  /*
   * 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;
355139a8d   Eddie.Horng   cap_inode_getsecu...
368
  	dentry = d_find_any_alias(inode);
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
369
370
371
372
373
374
375
376
377
378
379
380
381
  	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;
dc32b5c3e   Eric Biggers   capabilities: fix...
382
  	if (is_v2header((size_t) ret, cap)) {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
383
384
385
386
387
388
389
  		/* 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;
dc32b5c3e   Eric Biggers   capabilities: fix...
390
  	} else if (!is_v3header((size_t) ret, cap)) {
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
391
392
393
394
395
396
397
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
  		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);
1f5781725   Tetsuo Handa   commoncap: Handle...
429
430
  		} else {
  			size = -ENOMEM;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  		}
  	}
  	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);
  }
dc32b5c3e   Eric Biggers   capabilities: fix...
448
  static bool validheader(size_t size, const struct vfs_cap_data *cap)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
449
  {
dc32b5c3e   Eric Biggers   capabilities: fix...
450
  	return is_v2header(size, cap) || is_v3header(size, cap);
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  }
  
  /*
   * 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;
dc32b5c3e   Eric Biggers   capabilities: fix...
473
  	if (!validheader(size, cap))
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
474
475
476
477
478
479
480
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
  		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...
506
507
508
509
  /*
   * Calculate the new process capability sets from the capability sets attached
   * to a file.
   */
c0b004413   Eric Paris   This patch add a ...
510
  static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
a6f76f23d   David Howells   CRED: Make execve...
511
  					  struct linux_binprm *bprm,
4d49f6710   Zhi Li   capabilities: do ...
512
  					  bool *effective,
fc7eadf76   Richard Guy Briggs   capabilities: ren...
513
  					  bool *has_fcap)
b53767719   Serge E. Hallyn   Implement file po...
514
  {
a6f76f23d   David Howells   CRED: Make execve...
515
  	struct cred *new = bprm->cred;
c0b004413   Eric Paris   This patch add a ...
516
517
518
519
  	unsigned i;
  	int ret = 0;
  
  	if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
a6f76f23d   David Howells   CRED: Make execve...
520
  		*effective = true;
c0b004413   Eric Paris   This patch add a ...
521

4d49f6710   Zhi Li   capabilities: do ...
522
  	if (caps->magic_etc & VFS_CAP_REVISION_MASK)
fc7eadf76   Richard Guy Briggs   capabilities: ren...
523
  		*has_fcap = true;
4d49f6710   Zhi Li   capabilities: do ...
524

c0b004413   Eric Paris   This patch add a ...
525
526
527
528
529
530
  	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...
531
  		 * The addition of pA' is handled later.
c0b004413   Eric Paris   This patch add a ...
532
  		 */
a6f76f23d   David Howells   CRED: Make execve...
533
534
535
  		new->cap_permitted.cap[i] =
  			(new->cap_bset.cap[i] & permitted) |
  			(new->cap_inheritable.cap[i] & inheritable);
c0b004413   Eric Paris   This patch add a ...
536

a6f76f23d   David Howells   CRED: Make execve...
537
538
  		if (permitted & ~new->cap_permitted.cap[i])
  			/* insufficient to execute correctly */
c0b004413   Eric Paris   This patch add a ...
539
  			ret = -EPERM;
c0b004413   Eric Paris   This patch add a ...
540
541
542
543
544
545
546
  	}
  
  	/*
  	 * 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...
547
  	return *effective ? ret : 0;
c0b004413   Eric Paris   This patch add a ...
548
  }
1d045980e   David Howells   CRED: Prettify co...
549
550
551
  /*
   * Extract the on-exec-apply capability sets for an executable file.
   */
c0b004413   Eric Paris   This patch add a ...
552
553
  int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
  {
c6f493d63   David Howells   VFS: security/: d...
554
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
555
  	__u32 magic_etc;
e338d263a   Andrew Morgan   Add 64-bit capabi...
556
  	unsigned tocopy, i;
c0b004413   Eric Paris   This patch add a ...
557
  	int size;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
558
559
560
  	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...
561
  	struct user_namespace *fs_ns;
c0b004413   Eric Paris   This patch add a ...
562
563
  
  	memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
564
  	if (!inode)
c0b004413   Eric Paris   This patch add a ...
565
  		return -ENODATA;
76ba89c76   Colin Ian King   commoncap: move a...
566
  	fs_ns = inode->i_sb->s_user_ns;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
567
  	size = __vfs_getxattr((struct dentry *)dentry, inode,
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
568
  			      XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ);
a6f76f23d   David Howells   CRED: Make execve...
569
  	if (size == -ENODATA || size == -EOPNOTSUPP)
c0b004413   Eric Paris   This patch add a ...
570
571
  		/* no data, that's ok */
  		return -ENODATA;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
572

c0b004413   Eric Paris   This patch add a ...
573
574
  	if (size < 0)
  		return size;
b53767719   Serge E. Hallyn   Implement file po...
575

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

8db6c34f1   Serge E. Hallyn   Introduce v3 name...
580
  	rootkuid = make_kuid(fs_ns, 0);
a6f76f23d   David Howells   CRED: Make execve...
581
  	switch (magic_etc & VFS_CAP_REVISION_MASK) {
e338d263a   Andrew Morgan   Add 64-bit capabi...
582
583
584
585
586
587
588
589
590
591
  	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...
592
593
594
595
596
597
  	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...
598
599
600
  	default:
  		return -EINVAL;
  	}
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
601
602
603
604
605
  	/* 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...
606

5459c164f   Andrew G. Morgan   security: protect...
607
  	CAP_FOR_EACH_U32(i) {
c0b004413   Eric Paris   This patch add a ...
608
609
  		if (i >= tocopy)
  			break;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
610
611
  		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...
612
  	}
a6f76f23d   David Howells   CRED: Make execve...
613

7d8b6c637   Eric Paris   CAPABILITIES: rem...
614
615
  	cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
  	cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
2fec30e24   Richard Guy Briggs   audit: add suppor...
616
  	cpu_caps->rootid = rootkuid;
c0b004413   Eric Paris   This patch add a ...
617
  	return 0;
b53767719   Serge E. Hallyn   Implement file po...
618
  }
1d045980e   David Howells   CRED: Prettify co...
619
620
621
622
623
  /*
   * 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().
   */
fc7eadf76   Richard Guy Briggs   capabilities: ren...
624
  static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_fcap)
b53767719   Serge E. Hallyn   Implement file po...
625
  {
b53767719   Serge E. Hallyn   Implement file po...
626
  	int rc = 0;
c0b004413   Eric Paris   This patch add a ...
627
  	struct cpu_vfs_cap_data vcaps;
b53767719   Serge E. Hallyn   Implement file po...
628

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

1f29fae29   Serge E. Hallyn   file capabilities...
631
632
  	if (!file_caps_enabled)
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
633
  	if (!mnt_may_suid(bprm->file->f_path.mnt))
b53767719   Serge E. Hallyn   Implement file po...
634
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
635
636
637
638
639
640
  
  	/*
  	 * 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...
641
642
  	if (!current_in_userns(bprm->file->f_path.mnt->mnt_sb->s_user_ns))
  		return 0;
b53767719   Serge E. Hallyn   Implement file po...
643

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

fc7eadf76   Richard Guy Briggs   capabilities: ren...
655
  	rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_fcap);
b53767719   Serge E. Hallyn   Implement file po...
656
657
  
  out:
b53767719   Serge E. Hallyn   Implement file po...
658
  	if (rc)
ee67ae7ef   Kees Cook   commoncap: Move c...
659
  		cap_clear(bprm->cred->cap_permitted);
b53767719   Serge E. Hallyn   Implement file po...
660
661
662
  
  	return rc;
  }
9304b46c9   Richard Guy Briggs   capabilities: use...
663
  static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); }
81a6a0129   Richard Guy Briggs   capabilities: use...
664
665
666
667
668
669
670
671
  static inline bool __is_real(kuid_t uid, struct cred *cred)
  { return uid_eq(cred->uid, uid); }
  
  static inline bool __is_eff(kuid_t uid, struct cred *cred)
  { return uid_eq(cred->euid, uid); }
  
  static inline bool __is_suid(kuid_t uid, struct cred *cred)
  { return !__is_real(uid, cred) && __is_eff(uid, cred); }
db1a8922c   Richard Guy Briggs   capabilities: fac...
672
673
674
675
676
677
678
679
680
681
682
683
  /*
   * handle_privileged_root - Handle case of privileged root
   * @bprm: The execution parameters, including the proposed creds
   * @has_fcap: Are any file capabilities set?
   * @effective: Do we have effective root privilege?
   * @root_uid: This namespace' root UID WRT initial USER namespace
   *
   * Handle the case where root is privileged and hasn't been neutered by
   * SECURE_NOROOT.  If file capabilities are set, they won't be combined with
   * set UID root and nothing is changed.  If we are root, cap_permitted is
   * updated.  If we have become set UID root, the effective bit is set.
   */
fc7eadf76   Richard Guy Briggs   capabilities: ren...
684
  static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
db1a8922c   Richard Guy Briggs   capabilities: fac...
685
686
687
688
  				   bool *effective, kuid_t root_uid)
  {
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
9304b46c9   Richard Guy Briggs   capabilities: use...
689
  	if (!root_privileged())
db1a8922c   Richard Guy Briggs   capabilities: fac...
690
691
692
693
694
695
  		return;
  	/*
  	 * 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.
  	 */
81a6a0129   Richard Guy Briggs   capabilities: use...
696
  	if (has_fcap && __is_suid(root_uid, new)) {
db1a8922c   Richard Guy Briggs   capabilities: fac...
697
698
699
700
701
702
703
704
  		warn_setuid_and_fcaps_mixed(bprm->filename);
  		return;
  	}
  	/*
  	 * To support inheritance of root-permissions and suid-root
  	 * executables under compatibility mode, we override the
  	 * capability sets for the file.
  	 */
81a6a0129   Richard Guy Briggs   capabilities: use...
705
  	if (__is_eff(root_uid, new) || __is_real(root_uid, new)) {
db1a8922c   Richard Guy Briggs   capabilities: fac...
706
707
708
709
710
711
712
  		/* pP' = (cap_bset & ~0) | (pI & ~0) */
  		new->cap_permitted = cap_combine(old->cap_bset,
  						 old->cap_inheritable);
  	}
  	/*
  	 * If only the real uid is 0, we do not set the effective bit.
  	 */
81a6a0129   Richard Guy Briggs   capabilities: use...
713
  	if (__is_eff(root_uid, new))
db1a8922c   Richard Guy Briggs   capabilities: fac...
714
715
  		*effective = true;
  }
4c7e715fc   Richard Guy Briggs   capabilities: int...
716
717
718
719
720
721
  #define __cap_gained(field, target, source) \
  	!cap_issubset(target->cap_##field, source->cap_##field)
  #define __cap_grew(target, source, cred) \
  	!cap_issubset(cred->cap_##target, cred->cap_##source)
  #define __cap_full(field, cred) \
  	cap_issubset(CAP_FULL_SET, cred->cap_##field)
81a6a0129   Richard Guy Briggs   capabilities: use...
722
723
724
725
726
727
  
  static inline bool __is_setuid(struct cred *new, const struct cred *old)
  { return !uid_eq(new->euid, old->uid); }
  
  static inline bool __is_setgid(struct cred *new, const struct cred *old)
  { return !gid_eq(new->egid, old->gid); }
9fbc2c796   Richard Guy Briggs   capabilities: mov...
728
  /*
dbbbe1105   Richard Guy Briggs   capabilities: aud...
729
   * 1) Audit candidate if current->cap_effective is set
9fbc2c796   Richard Guy Briggs   capabilities: mov...
730
731
732
   *
   * We do not bother to audit if 3 things are true:
   *   1) cap_effective has all caps
588fb2c7e   Richard Guy Briggs   capabilities: fix...
733
   *   2) we became root *OR* are were already root
9fbc2c796   Richard Guy Briggs   capabilities: mov...
734
735
736
737
738
   *   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.
dbbbe1105   Richard Guy Briggs   capabilities: aud...
739
740
741
742
743
   *
   * A number of other conditions require logging:
   * 2) something prevented setuid root getting all caps
   * 3) non-setuid root gets fcaps
   * 4) non-setuid root gets ambient
9fbc2c796   Richard Guy Briggs   capabilities: mov...
744
   */
dbbbe1105   Richard Guy Briggs   capabilities: aud...
745
746
  static inline bool nonroot_raised_pE(struct cred *new, const struct cred *old,
  				     kuid_t root, bool has_fcap)
9fbc2c796   Richard Guy Briggs   capabilities: mov...
747
748
  {
  	bool ret = false;
dbbbe1105   Richard Guy Briggs   capabilities: aud...
749
750
751
752
753
754
755
756
757
758
759
  	if ((__cap_grew(effective, ambient, new) &&
  	     !(__cap_full(effective, new) &&
  	       (__is_eff(root, new) || __is_real(root, new)) &&
  	       root_privileged())) ||
  	    (root_privileged() &&
  	     __is_suid(root, new) &&
  	     !__cap_full(effective, new)) ||
  	    (!__is_setuid(new, old) &&
  	     ((has_fcap &&
  	       __cap_gained(permitted, new, old)) ||
  	      __cap_gained(ambient, new, old))))
02ebbaf48   Richard Guy Briggs   capabilities: rem...
760
  		ret = true;
dbbbe1105   Richard Guy Briggs   capabilities: aud...
761

9fbc2c796   Richard Guy Briggs   capabilities: mov...
762
763
  	return ret;
  }
1d045980e   David Howells   CRED: Prettify co...
764
765
766
767
768
769
770
  /**
   * 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...
771
772
   */
  int cap_bprm_set_creds(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
  {
a6f76f23d   David Howells   CRED: Make execve...
774
775
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
fc7eadf76   Richard Guy Briggs   capabilities: ren...
776
  	bool effective = false, has_fcap = false, is_setid;
b53767719   Serge E. Hallyn   Implement file po...
777
  	int ret;
18815a180   Eric W. Biederman   userns: Convert c...
778
  	kuid_t root_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779

58319057b   Andy Lutomirski   capabilities: amb...
780
781
  	if (WARN_ON(!cap_ambient_invariant_ok(old)))
  		return -EPERM;
fc7eadf76   Richard Guy Briggs   capabilities: ren...
782
  	ret = get_file_caps(bprm, &effective, &has_fcap);
a6f76f23d   David Howells   CRED: Make execve...
783
784
  	if (ret < 0)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785

18815a180   Eric W. Biederman   userns: Convert c...
786
  	root_uid = make_kuid(new->user_ns, 0);
fc7eadf76   Richard Guy Briggs   capabilities: ren...
787
  	handle_privileged_root(bprm, has_fcap, &effective, root_uid);
b53767719   Serge E. Hallyn   Implement file po...
788

d52fc5dde   Eric Paris   fcaps: clear the ...
789
  	/* if we have fs caps, clear dangerous personality flags */
4c7e715fc   Richard Guy Briggs   capabilities: int...
790
  	if (__cap_gained(permitted, new, old))
d52fc5dde   Eric Paris   fcaps: clear the ...
791
  		bprm->per_clear |= PER_CLEAR_ON_SETID;
a6f76f23d   David Howells   CRED: Make execve...
792
  	/* Don't let someone trace a set[ug]id/setpcap binary with the revised
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
793
794
795
  	 * 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...
796
  	 */
81a6a0129   Richard Guy Briggs   capabilities: use...
797
  	is_setid = __is_setuid(new, old) || __is_setgid(new, old);
58319057b   Andy Lutomirski   capabilities: amb...
798

4c7e715fc   Richard Guy Briggs   capabilities: int...
799
  	if ((is_setid || __cap_gained(permitted, new, old)) &&
9227dd2a8   Eric W. Biederman   exec: Remove LSM_...
800
  	    ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) ||
20523132e   Eric W. Biederman   exec: Test the pt...
801
  	     !ptracer_capable(current, new->user_ns))) {
a6f76f23d   David Howells   CRED: Make execve...
802
  		/* downgrade; they get no more than they had, and maybe less */
70169420f   Eric W. Biederman   exec: Don't reset...
803
  		if (!ns_capable(new->user_ns, CAP_SETUID) ||
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
804
  		    (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
a6f76f23d   David Howells   CRED: Make execve...
805
806
  			new->euid = new->uid;
  			new->egid = new->gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  		}
b3a222e52   Serge E. Hallyn   remove CONFIG_SEC...
808
809
  		new->cap_permitted = cap_intersect(new->cap_permitted,
  						   old->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
  	}
a6f76f23d   David Howells   CRED: Make execve...
811
812
  	new->suid = new->fsuid = new->euid;
  	new->sgid = new->fsgid = new->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813

58319057b   Andy Lutomirski   capabilities: amb...
814
  	/* File caps or setid cancels ambient. */
fc7eadf76   Richard Guy Briggs   capabilities: ren...
815
  	if (has_fcap || is_setid)
58319057b   Andy Lutomirski   capabilities: amb...
816
817
818
819
820
821
822
823
824
825
826
827
  		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 ...
828
829
830
  	if (effective)
  		new->cap_effective = new->cap_permitted;
  	else
58319057b   Andy Lutomirski   capabilities: amb...
831
832
833
834
  		new->cap_effective = new->cap_ambient;
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
dbbbe1105   Richard Guy Briggs   capabilities: aud...
835
  	if (nonroot_raised_pE(new, old, root_uid, has_fcap)) {
9fbc2c796   Richard Guy Briggs   capabilities: mov...
836
837
838
  		ret = audit_log_bprm_fcaps(bprm, new, old);
  		if (ret < 0)
  			return ret;
3fc689e96   Eric Paris   Any time fcaps or...
839
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840

d84f4f992   David Howells   CRED: Inaugurate ...
841
  	new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
58319057b   Andy Lutomirski   capabilities: amb...
842
843
844
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
46d98eb4e   Kees Cook   commoncap: Refact...
845
  	/* Check for privilege-elevated exec. */
ee67ae7ef   Kees Cook   commoncap: Move c...
846
  	bprm->cap_elevated = 0;
02ebbaf48   Richard Guy Briggs   capabilities: rem...
847
848
849
850
  	if (is_setid ||
  	    (!__is_real(root_uid, new) &&
  	     (effective ||
  	      __cap_grew(permitted, ambient, new))))
ee67ae7ef   Kees Cook   commoncap: Move c...
851
  		bprm->cap_elevated = 1;
b53767719   Serge E. Hallyn   Implement file po...
852

ee67ae7ef   Kees Cook   commoncap: Move c...
853
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
  }
1d045980e   David Howells   CRED: Prettify co...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  /**
   * 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...
869
870
  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
871
  {
b1d749c5c   Eric W. Biederman   capabilities: All...
872
  	struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
873
874
  	/* Ignore non-security xattrs */
  	if (strncmp(name, XATTR_SECURITY_PREFIX,
c5eaab1d1   Carmeli Tamir   security/commonca...
875
  			XATTR_SECURITY_PREFIX_LEN) != 0)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
876
877
878
879
880
881
882
  		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...
883
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
884

b1d749c5c   Eric W. Biederman   capabilities: All...
885
  	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
888
  		return -EPERM;
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
889
890
891
892
893
894
895
896
897
898
899
  /**
   * 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...
900
  int cap_inode_removexattr(struct dentry *dentry, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
  {
b1d749c5c   Eric W. Biederman   capabilities: All...
902
  	struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
903
904
  	/* Ignore non-security xattrs */
  	if (strncmp(name, XATTR_SECURITY_PREFIX,
c5eaab1d1   Carmeli Tamir   security/commonca...
905
  			XATTR_SECURITY_PREFIX_LEN) != 0)
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
906
907
908
909
910
911
912
913
  		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...
914
915
  			return -EPERM;
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
916
  	}
b1d749c5c   Eric W. Biederman   capabilities: All...
917
  	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
920
  		return -EPERM;
  	return 0;
  }
a6f76f23d   David Howells   CRED: Make execve...
921
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
924
925
926
927
928
929
930
931
932
933
934
   * 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...
935
   *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
   *  never happen.
   *
a6f76f23d   David Howells   CRED: Make execve...
938
   *  -astor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
941
942
943
944
945
946
947
948
949
   *
   * 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 ...
950
  static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
  {
18815a180   Eric W. Biederman   userns: Convert c...
952
953
954
955
956
957
958
  	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...
959
960
961
962
963
964
965
966
967
968
969
970
  	     !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
971
  	}
18815a180   Eric W. Biederman   userns: Convert c...
972
  	if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
973
  		cap_clear(new->cap_effective);
18815a180   Eric W. Biederman   userns: Convert c...
974
  	if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
975
  		new->cap_effective = new->cap_permitted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  }
1d045980e   David Howells   CRED: Prettify co...
977
978
979
980
981
982
983
984
985
  /**
   * 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 ...
986
  int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
989
990
991
  {
  	switch (flags) {
  	case LSM_SETID_RE:
  	case LSM_SETID_ID:
  	case LSM_SETID_RES:
1d045980e   David Howells   CRED: Prettify co...
992
993
  		/* juggle the capabilities to follow [RES]UID changes unless
  		 * otherwise suppressed */
d84f4f992   David Howells   CRED: Inaugurate ...
994
995
  		if (!issecure(SECURE_NO_SETUID_FIXUP))
  			cap_emulate_setxuid(new, old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997

1d045980e   David Howells   CRED: Prettify co...
998
999
1000
1001
  	case LSM_SETID_FS:
  		/* juggle the capabilties to follow FSUID changes, unless
  		 * otherwise suppressed
  		 *
d84f4f992   David Howells   CRED: Inaugurate ...
1002
1003
1004
1005
  		 * 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...
1006
1007
  			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 ...
1008
1009
  				new->cap_effective =
  					cap_drop_fs_set(new->cap_effective);
1d045980e   David Howells   CRED: Prettify co...
1010

18815a180   Eric W. Biederman   userns: Convert c...
1011
  			if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
1012
1013
1014
  				new->cap_effective =
  					cap_raise_fs_set(new->cap_effective,
  							 new->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
  		}
d84f4f992   David Howells   CRED: Inaugurate ...
1016
  		break;
1d045980e   David Howells   CRED: Prettify co...
1017

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
1020
1021
1022
1023
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
b53767719   Serge E. Hallyn   Implement file po...
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
  /*
   * 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...
1034
  static int cap_safe_nice(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
1035
  {
f54fb863c   Serge Hallyn   capabilities: all...
1036
  	int is_subset, ret = 0;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1037
1038
1039
1040
  
  	rcu_read_lock();
  	is_subset = cap_issubset(__task_cred(p)->cap_permitted,
  				 current_cred()->cap_permitted);
f54fb863c   Serge Hallyn   capabilities: all...
1041
1042
  	if (!is_subset && !ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
  		ret = -EPERM;
c69e8d9c0   David Howells   CRED: Use RCU to ...
1043
  	rcu_read_unlock();
f54fb863c   Serge Hallyn   capabilities: all...
1044
  	return ret;
b53767719   Serge E. Hallyn   Implement file po...
1045
  }
1d045980e   David Howells   CRED: Prettify co...
1046
1047
1048
  /**
   * cap_task_setscheduler - Detemine if scheduler policy change is permitted
   * @p: The task to affect
1d045980e   David Howells   CRED: Prettify co...
1049
1050
1051
1052
   *
   * 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 ...
1053
  int cap_task_setscheduler(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
1054
1055
1056
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
1057
1058
1059
1060
1061
1062
1063
1064
1065
  /**
   * 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...
1066
1067
1068
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
1069
1070
1071
1072
1073
1074
1075
1076
1077
  /**
   * 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...
1078
1079
1080
  {
  	return cap_safe_nice(p);
  }
3b7391de6   Serge E. Hallyn   capabilities: int...
1081
  /*
1d045980e   David Howells   CRED: Prettify co...
1082
1083
   * 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...
1084
   */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1085
  static int cap_prctl_drop(unsigned long cap)
3b7391de6   Serge E. Hallyn   capabilities: int...
1086
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
1087
  	struct cred *new;
160da84db   Eric W. Biederman   userns: Allow PR_...
1088
  	if (!ns_capable(current_user_ns(), CAP_SETPCAP))
3b7391de6   Serge E. Hallyn   capabilities: int...
1089
1090
1091
  		return -EPERM;
  	if (!cap_valid(cap))
  		return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
1092

6d6f33284   Tetsuo Handa   commoncap: don't ...
1093
1094
1095
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1096
  	cap_lower(new->cap_bset, cap);
6d6f33284   Tetsuo Handa   commoncap: don't ...
1097
  	return commit_creds(new);
3b7391de6   Serge E. Hallyn   capabilities: int...
1098
  }
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1099

1d045980e   David Howells   CRED: Prettify co...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  /**
   * 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...
1112
  int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
d84f4f992   David Howells   CRED: Inaugurate ...
1113
  		   unsigned long arg4, unsigned long arg5)
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1114
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
1115
  	const struct cred *old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
1116
  	struct cred *new;
d84f4f992   David Howells   CRED: Inaugurate ...
1117

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1118
1119
1120
  	switch (option) {
  	case PR_CAPBSET_READ:
  		if (!cap_valid(arg2))
6d6f33284   Tetsuo Handa   commoncap: don't ...
1121
1122
  			return -EINVAL;
  		return !!cap_raised(old->cap_bset, arg2);
d84f4f992   David Howells   CRED: Inaugurate ...
1123

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1124
  	case PR_CAPBSET_DROP:
6d6f33284   Tetsuo Handa   commoncap: don't ...
1125
  		return cap_prctl_drop(arg2);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  
  	/*
  	 * 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 ...
1147
1148
1149
  		if ((((old->securebits & SECURE_ALL_LOCKS) >> 1)
  		     & (old->securebits ^ arg2))			/*[1]*/
  		    || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))	/*[2]*/
d84f4f992   David Howells   CRED: Inaugurate ...
1150
  		    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))	/*[3]*/
6a9de4911   Eric Paris   capabilities: rem...
1151
  		    || (cap_capable(current_cred(),
c1a85a00e   Micah Morton   LSM: generalize f...
1152
1153
1154
  				    current_cred()->user_ns,
  				    CAP_SETPCAP,
  				    CAP_OPT_NONE) != 0)			/*[4]*/
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1155
1156
1157
1158
1159
1160
1161
  			/*
  			 * [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 ...
1162
1163
  		    )
  			/* cannot change a locked bit */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1164
1165
1166
1167
1168
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1169
  		new->securebits = arg2;
6d6f33284   Tetsuo Handa   commoncap: don't ...
1170
  		return commit_creds(new);
d84f4f992   David Howells   CRED: Inaugurate ...
1171

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

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

3898b1b4e   Andrew G. Morgan   capabilities: imp...
1178
1179
  	case PR_SET_KEEPCAPS:
  		if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1180
  			return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
1181
  		if (issecure(SECURE_KEEP_CAPS_LOCKED))
6d6f33284   Tetsuo Handa   commoncap: don't ...
1182
1183
1184
1185
1186
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
1187
1188
  		if (arg2)
  			new->securebits |= issecure_mask(SECURE_KEEP_CAPS);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1189
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
1190
  			new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
6d6f33284   Tetsuo Handa   commoncap: don't ...
1191
  		return commit_creds(new);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1192

58319057b   Andy Lutomirski   capabilities: amb...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
  	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...
1217
1218
  					 arg3) ||
  			     issecure(SECURE_NO_CAP_AMBIENT_RAISE)))
58319057b   Andy Lutomirski   capabilities: amb...
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
  				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...
1230
1231
  	default:
  		/* No functionality available - continue with default */
6d6f33284   Tetsuo Handa   commoncap: don't ...
1232
  		return -ENOSYS;
3898b1b4e   Andrew G. Morgan   capabilities: imp...
1233
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
  }
1d045980e   David Howells   CRED: Prettify co...
1235
  /**
1d045980e   David Howells   CRED: Prettify co...
1236
1237
1238
1239
1240
   * 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...
1241
   * task is permitted, returning 1 if permission is granted, 0 if not.
1d045980e   David Howells   CRED: Prettify co...
1242
   */
34b4e4aa3   Alan Cox   fix NULL pointer ...
1243
  int cap_vm_enough_memory(struct mm_struct *mm, long pages)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
  {
  	int cap_sys_admin = 0;
c1a85a00e   Micah Morton   LSM: generalize f...
1246
1247
  	if (cap_capable(current_cred(), &init_user_ns,
  				CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1248
  		cap_sys_admin = 1;
c1a85a00e   Micah Morton   LSM: generalize f...
1249

b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1250
  	return cap_sys_admin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251
  }
7c73875e7   Eric Paris   Capabilities: mov...
1252
1253
  
  /*
d007794a1   Al Viro   split cap_mmap_ad...
1254
   * cap_mmap_addr - check if able to map given addr
7c73875e7   Eric Paris   Capabilities: mov...
1255
   * @addr: address attempting to be mapped
7c73875e7   Eric Paris   Capabilities: mov...
1256
   *
6f262d8e1   wzt.wzt@gmail.com   Security: Fix the...
1257
   * If the process is attempting to map memory below dac_mmap_min_addr they need
7c73875e7   Eric Paris   Capabilities: mov...
1258
1259
1260
1261
   * 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...
1262
  int cap_mmap_addr(unsigned long addr)
7c73875e7   Eric Paris   Capabilities: mov...
1263
1264
  {
  	int ret = 0;
a2551df7e   Eric Paris   Security/SELinux:...
1265
  	if (addr < dac_mmap_min_addr) {
6a9de4911   Eric Paris   capabilities: rem...
1266
  		ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
c1a85a00e   Micah Morton   LSM: generalize f...
1267
  				  CAP_OPT_NONE);
7c73875e7   Eric Paris   Capabilities: mov...
1268
1269
1270
1271
1272
1273
  		/* 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...
1274

e5467859f   Al Viro   split ->file_mmap...
1275
1276
  int cap_mmap_file(struct file *file, unsigned long reqprot,
  		  unsigned long prot, unsigned long flags)
d007794a1   Al Viro   split cap_mmap_ad...
1277
  {
e5467859f   Al Viro   split ->file_mmap...
1278
  	return 0;
d007794a1   Al Viro   split cap_mmap_ad...
1279
  }
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1280
1281
  
  #ifdef CONFIG_SECURITY
d1c5947ec   YueHaibing   security: Make ca...
1282
  static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1283
1284
1285
1286
1287
1288
1289
  	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...
1290
1291
  	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...
1292
  	LSM_HOOK_INIT(inode_getsecurity, cap_inode_getsecurity),
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1293
1294
1295
1296
1297
1298
1299
1300
1301
  	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),
  };
d117a154e   Kees Cook   capability: Initi...
1302
  static int __init capability_init(void)
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1303
  {
d69dece5f   Casey Schaufler   LSM: Add /sys/ker...
1304
1305
  	security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
  				"capability");
d117a154e   Kees Cook   capability: Initi...
1306
  	return 0;
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1307
  }
d117a154e   Kees Cook   capability: Initi...
1308
1309
1310
1311
1312
  DEFINE_LSM(capability) = {
  	.name = "capability",
  	.order = LSM_ORDER_FIRST,
  	.init = capability_init,
  };
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1313
  #endif /* CONFIG_SECURITY */