diff options
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 31 |
1 files changed, 15 insertions, 16 deletions
@@ -425,30 +425,33 @@ out: | |||
425 | */ | 425 | */ |
426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | 426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) |
427 | { | 427 | { |
428 | struct cred *cred = current->cred; | 428 | const struct cred *old_cred; |
429 | struct cred *override_cred; | ||
429 | struct path path; | 430 | struct path path; |
430 | struct inode *inode; | 431 | struct inode *inode; |
431 | int old_fsuid, old_fsgid; | ||
432 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | ||
433 | int res; | 432 | int res; |
434 | 433 | ||
435 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ | 434 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ |
436 | return -EINVAL; | 435 | return -EINVAL; |
437 | 436 | ||
438 | old_fsuid = cred->fsuid; | 437 | override_cred = prepare_creds(); |
439 | old_fsgid = cred->fsgid; | 438 | if (!override_cred) |
439 | return -ENOMEM; | ||
440 | 440 | ||
441 | cred->fsuid = cred->uid; | 441 | override_cred->fsuid = override_cred->uid; |
442 | cred->fsgid = cred->gid; | 442 | override_cred->fsgid = override_cred->gid; |
443 | 443 | ||
444 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 444 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
445 | /* Clear the capabilities if we switch to a non-root user */ | 445 | /* Clear the capabilities if we switch to a non-root user */ |
446 | if (current->cred->uid) | 446 | if (override_cred->uid) |
447 | old_cap = cap_set_effective(__cap_empty_set); | 447 | cap_clear(override_cred->cap_effective); |
448 | else | 448 | else |
449 | old_cap = cap_set_effective(cred->cap_permitted); | 449 | override_cred->cap_effective = |
450 | override_cred->cap_permitted; | ||
450 | } | 451 | } |
451 | 452 | ||
453 | old_cred = override_creds(override_cred); | ||
454 | |||
452 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); | 455 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
453 | if (res) | 456 | if (res) |
454 | goto out; | 457 | goto out; |
@@ -485,12 +488,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
485 | out_path_release: | 488 | out_path_release: |
486 | path_put(&path); | 489 | path_put(&path); |
487 | out: | 490 | out: |
488 | cred->fsuid = old_fsuid; | 491 | revert_creds(old_cred); |
489 | cred->fsgid = old_fsgid; | 492 | put_cred(override_cred); |
490 | |||
491 | if (!issecure(SECURE_NO_SETUID_FIXUP)) | ||
492 | cap_set_effective(old_cap); | ||
493 | |||
494 | return res; | 493 | return res; |
495 | } | 494 | } |
496 | 495 | ||