Blame view

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	/* Derived from kernel/capability.c:sys_capget. */
c69e8d9c0   David Howells   CRED: Use RCU to ...
201
202
  	rcu_read_lock();
  	cred = __task_cred(target);
b6dff3ec5   David Howells   CRED: Separate ta...
203
204
205
  	*effective   = cred->cap_effective;
  	*inheritable = cred->cap_inheritable;
  	*permitted   = cred->cap_permitted;
c69e8d9c0   David Howells   CRED: Use RCU to ...
206
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
209
210
211
212
  /*
   * 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...
213
214
  static inline int cap_inh_is_capped(void)
  {
72c2d5823   Andrew Morgan   V3 file capabilit...
215

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

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

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

d84f4f992   David Howells   CRED: Inaugurate ...
264
265
266
  	new->cap_effective   = *effective;
  	new->cap_inheritable = *inheritable;
  	new->cap_permitted   = *permitted;
58319057b   Andy Lutomirski   capabilities: amb...
267
268
269
270
271
272
273
274
275
276
  
  	/*
  	 * 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
277
278
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
279
280
281
  /*
   * Clear proposed capability sets for execve().
   */
b53767719   Serge E. Hallyn   Implement file po...
282
283
  static inline void bprm_clear_caps(struct linux_binprm *bprm)
  {
a6f76f23d   David Howells   CRED: Make execve...
284
  	cap_clear(bprm->cred->cap_permitted);
b53767719   Serge E. Hallyn   Implement file po...
285
286
  	bprm->cap_effective = false;
  }
1d045980e   David Howells   CRED: Prettify co...
287
288
289
290
291
292
293
294
295
296
297
  /**
   * 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
   * inode_killpriv() be invoked or the change rejected?
   *
   * Returns 0 if granted; +ve if granted, but inode_killpriv() is required; and
   * -ve to deny the change.
   */
b53767719   Serge E. Hallyn   Implement file po...
298
299
  int cap_inode_need_killpriv(struct dentry *dentry)
  {
c6f493d63   David Howells   VFS: security/: d...
300
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
301
  	int error;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
302
303
  	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
  	return error > 0;
b53767719   Serge E. Hallyn   Implement file po...
304
  }
1d045980e   David Howells   CRED: Prettify co...
305
306
307
308
309
310
311
312
  /**
   * 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...
313
314
  int cap_inode_killpriv(struct dentry *dentry)
  {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
315
  	int error;
b53767719   Serge E. Hallyn   Implement file po...
316

5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
317
318
319
320
  	error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
  	if (error == -EOPNOTSUPP)
  		error = 0;
  	return error;
b53767719   Serge E. Hallyn   Implement file po...
321
  }
1d045980e   David Howells   CRED: Prettify co...
322
323
324
325
  /*
   * Calculate the new process capability sets from the capability sets attached
   * to a file.
   */
c0b004413   Eric Paris   This patch add a ...
326
  static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
a6f76f23d   David Howells   CRED: Make execve...
327
  					  struct linux_binprm *bprm,
4d49f6710   Zhi Li   capabilities: do ...
328
329
  					  bool *effective,
  					  bool *has_cap)
