aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c152
1 files changed, 76 insertions, 76 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index b5419273f92d..51dfa11e8e56 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -167,7 +167,7 @@ int cap_capset(struct cred *new,
167 167
168static inline void bprm_clear_caps(struct linux_binprm *bprm) 168static inline void bprm_clear_caps(struct linux_binprm *bprm)
169{ 169{
170 cap_clear(bprm->cap_post_exec_permitted); 170 cap_clear(bprm->cred->cap_permitted);
171 bprm->cap_effective = false; 171 bprm->cap_effective = false;
172} 172}
173 173
@@ -198,15 +198,15 @@ int cap_inode_killpriv(struct dentry *dentry)
198} 198}
199 199
200static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, 200static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
201 struct linux_binprm *bprm) 201 struct linux_binprm *bprm,
202 bool *effective)
202{ 203{
204 struct cred *new = bprm->cred;
203 unsigned i; 205 unsigned i;
204 int ret = 0; 206 int ret = 0;
205 207
206 if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) 208 if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
207 bprm->cap_effective = true; 209 *effective = true;
208 else
209 bprm->cap_effective = false;
210 210
211 CAP_FOR_EACH_U32(i) { 211 CAP_FOR_EACH_U32(i) {
212 __u32 permitted = caps->permitted.cap[i]; 212 __u32 permitted = caps->permitted.cap[i];
@@ -215,16 +215,13 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
215 /* 215 /*
216 * pP' = (X & fP) | (pI & fI) 216 * pP' = (X & fP) | (pI & fI)
217 */ 217 */
218 bprm->cap_post_exec_permitted.cap[i] = 218 new->cap_permitted.cap[i] =
219 (current->cred->cap_bset.cap[i] & permitted) | 219 (new->cap_bset.cap[i] & permitted) |
220 (current->cred->cap_inheritable.cap[i] & inheritable); 220 (new->cap_inheritable.cap[i] & inheritable);
221 221
222 if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) { 222 if (permitted & ~new->cap_permitted.cap[i])
223 /* 223 /* insufficient to execute correctly */
224 * insufficient to execute correctly
225 */
226 ret = -EPERM; 224 ret = -EPERM;
227 }
228 } 225 }
229 226
230 /* 227 /*
@@ -232,7 +229,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
232 * do not have enough capabilities, we return an error if they are 229 * do not have enough capabilities, we return an error if they are
233 * missing some "forced" (aka file-permitted) capabilities. 230 * missing some "forced" (aka file-permitted) capabilities.
234 */ 231 */
235 return bprm->cap_effective ? ret : 0; 232 return *effective ? ret : 0;
236} 233}
237 234
238int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) 235int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
@@ -250,10 +247,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
250 247
251 size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, 248 size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps,
252 XATTR_CAPS_SZ); 249 XATTR_CAPS_SZ);
253 if (size == -ENODATA || size == -EOPNOTSUPP) { 250 if (size == -ENODATA || size == -EOPNOTSUPP)
254 /* no data, that's ok */ 251 /* no data, that's ok */
255 return -ENODATA; 252 return -ENODATA;
256 }
257 if (size < 0) 253 if (size < 0)
258 return size; 254 return size;
259 255
@@ -262,7 +258,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
262 258
263 cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); 259 cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc);
264 260
265 switch ((magic_etc & VFS_CAP_REVISION_MASK)) { 261 switch (magic_etc & VFS_CAP_REVISION_MASK) {
266 case VFS_CAP_REVISION_1: 262 case VFS_CAP_REVISION_1:
267 if (size != XATTR_CAPS_SZ_1) 263 if (size != XATTR_CAPS_SZ_1)
268 return -EINVAL; 264 return -EINVAL;
@@ -283,11 +279,12 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
283 cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); 279 cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted);
284 cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); 280 cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable);
285 } 281 }
282
286 return 0; 283 return 0;
287} 284}
288 285
289/* Locate any VFS capabilities: */ 286/* Locate any VFS capabilities: */
290static int get_file_caps(struct linux_binprm *bprm) 287static int get_file_caps(struct linux_binprm *bprm, bool *effective)
291{ 288{
292 struct dentry *dentry; 289 struct dentry *dentry;
293 int rc = 0; 290 int rc = 0;
@@ -313,7 +310,10 @@ static int get_file_caps(struct linux_binprm *bprm)
313 goto out; 310 goto out;
314 } 311 }
315 312
316 rc = bprm_caps_from_vfs_caps(&vcaps, bprm); 313 rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective);
314 if (rc == -EINVAL)
315 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
316 __func__, rc, bprm->filename);
317 317
318out: 318out:
319 dput(dentry); 319 dput(dentry);
@@ -334,18 +334,27 @@ int cap_inode_killpriv(struct dentry *dentry)
334 return 0; 334 return 0;
335} 335}
336 336
337static inline int get_file_caps(struct linux_binprm *bprm) 337static inline int get_file_caps(struct linux_binprm *bprm, bool *effective)
338{ 338{
339 bprm_clear_caps(bprm); 339 bprm_clear_caps(bprm);
340 return 0; 340 return 0;
341} 341}
342#endif 342#endif
343 343
344int cap_bprm_set_security (struct linux_binprm *bprm) 344/*
345 * set up the new credentials for an exec'd task
346 */
347int cap_bprm_set_creds(struct linux_binprm *bprm)
345{ 348{
349 const struct cred *old = current_cred();
350 struct cred *new = bprm->cred;
351 bool effective;
346 int ret; 352 int ret;
347 353
348 ret = get_file_caps(bprm); 354 effective = false;
355 ret = get_file_caps(bprm, &effective);
356 if (ret < 0)
357 return ret;
349 358
350 if (!issecure(SECURE_NOROOT)) { 359 if (!issecure(SECURE_NOROOT)) {
351 /* 360 /*
@@ -353,63 +362,47 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
353 * executables under compatibility mode, we override the 362 * executables under compatibility mode, we override the
354 * capability sets for the file. 363 * capability sets for the file.
355 * 364 *
356 * If only the real uid is 0, we do not set the effective 365 * If only the real uid is 0, we do not set the effective bit.
357 * bit.
358 */ 366 */
359 if (bprm->e_uid == 0 || current_uid() == 0) { 367 if (new->euid == 0 || new->uid == 0) {
360 /* pP' = (cap_bset & ~0) | (pI & ~0) */ 368 /* pP' = (cap_bset & ~0) | (pI & ~0) */
361 bprm->cap_post_exec_permitted = cap_combine( 369 new->cap_permitted = cap_combine(old->cap_bset,
362 current->cred->cap_bset, 370 old->cap_inheritable);
363 current->cred->cap_inheritable);
364 bprm->cap_effective = (bprm->e_uid == 0);
365 ret = 0;
366 } 371 }
372 if (new->euid == 0)
373 effective = true;
367 } 374 }
368 375
369 return ret; 376 /* Don't let someone trace a set[ug]id/setpcap binary with the revised
370} 377 * credentials unless they have the appropriate permit
371 378 */
372int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 379 if ((new->euid != old->uid ||
373{ 380 new->egid != old->gid ||
374 const struct cred *old = current_cred(); 381 !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
375 struct cred *new; 382 bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
376 383 /* downgrade; they get no more than they had, and maybe less */
377 new = prepare_creds(); 384 if (!capable(CAP_SETUID)) {
378 if (!new) 385 new->euid = new->uid;
379 return -ENOMEM; 386 new->egid = new->gid;
380
381 if (bprm->e_uid != old->uid || bprm->e_gid != old->gid ||
382 !cap_issubset(bprm->cap_post_exec_permitted,
383 old->cap_permitted)) {
384 set_dumpable(current->mm, suid_dumpable);
385 current->pdeath_signal = 0;
386
387 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
388 if (!capable(CAP_SETUID)) {
389 bprm->e_uid = old->uid;
390 bprm->e_gid = old->gid;
391 }
392 if (cap_limit_ptraced_target()) {
393 bprm->cap_post_exec_permitted = cap_intersect(
394 bprm->cap_post_exec_permitted,
395 new->cap_permitted);
396 }
397 } 387 }
388 if (cap_limit_ptraced_target())
389 new->cap_permitted = cap_intersect(new->cap_permitted,
390 old->cap_permitted);
398 } 391 }
399 392
400 new->suid = new->euid = new->fsuid = bprm->e_uid; 393 new->suid = new->fsuid = new->euid;
401 new->sgid = new->egid = new->fsgid = bprm->e_gid; 394 new->sgid = new->fsgid = new->egid;
402 395
403 /* For init, we want to retain the capabilities set 396 /* For init, we want to retain the capabilities set in the initial
404 * in the init_task struct. Thus we skip the usual 397 * task. Thus we skip the usual capability rules
405 * capability rules */ 398 */
406 if (!is_global_init(current)) { 399 if (!is_global_init(current)) {
407 new->cap_permitted = bprm->cap_post_exec_permitted; 400 if (effective)
408 if (bprm->cap_effective) 401 new->cap_effective = new->cap_permitted;
409 new->cap_effective = bprm->cap_post_exec_permitted;
410 else 402 else
411 cap_clear(new->cap_effective); 403 cap_clear(new->cap_effective);
412 } 404 }
405 bprm->cap_effective = effective;
413 406
414 /* 407 /*
415 * Audit candidate if current->cap_effective is set 408 * Audit candidate if current->cap_effective is set
@@ -425,23 +418,31 @@ int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
425 */ 418 */
426 if (!cap_isclear(new->cap_effective)) { 419 if (!cap_isclear(new->cap_effective)) {
427 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || 420 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
428 bprm->e_uid != 0 || new->uid != 0 || 421 new->euid != 0 || new->uid != 0 ||
429 issecure(SECURE_NOROOT)) 422 issecure(SECURE_NOROOT)) {
430 audit_log_bprm_fcaps(bprm, new, old); 423 ret = audit_log_bprm_fcaps(bprm, new, old);
424 if (ret < 0)
425 return ret;
426 }
431 } 427 }
432 428
433 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 429 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
434 return commit_creds(new); 430 return 0;
435} 431}
436 432
437int cap_bprm_secureexec (struct linux_binprm *bprm) 433/*
434 * determine whether a secure execution is required
435 * - the creds have been committed at this point, and are no longer available
436 * through bprm
437 */
438int cap_bprm_secureexec(struct linux_binprm *bprm)
438{ 439{
439 const struct cred *cred = current_cred(); 440 const struct cred *cred = current_cred();
440 441
441 if (cred->uid != 0) { 442 if (cred->uid != 0) {
442 if (bprm->cap_effective) 443 if (bprm->cap_effective)
443 return 1; 444 return 1;
444 if (!cap_isclear(bprm->cap_post_exec_permitted)) 445 if (!cap_isclear(cred->cap_permitted))
445 return 1; 446 return 1;
446 } 447 }
447 448
@@ -477,7 +478,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
477} 478}
478 479
479/* moved from kernel/sys.c. */ 480/* moved from kernel/sys.c. */
480/* 481/*
481 * cap_emulate_setxuid() fixes the effective / permitted capabilities of 482 * cap_emulate_setxuid() fixes the effective / permitted capabilities of
482 * a process after a call to setuid, setreuid, or setresuid. 483 * a process after a call to setuid, setreuid, or setresuid.
483 * 484 *
@@ -491,10 +492,10 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
491 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective 492 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
492 * capabilities are set to the permitted capabilities. 493 * capabilities are set to the permitted capabilities.
493 * 494 *
494 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 495 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
495 * never happen. 496 * never happen.
496 * 497 *
497 * -astor 498 * -astor
498 * 499 *
499 * cevans - New behaviour, Oct '99 500 * cevans - New behaviour, Oct '99
500 * A process may, via prctl(), elect to keep its capabilities when it 501 * A process may, via prctl(), elect to keep its capabilities when it
@@ -751,4 +752,3 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
751 cap_sys_admin = 1; 752 cap_sys_admin = 1;
752 return __vm_enough_memory(mm, pages, cap_sys_admin); 753 return __vm_enough_memory(mm, pages, cap_sys_admin);
753} 754}
754