diff options
author | Serge E. Hallyn <serue@us.ibm.com> | 2009-04-02 19:47:14 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-04-02 20:49:31 -0400 |
commit | b5f22a59c0356655a501190959db9f7f5dd07e3f (patch) | |
tree | 3c20437a6a3b7b7e980078bfbcd0d53cdeda7528 | |
parent | 3d43321b7015387cfebbe26436d0e9d299162ea1 (diff) |
don't raise all privs on setuid-root file with fE set (v2)
Distributions face a backward compatibility problem with starting to use
file capabilities. For instance, removing setuid root from ping and
doing setcap cap_net_raw=pe means that booting with an older kernel
or one compiled without file capabilities means ping won't work for
non-root users.
In order to replace the setuid root bit on a capability-unaware
program, one has to set the effective, or legacy, file capability,
which makes the capability effective immediately. This patch
uses the legacy bit as a queue to not automatically add full
privilege to a setuid-root program.
So, with this patch, an ordinary setuid-root program will run with
privilege. But if /bin/ping has both setuid-root and cap_net_raw in
fP and fE, then ping (when run by non-root user) will not run
with only cap_net_raw.
Changelog:
Apr 2 2009: Print a message once when such a binary is loaded,
as per James Morris' suggestion.
Apr 2 2009: Fix the condition to only catch uid!=0 && euid==0.
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/commoncap.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index 7cd61a5f5205..97ac1f167717 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -28,6 +28,28 @@ | |||
28 | #include <linux/prctl.h> | 28 | #include <linux/prctl.h> |
29 | #include <linux/securebits.h> | 29 | #include <linux/securebits.h> |
30 | 30 | ||
31 | /* | ||
32 | * If a non-root user executes a setuid-root binary in | ||
33 | * !secure(SECURE_NOROOT) mode, then we raise capabilities. | ||
34 | * However if fE is also set, then the intent is for only | ||
35 | * the file capabilities to be applied, and the setuid-root | ||
36 | * bit is left on either to change the uid (plausible) or | ||
37 | * to get full privilege on a kernel without file capabilities | ||
38 | * support. So in that case we do not raise capabilities. | ||
39 | * | ||
40 | * Warn if that happens, once per boot. | ||
41 | */ | ||
42 | static void warn_setuid_and_fcaps_mixed(char *fname) | ||
43 | { | ||
44 | static int warned; | ||
45 | if (!warned) { | ||
46 | printk(KERN_INFO "warning: `%s' has both setuid-root and" | ||
47 | " effective capabilities. Therefore not raising all" | ||
48 | " capabilities.\n", fname); | ||
49 | warned = 1; | ||
50 | } | ||
51 | } | ||
52 | |||
31 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) | 53 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) |
32 | { | 54 | { |
33 | NETLINK_CB(skb).eff_cap = current_cap(); | 55 | NETLINK_CB(skb).eff_cap = current_cap(); |
@@ -464,6 +486,15 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
464 | 486 | ||
465 | if (!issecure(SECURE_NOROOT)) { | 487 | if (!issecure(SECURE_NOROOT)) { |
466 | /* | 488 | /* |
489 | * If the legacy file capability is set, then don't set privs | ||
490 | * for a setuid root binary run by a non-root user. Do set it | ||
491 | * for a root user just to cause least surprise to an admin. | ||
492 | */ | ||
493 | if (effective && new->uid != 0 && new->euid == 0) { | ||
494 | warn_setuid_and_fcaps_mixed(bprm->filename); | ||
495 | goto skip; | ||
496 | } | ||
497 | /* | ||
467 | * To support inheritance of root-permissions and suid-root | 498 | * To support inheritance of root-permissions and suid-root |
468 | * executables under compatibility mode, we override the | 499 | * executables under compatibility mode, we override the |
469 | * capability sets for the file. | 500 | * capability sets for the file. |
@@ -478,6 +509,7 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |||
478 | if (new->euid == 0) | 509 | if (new->euid == 0) |
479 | effective = true; | 510 | effective = true; |
480 | } | 511 | } |
512 | skip: | ||
481 | 513 | ||
482 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised | 514 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised |
483 | * credentials unless they have the appropriate permit | 515 | * credentials unless they have the appropriate permit |