b53767719   Serge E. Hallyn   Implement file po...
330
  {
a6f76f23d   David Howells   CRED: Make execve...
331
  	struct cred *new = bprm->cred;
c0b004413   Eric Paris   This patch add a ...
332
333
334
335
  	unsigned i;
  	int ret = 0;
  
  	if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
a6f76f23d   David Howells   CRED: Make execve...
336
  		*effective = true;
c0b004413   Eric Paris   This patch add a ...
337

4d49f6710   Zhi Li   capabilities: do ...
338
339
  	if (caps->magic_etc & VFS_CAP_REVISION_MASK)
  		*has_cap = true;
c0b004413   Eric Paris   This patch add a ...
340
341
342
343
344
345
  	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...
346
  		 * The addition of pA' is handled later.
c0b004413   Eric Paris   This patch add a ...
347
  		 */
a6f76f23d   David Howells   CRED: Make execve...
348
349
350
  		new->cap_permitted.cap[i] =
  			(new->cap_bset.cap[i] & permitted) |
  			(new->cap_inheritable.cap[i] & inheritable);
c0b004413   Eric Paris   This patch add a ...
351

a6f76f23d   David Howells   CRED: Make execve...
352
353
  		if (permitted & ~new->cap_permitted.cap[i])
  			/* insufficient to execute correctly */
c0b004413   Eric Paris   This patch add a ...
354
  			ret = -EPERM;
c0b004413   Eric Paris   This patch add a ...
355
356
357
358
359
360
361
  	}
  
  	/*
  	 * 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...
362
  	return *effective ? ret : 0;
c0b004413   Eric Paris   This patch add a ...
363
  }
1d045980e   David Howells   CRED: Prettify co...
364
365
366
  /*
   * Extract the on-exec-apply capability sets for an executable file.
   */
c0b004413   Eric Paris   This patch add a ...
367
368
  int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
  {
c6f493d63   David Howells   VFS: security/: d...
369
  	struct inode *inode = d_backing_inode(dentry);
b53767719   Serge E. Hallyn   Implement file po...
370
  	__u32 magic_etc;
e338d263a   Andrew Morgan   Add 64-bit capabi...
371
  	unsigned tocopy, i;
c0b004413   Eric Paris   This patch add a ...
372
373
374
375
  	int size;
  	struct vfs_cap_data caps;
  
  	memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
376
  	if (!inode)
c0b004413   Eric Paris   This patch add a ...
377
  		return -ENODATA;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
378
379
  	size = __vfs_getxattr((struct dentry *)dentry, inode,
  			      XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
a6f76f23d   David Howells   CRED: Make execve...
380
  	if (size == -ENODATA || size == -EOPNOTSUPP)
c0b004413   Eric Paris   This patch add a ...
381
382
  		/* no data, that's ok */
  		return -ENODATA;
c0b004413   Eric Paris   This patch add a ...
383
384
  	if (size < 0)
  		return size;
b53767719   Serge E. Hallyn   Implement file po...
385

e338d263a   Andrew Morgan   Add 64-bit capabi...
386
  	if (size < sizeof(magic_etc))
b53767719   Serge E. Hallyn   Implement file po...
387
  		return -EINVAL;
c0b004413   Eric Paris   This patch add a ...
388
  	cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc);
b53767719   Serge E. Hallyn   Implement file po...
389

a6f76f23d   David Howells   CRED: Make execve...
390
  	switch (magic_etc & VFS_CAP_REVISION_MASK) {
e338d263a   Andrew Morgan   Add 64-bit capabi...
391
392
393
394
395
396
397
398
399
400
  	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;
b53767719   Serge E. Hallyn   Implement file po...
401
402
403
  	default:
  		return -EINVAL;
  	}
e338d263a   Andrew Morgan   Add 64-bit capabi...
404

5459c164f   Andrew G. Morgan   security: protect...
405
  	CAP_FOR_EACH_U32(i) {
c0b004413   Eric Paris   This patch add a ...
406
407
408
409
  		if (i >= tocopy)
  			break;
  		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...
410
  	}
a6f76f23d   David Howells   CRED: Make execve...
411

7d8b6c637   Eric Paris   CAPABILITIES: rem...
412
413
  	cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
  	cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
c0b004413   Eric Paris   This patch add a ...
414
  	return 0;
b53767719   Serge E. Hallyn   Implement file po...
415
  }
1d045980e   David Howells   CRED: Prettify co...
416
417
418
419
420
  /*
   * Attempt to get the on-exec apply capability sets for an executable file from
   * its xattrs and, if present, apply them to the proposed credentials being
   * constructed by execve().
   */
4d49f6710   Zhi Li   capabilities: do ...
421
  static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap)
