diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 37 |
1 files changed, 22 insertions, 15 deletions
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
| 17 | #include <linux/backing-dev.h> | 17 | #include <linux/backing-dev.h> |
| 18 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
| 19 | #include <linux/securebits.h> | ||
| 19 | #include <linux/security.h> | 20 | #include <linux/security.h> |
| 20 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
| 21 | #include <linux/vfs.h> | 22 | #include <linux/vfs.h> |
| @@ -425,7 +426,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 425 | { | 426 | { |
| 426 | struct nameidata nd; | 427 | struct nameidata nd; |
| 427 | int old_fsuid, old_fsgid; | 428 | int old_fsuid, old_fsgid; |
| 428 | kernel_cap_t old_cap; | 429 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ |
| 429 | int res; | 430 | int res; |
| 430 | 431 | ||
| 431 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ | 432 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ |
| @@ -433,23 +434,27 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 433 | 434 | ||
| 434 | old_fsuid = current->fsuid; | 435 | old_fsuid = current->fsuid; |
| 435 | old_fsgid = current->fsgid; | 436 | old_fsgid = current->fsgid; |
| 436 | old_cap = current->cap_effective; | ||
| 437 | 437 | ||
| 438 | current->fsuid = current->uid; | 438 | current->fsuid = current->uid; |
| 439 | current->fsgid = current->gid; | 439 | current->fsgid = current->gid; |
| 440 | 440 | ||
| 441 | /* | 441 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
| 442 | * Clear the capabilities if we switch to a non-root user | 442 | /* |
| 443 | * | 443 | * Clear the capabilities if we switch to a non-root user |
| 444 | * FIXME: There is a race here against sys_capset. The | 444 | */ |
| 445 | * capabilities can change yet we will restore the old | 445 | #ifndef CONFIG_SECURITY_FILE_CAPABILITIES |
| 446 | * value below. We should hold task_capabilities_lock, | 446 | /* |
| 447 | * but we cannot because user_path_walk can sleep. | 447 | * FIXME: There is a race here against sys_capset. The |
| 448 | */ | 448 | * capabilities can change yet we will restore the old |
| 449 | if (current->uid) | 449 | * value below. We should hold task_capabilities_lock, |
| 450 | cap_clear(current->cap_effective); | 450 | * but we cannot because user_path_walk can sleep. |
| 451 | else | 451 | */ |
| 452 | current->cap_effective = current->cap_permitted; | 452 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ |
| 453 | if (current->uid) | ||
| 454 | old_cap = cap_set_effective(__cap_empty_set); | ||
| 455 | else | ||
| 456 | old_cap = cap_set_effective(current->cap_permitted); | ||
| 457 | } | ||
| 453 | 458 | ||
| 454 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); | 459 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); |
| 455 | if (res) | 460 | if (res) |
| @@ -478,7 +483,9 @@ out_path_release: | |||
| 478 | out: | 483 | out: |
| 479 | current->fsuid = old_fsuid; | 484 | current->fsuid = old_fsuid; |
| 480 | current->fsgid = old_fsgid; | 485 | current->fsgid = old_fsgid; |
| 481 | current->cap_effective = old_cap; | 486 | |
| 487 | if (!issecure(SECURE_NO_SETUID_FIXUP)) | ||
| 488 | cap_set_effective(old_cap); | ||
| 482 | 489 | ||
| 483 | return res; | 490 | return res; |
| 484 | } | 491 | } |
