Skip to content

Commit

Permalink
security: filesystem capabilities: fix fragile setuid fixup code
Browse files Browse the repository at this point in the history
This commit includes a bugfix for the fragile setuid fixup code in the
case that filesystem capabilities are supported (in access()).  The effect
of this fix is gated on filesystem capability support because changing
securebits is only supported when filesystem capabilities support is
configured.)

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
AndrewGMorgan authored and torvalds committed Jul 4, 2008
1 parent abbaeff commit 086f731
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
37 changes: 22 additions & 15 deletions fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/namei.h>
#include <linux/backing-dev.h>
#include <linux/capability.h>
#include <linux/securebits.h>
#include <linux/security.h>
#include <linux/mount.h>
#include <linux/vfs.h>
Expand Down Expand Up @@ -425,31 +426,35 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
{
struct nameidata nd;
int old_fsuid, old_fsgid;
kernel_cap_t old_cap;
kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */
int res;

if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;

old_fsuid = current->fsuid;
old_fsgid = current->fsgid;
old_cap = current->cap_effective;

current->fsuid = current->uid;
current->fsgid = current->gid;

/*
* Clear the capabilities if we switch to a non-root user
*
* FIXME: There is a race here against sys_capset. The
* capabilities can change yet we will restore the old
* value below. We should hold task_capabilities_lock,
* but we cannot because user_path_walk can sleep.
*/
if (current->uid)
cap_clear(current->cap_effective);
else
current->cap_effective = current->cap_permitted;
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
/*
* Clear the capabilities if we switch to a non-root user
*/
#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
/*
* FIXME: There is a race here against sys_capset. The
* capabilities can change yet we will restore the old
* value below. We should hold task_capabilities_lock,
* but we cannot because user_path_walk can sleep.
*/
#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
if (current->uid)
old_cap = cap_set_effective(__cap_empty_set);
else
old_cap = cap_set_effective(current->cap_permitted);
}

res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
if (res)
Expand Down Expand Up @@ -478,7 +483,9 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
out:
current->fsuid = old_fsuid;
current->fsgid = old_fsgid;
current->cap_effective = old_cap;

if (!issecure(SECURE_NO_SETUID_FIXUP))
cap_set_effective(old_cap);

return res;
}
Expand Down
2 changes: 2 additions & 0 deletions include/linux/capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@ extern const kernel_cap_t __cap_empty_set;
extern const kernel_cap_t __cap_full_set;
extern const kernel_cap_t __cap_init_eff_set;

kernel_cap_t cap_set_effective(const kernel_cap_t pE_new);

int capable(int cap);
int __capable(struct task_struct *t, int cap);

Expand Down
15 changes: 8 additions & 7 deletions include/linux/securebits.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
inheritance of root-permissions and suid-root executable under
compatibility mode. We raise the effective and inheritable bitmasks
*of the executable file* if the effective uid of the new process is
0. If the real uid is 0, we raise the inheritable bitmask of the
0. If the real uid is 0, we raise the effective (legacy) bit of the
executable file. */
#define SECURE_NOROOT 0
#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */

/* When set, setuid to/from uid 0 does not trigger capability-"fixes"
to be compatible with old programs relying on set*uid to loose
privileges. When unset, setuid doesn't change privileges. */
/* When set, setuid to/from uid 0 does not trigger capability-"fixup".
When unset, to provide compatiblility with old programs relying on
set*uid to gain/lose privilege, transitions to/from uid 0 cause
capabilities to be gained/lost. */
#define SECURE_NO_SETUID_FIXUP 2
#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */

Expand All @@ -26,10 +27,10 @@
#define SECURE_KEEP_CAPS 4
#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */

/* Each securesetting is implemented using two bits. One bit specify
/* Each securesetting is implemented using two bits. One bit specifies
whether the setting is on or off. The other bit specify whether the
setting is fixed or not. A setting which is fixed cannot be changed
from user-level. */
setting is locked or not. A setting which is locked cannot be
changed from user-level. */
#define issecure_mask(X) (1 << (X))
#define issecure(X) (issecure_mask(X) & current->securebits)

Expand Down
21 changes: 21 additions & 0 deletions kernel/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,27 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
* uninteresting and/or not to be changed.
*/

/*
* Atomically modify the effective capabilities returning the original
* value. No permission check is performed here - it is assumed that the
* caller is permitted to set the desired effective capabilities.
*/
kernel_cap_t cap_set_effective(const kernel_cap_t pE_new)
{
kernel_cap_t pE_old;

spin_lock(&task_capability_lock);

pE_old = current->cap_effective;
current->cap_effective = pE_new;

spin_unlock(&task_capability_lock);

return pE_old;
}

EXPORT_SYMBOL(cap_set_effective);

/**
* sys_capget - get the capabilities of a given process.
* @header: pointer to struct that contains capability version and
Expand Down

0 comments on commit 086f731

Please sign in to comment.