b53767719   Serge E. Hallyn   Implement file po...
422
  {
b53767719   Serge E. Hallyn   Implement file po...
423
  	int rc = 0;
c0b004413   Eric Paris   This patch add a ...
424
  	struct cpu_vfs_cap_data vcaps;
b53767719   Serge E. Hallyn   Implement file po...
425

3318a386e   Serge Hallyn   file caps: always...
426
  	bprm_clear_caps(bprm);
1f29fae29   Serge E. Hallyn   file capabilities...
427
428
  	if (!file_caps_enabled)
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
429
  	if (!mnt_may_suid(bprm->file->f_path.mnt))
b53767719   Serge E. Hallyn   Implement file po...
430
  		return 0;
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
431
432
433
434
435
436
  
  	/*
  	 * 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...
437
438
  	if (!current_in_userns(bprm->file->f_path.mnt->mnt_sb->s_user_ns))
  		return 0;
b53767719   Serge E. Hallyn   Implement file po...
439

f4a4a8b12   Al Viro   file->f_path.dent...
440
  	rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
c0b004413   Eric Paris   This patch add a ...
441
442
443
444
445
446
447
  	if (rc < 0) {
  		if (rc == -EINVAL)
  			printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s
  ",
  				__func__, rc, bprm->filename);
  		else if (rc == -ENODATA)
  			rc = 0;
b53767719   Serge E. Hallyn   Implement file po...
448
449
  		goto out;
  	}
b53767719   Serge E. Hallyn   Implement file po...
450

4d49f6710   Zhi Li   capabilities: do ...
451
  	rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective, has_cap);
a6f76f23d   David Howells   CRED: Make execve...
452
453
454
455
  	if (rc == -EINVAL)
  		printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s
  ",
  		       __func__, rc, bprm->filename);
b53767719   Serge E. Hallyn   Implement file po...
456
457
  
  out:
b53767719   Serge E. Hallyn   Implement file po...
458
459
460
461
462
  	if (rc)
  		bprm_clear_caps(bprm);
  
  	return rc;
  }
1d045980e   David Howells   CRED: Prettify co...
463
464
465
466
467
468
469
  /**
   * 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...
470
471
   */
  int cap_bprm_set_creds(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
  {
a6f76f23d   David Howells   CRED: Make execve...
473
474
  	const struct cred *old = current_cred();
  	struct cred *new = bprm->cred;
58319057b   Andy Lutomirski   capabilities: amb...
475
  	bool effective, has_cap = false, is_setid;
b53767719   Serge E. Hallyn   Implement file po...
476
  	int ret;
18815a180   Eric W. Biederman   userns: Convert c...
477
  	kuid_t root_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478

58319057b   Andy Lutomirski   capabilities: amb...
479
480
  	if (WARN_ON(!cap_ambient_invariant_ok(old)))
  		return -EPERM;
a6f76f23d   David Howells   CRED: Make execve...
481
  	effective = false;
4d49f6710   Zhi Li   capabilities: do ...
482
  	ret = get_file_caps(bprm, &effective, &has_cap);
a6f76f23d   David Howells   CRED: Make execve...
483
484
  	if (ret < 0)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485

18815a180   Eric W. Biederman   userns: Convert c...
486
  	root_uid = make_kuid(new->user_ns, 0);
5459c164f   Andrew G. Morgan   security: protect...
487
488
  	if (!issecure(SECURE_NOROOT)) {
  		/*
b5f22a59c   Serge E. Hallyn   don't raise all p...
489
490
491
492
  		 * If the legacy file capability is set, then don't set privs
  		 * for a setuid root binary run by a non-root user.  Do set it
  		 * for a root user just to cause least surprise to an admin.
  		 */
18815a180   Eric W. Biederman   userns: Convert c...
493
  		if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) {
b5f22a59c   Serge E. Hallyn   don't raise all p...
494
495
496
497
  			warn_setuid_and_fcaps_mixed(bprm->filename);
  			goto skip;
  		}
  		/*
5459c164f   Andrew G. Morgan   security: protect...
498
499
500
501
  		 * To support inheritance of root-permissions and suid-root
  		 * executables under compatibility mode, we override the
  		 * capability sets for the file.
  		 *
a6f76f23d   David Howells   CRED: Make execve...
502
  		 * If only the real uid is 0, we do not set the effective bit.
5459c164f   Andrew G. Morgan   security: protect...
503
  		 */
18815a180   Eric W. Biederman   userns: Convert c...
504
  		if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) {
5459c164f   Andrew G. Morgan   security: protect...
505
  			/* pP' = (cap_bset & ~0) | (pI & ~0) */
a6f76f23d   David Howells   CRED: Make execve...
506
507
  			new->cap_permitted = cap_combine(old->cap_bset,
  							 old->cap_inheritable);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  		}
18815a180   Eric W. Biederman   userns: Convert c...
509
  		if (uid_eq(new->euid, root_uid))
a6f76f23d   David Howells   CRED: Make execve...
510
  			effective = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	}
b5f22a59c   Serge E. Hallyn   don't raise all p...
512
  skip:
b53767719   Serge E. Hallyn   Implement file po...
513

d52fc5dde   Eric Paris   fcaps: clear the ...
514
515
516
  	/* if we have fs caps, clear dangerous personality flags */
  	if (!cap_issubset(new->cap_permitted, old->cap_permitted))
  		bprm->per_clear |= PER_CLEAR_ON_SETID;
a6f76f23d   David Howells   CRED: Make execve...
517
  	/* Don't let someone trace a set[ug]id/setpcap binary with the revised
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
518
519
520
  	 * 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...
521
  	 */
58319057b   Andy Lutomirski   capabilities: amb...
522
523
524
  	is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
  
  	if ((is_setid ||
a6f76f23d   David Howells   CRED: Make execve...
525
526
527
  	     !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
  	    bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
  		/* downgrade; they get no more than they had, and maybe less */
259e5e6c7   Andy Lutomirski   Add PR_{GET,SET}_...
528
529
  		if (!capable(CAP_SETUID) ||
  		    (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
a6f76f23d   David Howells   CRED: Make execve...
530
531
  			new->euid = new->uid;
  			new->egid = new->gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  		}
b3a222e52   Serge E. Hallyn   remove CONFIG_SEC...
533
534
  		new->cap_permitted = cap_intersect(new->cap_permitted,
  						   old->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  	}
a6f76f23d   David Howells   CRED: Make execve...
536
537
  	new->suid = new->fsuid = new->euid;
  	new->sgid = new->fsgid = new->egid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538

58319057b   Andy Lutomirski   capabilities: amb...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  	/* File caps or setid cancels ambient. */
  	if (has_cap || is_setid)
  		cap_clear(new->cap_ambient);
  
  	/*
  	 * Now that we've computed pA', update pP' to give:
  	 *   pP' = (X & fP) | (pI & fI) | pA'
  	 */
  	new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient);
  
  	/*
  	 * Set pE' = (fE ? pP' : pA').  Because pA' is zero if fE is set,
  	 * this is the same as pE' = (fE ? pP' : 0) | pA'.
  	 */
4bf2ea77d   Eric Paris   capabilities: do ...
553
554
555
  	if (effective)
  		new->cap_effective = new->cap_permitted;
  	else
58319057b   Andy Lutomirski   capabilities: amb...
556
557
558
559
  		new->cap_effective = new->cap_ambient;
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
a6f76f23d   David Howells   CRED: Make execve...
560
  	bprm->cap_effective = effective;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561

3fc689e96   Eric Paris   Any time fcaps or...
562
563
564
565
566
567
568
569
570
571
572
573
  	/*
  	 * Audit candidate if current->cap_effective is set
  	 *
  	 * We do not bother to audit if 3 things are true:
  	 *   1) cap_effective has all caps
  	 *   2) we are root
  	 *   3) root is supposed to have all caps (SECURE_NOROOT)
  	 * Since this is just a normal root execing a process.
  	 *
  	 * Number 1 above might fail if you don't have a full bset, but I think
  	 * that is interesting information to audit.
  	 */
58319057b   Andy Lutomirski   capabilities: amb...
574
  	if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
d84f4f992   David Howells   CRED: Inaugurate ...
575
  		if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
18815a180   Eric W. Biederman   userns: Convert c...
576
  		    !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
a6f76f23d   David Howells   CRED: Make execve...
577
578
579
580
581
  		    issecure(SECURE_NOROOT)) {
  			ret = audit_log_bprm_fcaps(bprm, new, old);
  			if (ret < 0)
  				return ret;
  		}
3fc689e96   Eric Paris   Any time fcaps or...
582
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583

d84f4f992   David Howells   CRED: Inaugurate ...
584
  	new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
58319057b   Andy Lutomirski   capabilities: amb...
585
586
587
  
  	if (WARN_ON(!cap_ambient_invariant_ok(new)))
  		return -EPERM;
a6f76f23d   David Howells   CRED: Make execve...
588
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  }
1d045980e   David Howells   CRED: Prettify co...
590
591
592
593
594
595
596
597
598
  /**
   * cap_bprm_secureexec - Determine whether a secure execution is required
   * @bprm: The execution parameters
   *
   * Determine whether a secure execution is required, return 1 if it is, and 0
   * if it is not.
   *
   * The credentials have been committed by this point, and so are no longer
   * available through @bprm->cred.
a6f76f23d   David Howells   CRED: Make execve...
599
600
   */
  int cap_bprm_secureexec(struct linux_binprm *bprm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
602
  	const struct cred *cred = current_cred();
18815a180   Eric W. Biederman   userns: Convert c...
603
  	kuid_t root_uid = make_kuid(cred->user_ns, 0);
b6dff3ec5   David Howells   CRED: Separate ta...
604

18815a180   Eric W. Biederman   userns: Convert c...
605
  	if (!uid_eq(cred->uid, root_uid)) {
b53767719   Serge E. Hallyn   Implement file po...
606
607
  		if (bprm->cap_effective)
  			return 1;
58319057b   Andy Lutomirski   capabilities: amb...
608
  		if (!cap_issubset(cred->cap_permitted, cred->cap_ambient))
b53767719   Serge E. Hallyn   Implement file po...
609
610
  			return 1;
  	}
18815a180   Eric W. Biederman   userns: Convert c...
611
612
  	return (!uid_eq(cred->euid, cred->uid) ||
  		!gid_eq(cred->egid, cred->gid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  }
1d045980e   David Howells   CRED: Prettify co...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  /**
   * 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...
628
629
  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
630
  {
b53767719   Serge E. Hallyn   Implement file po...
631
632
633
634
  	if (!strcmp(name, XATTR_NAME_CAPS)) {
  		if (!capable(CAP_SETFCAP))
  			return -EPERM;
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
635
636
637
  	}
  
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
c5b60b5e6   Justin P. Mattock   security: whitesp...
638
  		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
  	    !capable(CAP_SYS_ADMIN))
  		return -EPERM;
  	return 0;
  }
1d045980e   David Howells   CRED: Prettify co...
643
644
645
646
647
648
649
650
651
652
653
  /**
   * 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...
654
  int cap_inode_removexattr(struct dentry *dentry, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  {
b53767719   Serge E. Hallyn   Implement file po...
656
657
658
659
  	if (!strcmp(name, XATTR_NAME_CAPS)) {
  		if (!capable(CAP_SETFCAP))
  			return -EPERM;
  		return 0;
1d045980e   David Howells   CRED: Prettify co...
660
661
662
  	}
  
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
c5b60b5e6   Justin P. Mattock   security: whitesp...
663
  		     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
666
667
  	    !capable(CAP_SYS_ADMIN))
  		return -EPERM;
  	return 0;
  }
a6f76f23d   David Howells   CRED: Make execve...
668
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
673
674
675
676
677
678
679
680
681
   * 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...
682
   *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
   *  never happen.
   *
a6f76f23d   David Howells   CRED: Make execve...
685
   *  -astor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
690
691
692
693
694
695
696
   *
   * 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 ...
697
  static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  {
18815a180   Eric W. Biederman   userns: Convert c...
699
700
701
702
703
704
705
  	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...
706
707
708
709
710
711
712
713
714
715
716
717
  	     !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
718
  	}
18815a180   Eric W. Biederman   userns: Convert c...
719
  	if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
720
  		cap_clear(new->cap_effective);
18815a180   Eric W. Biederman   userns: Convert c...
721
  	if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
722
  		new->cap_effective = new->cap_permitted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
  }
1d045980e   David Howells   CRED: Prettify co...
724
725
726
727
728
729
730
731
732
  /**
   * 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 ...
733
  int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
  {
  	switch (flags) {
  	case LSM_SETID_RE:
  	case LSM_SETID_ID:
  	case LSM_SETID_RES:
1d045980e   David Howells   CRED: Prettify co...
739
740
  		/* juggle the capabilities to follow [RES]UID changes unless
  		 * otherwise suppressed */
d84f4f992   David Howells   CRED: Inaugurate ...
741
742
  		if (!issecure(SECURE_NO_SETUID_FIXUP))
  			cap_emulate_setxuid(new, old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744

1d045980e   David Howells   CRED: Prettify co...
745
746
747
748
  	case LSM_SETID_FS:
  		/* juggle the capabilties to follow FSUID changes, unless
  		 * otherwise suppressed
  		 *
d84f4f992   David Howells   CRED: Inaugurate ...
749
750
751
752
  		 * 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...
753
754
  			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 ...
755
756
  				new->cap_effective =
  					cap_drop_fs_set(new->cap_effective);
1d045980e   David Howells   CRED: Prettify co...
757

18815a180   Eric W. Biederman   userns: Convert c...
758
  			if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid))
d84f4f992   David Howells   CRED: Inaugurate ...
759
760
761
  				new->cap_effective =
  					cap_raise_fs_set(new->cap_effective,
  							 new->cap_permitted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  		}
d84f4f992   David Howells   CRED: Inaugurate ...
763
  		break;
1d045980e   David Howells   CRED: Prettify co...
764

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
769
770
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
b53767719   Serge E. Hallyn   Implement file po...
771
772
773
774
775
776
777
778
779
780
  /*
   * 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...
781
  static int cap_safe_nice(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
782
  {
f54fb863c   Serge Hallyn   capabilities: all...
783
  	int is_subset, ret = 0;
c69e8d9c0   David Howells   CRED: Use RCU to ...
784
785
786
787
  
  	rcu_read_lock();
  	is_subset = cap_issubset(__task_cred(p)->cap_permitted,
  				 current_cred()->cap_permitted);
f54fb863c   Serge Hallyn   capabilities: all...
788
789
  	if (!is_subset && !ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
  		ret = -EPERM;
c69e8d9c0   David Howells   CRED: Use RCU to ...
790
  	rcu_read_unlock();
f54fb863c   Serge Hallyn   capabilities: all...
791
  	return ret;
b53767719   Serge E. Hallyn   Implement file po...
792
  }
1d045980e   David Howells   CRED: Prettify co...
793
794
795
  /**
   * cap_task_setscheduler - Detemine if scheduler policy change is permitted
   * @p: The task to affect
1d045980e   David Howells   CRED: Prettify co...
796
797
798
799
   *
   * 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 ...
800
  int cap_task_setscheduler(struct task_struct *p)
b53767719   Serge E. Hallyn   Implement file po...
801
802
803
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
804
805
806
807
808
809
810
811
812
  /**
   * 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...
813
814
815
  {
  	return cap_safe_nice(p);
  }
1d045980e   David Howells   CRED: Prettify co...
816
817
818
819
820
821
822
823
824
  /**
   * 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...
825
826
827
  {
  	return cap_safe_nice(p);
  }
3b7391de6   Serge E. Hallyn   capabilities: int...
828
  /*
1d045980e   David Howells   CRED: Prettify co...
829
830
   * 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...
831
   */
6d6f33284   Tetsuo Handa   commoncap: don't ...
832
  static int cap_prctl_drop(unsigned long cap)
3b7391de6   Serge E. Hallyn   capabilities: int...
833
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
834
  	struct cred *new;
160da84db   Eric W. Biederman   userns: Allow PR_...
835
  	if (!ns_capable(current_user_ns(), CAP_SETPCAP))
3b7391de6   Serge E. Hallyn   capabilities: int...
836
837
838
  		return -EPERM;
  	if (!cap_valid(cap))
  		return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
839

6d6f33284   Tetsuo Handa   commoncap: don't ...
840
841
842
  	new = prepare_creds();
  	if (!new)
  		return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
843
  	cap_lower(new->cap_bset, cap);
6d6f33284   Tetsuo Handa   commoncap: don't ...
844
  	return commit_creds(new);
3b7391de6   Serge E. Hallyn   capabilities: int...
845
  }
3898b1b4e   Andrew G. Morgan   capabilities: imp...
846

1d045980e   David Howells   CRED: Prettify co...
847
848
849
850
851
852
853
854
855
856
857
858
  /**
   * 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...
859
  int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
d84f4f992   David Howells   CRED: Inaugurate ...
860
  		   unsigned long arg4, unsigned long arg5)
3898b1b4e   Andrew G. Morgan   capabilities: imp...
861
  {
6d6f33284   Tetsuo Handa   commoncap: don't ...
862
  	const struct cred *old = current_cred();
d84f4f992   David Howells   CRED: Inaugurate ...
863
  	struct cred *new;
d84f4f992   David Howells   CRED: Inaugurate ...
864

3898b1b4e   Andrew G. Morgan   capabilities: imp...
865
866
867
  	switch (option) {
  	case PR_CAPBSET_READ:
  		if (!cap_valid(arg2))
6d6f33284   Tetsuo Handa   commoncap: don't ...
868
869
  			return -EINVAL;
  		return !!cap_raised(old->cap_bset, arg2);
d84f4f992   David Howells   CRED: Inaugurate ...
870

3898b1b4e   Andrew G. Morgan   capabilities: imp...
871
  	case PR_CAPBSET_DROP:
6d6f33284   Tetsuo Handa   commoncap: don't ...
872
  		return cap_prctl_drop(arg2);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  
  	/*
  	 * 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 ...
894
895
896
  		if ((((old->securebits & SECURE_ALL_LOCKS) >> 1)
  		     & (old->securebits ^ arg2))			/*[1]*/
  		    || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))	/*[2]*/
d84f4f992   David Howells   CRED: Inaugurate ...
897
  		    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))	/*[3]*/
