Commit b5f22a59c0356655a501190959db9f7f5dd07e3f
Committed by
James Morris
1 parent
3d43321b70
Exists in
master
and in
39 other branches
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>
Showing 1 changed file with 32 additions and 0 deletions Side-by-side Diff
security/commoncap.c
... | ... | @@ -28,6 +28,28 @@ |
28 | 28 | #include <linux/prctl.h> |
29 | 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 | 53 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) |
32 | 54 | { |
33 | 55 | NETLINK_CB(skb).eff_cap = current_cap(); |
... | ... | @@ -464,6 +486,15 @@ |
464 | 486 | |
465 | 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 | 498 | * To support inheritance of root-permissions and suid-root |
468 | 499 | * executables under compatibility mode, we override the |
469 | 500 | * capability sets for the file. |
... | ... | @@ -478,6 +509,7 @@ |
478 | 509 | if (new->euid == 0) |
479 | 510 | effective = true; |
480 | 511 | } |
512 | +skip: | |
481 | 513 | |
482 | 514 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised |
483 | 515 | * credentials unless they have the appropriate permit |