Blame view

security/commoncap.c 39.1 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;
3484eba91   Mark Salyzyn   FROMLIST: Add fla...
289
290
  	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0,
  			       XATTR_NOSECURITY);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
291
  	return error > 0;
b53767719   Serge E. Hallyn   Implement file po...
292
  }
1d045980e   David Howells   CRED: Prettify co...
293
294
295
296
297
298
299
300
  /**
   * 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...
301
302
  int cap_inode_killpriv(struct dentry *dentry)
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
303
  	int error;
b53767719   Serge E. Hallyn   Implement file po...
304

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

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

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

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

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

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

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

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

7d8b6c637   Eric Paris   CAPABILITIES: rem...
616
617
  	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...
618
  	cpu_caps->rootid = rootkuid;
c0b004413   Eric Paris   This patch add a ...
619
  	return 0;
b53767719   Serge E. Hallyn   Implement file po...
620
  }
1d045980e   David Howells   CRED: Prettify co...
621
622
623
624
625
  /*
   * 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().
   */
56305aa9b   Eric W. Biederman   exec: Compute fil...
626
627
  static int get_file_caps(struct linux_binprm *bprm, struct file *file,
  			 bool *effective, bool *has_fcap)
b53767719   Serge E. Hallyn   Implement file po...
628
  {
b53767719   Serge E. Hallyn   Implement file po...
629
  	int rc = 0;
c0b004413   Eric Paris   This patch add a ...
630
  	struct cpu_vfs_cap_data vcaps;
b53767719   Serge E. Hallyn   Implement file po...
631

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

1f29fae29   Serge E. Hallyn   file capabilities...
634
635
  	if (!file_caps_enabled)
  		return 0;
56305aa9b   Eric W. Biederman   exec: Compute fil...
636
  	if (!mnt_may_suid(file->f_path.mnt))
b53767719   Serge E. Hallyn   Implement file po...
637
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
638
639
640
641
642
643
  
  	/*
  	 * 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.
  	 */
56305aa9b   Eric W. Biederman   exec: Compute fil...
644
  	if (!current_in_userns(file->f_path.mnt->mnt_sb->s_user_ns))
d07b846f6   Seth Forshee   fs: Limit file ca...
645
  		return 0;
b53767719   Serge E. Hallyn   Implement file po...
646

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

fc7eadf76   Richard Guy Briggs   capabilities: ren...
658
  	rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_fcap);
b53767719   Serge E. Hallyn   Implement file po...
659
660
  
  out:
b53767719   Serge E. Hallyn   Implement file po...
661
  	if (rc)
ee67ae7ef   Kees Cook   commoncap: Move c...
662
  		cap_clear(bprm->cred->cap_permitted);
b53767719   Serge E. Hallyn   Implement file po...
663
664
665
  
  	return rc;
  }
9304b46c9   Richard Guy Briggs   capabilities: use...
666
  static inline bool root_privileged(void) { return !issecure(SECURE_NOROOT); }
81a6a0129   Richard Guy Briggs   capabilities: use...
667
668
669
670
671
672
673
674
  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...
675
676
677
678
679
680
681
682
683
684
685
686
  /*
   * 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...
687
  static void handle_privileged_root(struct linux_binprm *bprm, bool has_fcap,
db1a8922c   Richard Guy Briggs   capabilities: fac...
688
689
690
691
  				   bool *effective, kuid_t root_uid)
  {
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
9304b46c9   Richard Guy Briggs   capabilities: use...
692
  	if (!root_privileged())
db1a8922c   Richard Guy Briggs   capabilities: fac...
693
694
695
696
697
698
  		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...
699
  	if (has_fcap && __is_suid(root_uid, new)) {
db1a8922c   Richard Guy Briggs   capabilities: fac...
700
701
702
703
704
705
706
707
  		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...
708
  	if (__is_eff(root_uid, new) || __is_real(root_uid, new)) {
db1a8922c   Richard Guy Briggs   capabilities: fac...
709
710
711
712
713
714
715
  		/* 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...
716
  	if (__is_eff(root_uid, new))
db1a8922c   Richard Guy Briggs   capabilities: fac...
717
718
  		*effective = true;
  }
4c7e715fc   Richard Guy Briggs   capabilities: int...
719
720
721
722
723
724
  #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...
725
726
727
728
729
730
  
  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...
731
  /*
dbbbe1105   Richard Guy Briggs   capabilities: aud...
732
   * 1) Audit candidate if current->cap_effective is set
9fbc2c796   Richard Guy Briggs   capabilities: mov...
733
734
735
   *
   * We do not bother to audit if 3 things are true:
   *   1) cap_effective has all caps
588fb2c7e   Richard Guy Briggs   capabilities: fix...
736
   *   2) we became root *OR* are were already root
9fbc2c796   Richard Guy Briggs   capabilities: mov...
737
738
739
740
741
   *   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...
742
743
744
745
746
   *
   * 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...
747
   */
dbbbe1105   Richard Guy Briggs   capabilities: aud...
748
749
  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...
750
751
  {
  	bool ret = false;
dbbbe1105   Richard Guy Briggs   capabilities: aud...
752
753
754
755
756
757
758
759
760
761
762
  	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...
763
  		ret = true;
dbbbe1105   Richard Guy Briggs   capabilities: aud...
764

9fbc2c796   Richard Guy Briggs   capabilities: mov...
765
766
  	return ret;
  }
1d045980e   David Howells   CRED: Prettify co...
767
  /**
56305aa9b   Eric W. Biederman   exec: Compute fil...
768
   * cap_bprm_creds_from_file - Set up the proposed credentials for execve().
1d045980e   David Howells   CRED: Prettify co...
769
   * @bprm: The execution parameters, including the proposed creds
56305aa9b   Eric W. Biederman   exec: Compute fil...
770
   * @file: The file to pull the credentials from
1d045980e   David Howells   CRED: Prettify co...
771
772
773
774
   *
   * 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...
775
   */
56305aa9b   Eric W. Biederman   exec: Compute fil...
776
  int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  {
56305aa9b   Eric W. Biederman   exec: Compute fil...
778
  	/* Process setpcap binaries and capabilities for uid 0 */
a6f76f23d   David Howells   CRED: Make execve...
779
780
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
fc7eadf76   Richard Guy Briggs   capabilities: ren...
781
  	bool effective = false, has_fcap = false, is_setid;
b53767719   Serge E. Hallyn   Implement file po...
782
  	int ret;
18815a180   Eric W. Biederman   userns: Convert c...
783
  	kuid_t root_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784

58319057b   Andy Lutomirski   capabilities: amb...
785
786
  	if (WARN_ON(!cap_ambient_invariant_ok(old)))
  		return -EPERM;
56305aa9b   Eric W. Biederman   exec: Compute fil...
787
  	ret = get_file_caps(bprm, file, &effective, &has_fcap);
a6f76f23d   David Howells   CRED: Make execve...
788
789
  	if (ret < 0)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790

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

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

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

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

d84f4f992   David Howells   CRED: Inaugurate ...
846
  	new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
58319057b   Andy Lutomirski   capabilities: amb...
847
848
849
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
46d98eb4e   Kees Cook   commoncap: Refact...
850
  	/* Check for privilege-elevated exec. */
02ebbaf48   Richard Guy Briggs   capabilities: rem...
851
852
853
854
  	if (is_setid ||
  	    (!__is_real(root_uid, new) &&
  	     (effective ||
  	      __cap_grew(permitted, ambient, new))))
56305aa9b   Eric W. Biederman   exec: Compute fil...
855
  		bprm->secureexec = 1;
b53767719   Serge E. Hallyn   Implement file po...
856

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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