6a9de4911   Eric Paris   capabilities: rem...
898
  		    || (cap_capable(current_cred(),
c4a4d6037   Eric W. Biederman   userns: Use cred-...
899
  				    current_cred()->user_ns, CAP_SETPCAP,
3699c53c4   David Howells   CRED: Fix regress...
900
  				    SECURITY_CAP_AUDIT) != 0)		/*[4]*/
3898b1b4e   Andrew G. Morgan   capabilities: imp...
901
902
903
904
905
906
907
  			/*
  			 * [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 ...
908
909
  		    )
  			/* cannot change a locked bit */
6d6f33284   Tetsuo Handa   commoncap: don't ...
910
911
912
913
914
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
915
  		new->securebits = arg2;
6d6f33284   Tetsuo Handa   commoncap: don't ...
916
  		return commit_creds(new);
d84f4f992   David Howells   CRED: Inaugurate ...
917

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

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

3898b1b4e   Andrew G. Morgan   capabilities: imp...
924
925
  	case PR_SET_KEEPCAPS:
  		if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
6d6f33284   Tetsuo Handa   commoncap: don't ...
926
  			return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
927
  		if (issecure(SECURE_KEEP_CAPS_LOCKED))
6d6f33284   Tetsuo Handa   commoncap: don't ...
928
929
930
931
932
  			return -EPERM;
  
  		new = prepare_creds();
  		if (!new)
  			return -ENOMEM;
