Commit b5f22a59c0356655a501190959db9f7f5dd07e3f

Authored by Serge E. Hallyn
Committed by James Morris
1 parent 3d43321b70

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