d84f4f992   David Howells   CRED: Inaugurate ...
933
934
  		if (arg2)
  			new->securebits |= issecure_mask(SECURE_KEEP_CAPS);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
935
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
936
  			new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
6d6f33284   Tetsuo Handa   commoncap: don't ...
937
  		return commit_creds(new);
3898b1b4e   Andrew G. Morgan   capabilities: imp...
938

58319057b   Andy Lutomirski   capabilities: amb...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
  	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...
963
964
  					 arg3) ||
  			     issecure(SECURE_NO_CAP_AMBIENT_RAISE)))
58319057b   Andy Lutomirski   capabilities: amb...
965
966
967
968
969
970
971
972
973
974
975
  				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...
976
977
  	default:
  		/* No functionality available - continue with default */
6d6f33284   Tetsuo Handa   commoncap: don't ...
978
  		return -ENOSYS;
3898b1b4e   Andrew G. Morgan   capabilities: imp...
979
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
  }
1d045980e   David Howells   CRED: Prettify co...
981
  /**
1d045980e   David Howells   CRED: Prettify co...
982
983
984
985
986
   * 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...
987
   * task is permitted, returning 1 if permission is granted, 0 if not.
1d045980e   David Howells   CRED: Prettify co...
988
   */
34b4e4aa3   Alan Cox   fix NULL pointer ...
989
  int cap_vm_enough_memory(struct mm_struct *mm, long pages)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
  {
  	int cap_sys_admin = 0;
6a9de4911   Eric Paris   capabilities: rem...
992
  	if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
3699c53c4   David Howells   CRED: Fix regress...
993
  			SECURITY_CAP_NOAUDIT) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  		cap_sys_admin = 1;
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
995
  	return cap_sys_admin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
  }
7c73875e7   Eric Paris   Capabilities: mov...
997
998
  
  /*
d007794a1   Al Viro   split cap_mmap_ad...
999
   * cap_mmap_addr - check if able to map given addr
7c73875e7   Eric Paris   Capabilities: mov...
1000
   * @addr: address attempting to be mapped
7c73875e7   Eric Paris   Capabilities: mov...
1001
   *
6f262d8e1   wzt.wzt@gmail.com   Security: Fix the...
1002
   * If the process is attempting to map memory below dac_mmap_min_addr they need
7c73875e7   Eric Paris   Capabilities: mov...
1003
1004
1005
1006
   * 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...
1007
  int cap_mmap_addr(unsigned long addr)
7c73875e7   Eric Paris   Capabilities: mov...
1008
1009
  {
  	int ret = 0;
a2551df7e   Eric Paris   Security/SELinux:...
1010
  	if (addr < dac_mmap_min_addr) {
6a9de4911   Eric Paris   capabilities: rem...
1011
  		ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
7c73875e7   Eric Paris   Capabilities: mov...
1012
1013
1014
1015
1016
1017
1018
  				  SECURITY_CAP_AUDIT);
  		/* set PF_SUPERPRIV if it turns out we allow the low mmap */
  		if (ret == 0)
  			current->flags |= PF_SUPERPRIV;
  	}
  	return ret;
  }
d007794a1   Al Viro   split cap_mmap_ad...
1019

e5467859f   Al Viro   split ->file_mmap...
1020
1021
  int cap_mmap_file(struct file *file, unsigned long reqprot,
  		  unsigned long prot, unsigned long flags)
d007794a1   Al Viro   split cap_mmap_ad...
1022
  {
e5467859f   Al Viro   split ->file_mmap...
1023
  	return 0;
d007794a1   Al Viro   split cap_mmap_ad...
1024
  }
b1d9e6b06   Casey Schaufler   LSM: Switch to li...
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  
  #ifdef CONFIG_SECURITY
  
  struct security_hook_list capability_hooks[] = {
  	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),
  	LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
  	LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
  	LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
  	LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
  	LSM_HOOK_INIT(mmap_file, cap_mmap_file),
  	LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
  	LSM_HOOK_INIT(task_prctl, cap_task_prctl),
  	LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
  	LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
  	LSM_HOOK_INIT(task_setnice, cap_task_setnice),
  	LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
  };
  
  void __init capability_add_hooks(void)
  {
  	security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
  }
  
  #endif /* CONFIG_SECURITY */