[OPW,kernel] kernel: Compile out support for capabilities
diff mbox

Message ID 20141030202255.GA18932@winterfell
State New, archived
Headers show

Commit Message

Iulia Manda Oct. 30, 2014, 8:22 p.m. UTC
This patch adds a new Kconfig symbol in order to conditionally compile
support for capabilities. If CONFIG_CAPABILITIES is not set, capget and
capset syscalls are removed and root will be the only user having all
capabilities.

When this option is disabled, ns_capable just checks that the both the current
namespace owner and the user are root.

Bloat-o-meter output:

add/remove: 0/3 grow/shrink: 0/2 up/down: 0/-1042 (-1042)
function                                     old     new   delta
__print_once                                  50      48      -2
ns_capable                                    77      60     -17
cap_validate_magic                           238       -    -238
sys_capget                                   354       -    -354
sys_capset                                   431       -    -431

Signed-off-by: Iulia Manda <iulia.manda21@gmail.com>
---
 init/Kconfig        |    9 +++++++++
 kernel/capability.c |   14 ++++++++++++++
 kernel/sys_ni.c     |    2 ++
 3 files changed, 25 insertions(+)

Comments

Josh Triplett Nov. 5, 2014, 7:28 p.m. UTC | #1
On Thu, Oct 30, 2014 at 10:22:55PM +0200, Iulia Manda wrote:
> This patch adds a new Kconfig symbol in order to conditionally compile
> support for capabilities. If CONFIG_CAPABILITIES is not set, capget and
> capset syscalls are removed and root will be the only user having all
> capabilities.
> 
> When this option is disabled, ns_capable just checks that the both the current
> namespace owner and the user are root.
> 
> Bloat-o-meter output:
> 
> add/remove: 0/3 grow/shrink: 0/2 up/down: 0/-1042 (-1042)
> function                                     old     new   delta
> __print_once                                  50      48      -2
> ns_capable                                    77      60     -17
> cap_validate_magic                           238       -    -238
> sys_capget                                   354       -    -354
> sys_capset                                   431       -    -431
> 
> Signed-off-by: Iulia Manda <iulia.manda21@gmail.com>

Reading through this patch, I think this will need to extend further.
Commit b3a222e52e4d4be77cc4520a57af1a4a0d8222d1, back in 2009, *removed*
the ability to compile out "file capabilities" (like setuid but for
capabilities rather than uid).  We want to avoid introducing the same
level of complexity that patch had; ideally, instead, we can use inline
functions and constant folding to get the same effect.

Note that other than the contents of capability.c itself, this *might*
not actually save significant code size without a subsequent patch
making non-root users and groups configurable; the two together will
allow capable and ns_capable to become "return true;".  At that point,
both capable and ns_capable need to become static inline stubs.
However, doing so in *this* patch would likely not help.

In that scenario, kernel/capability.c should get compiled out
completely.

Note that the PF_SUPERPRIV flag *only* gets used by accounting (acct and
tsacct), so you could simply make those select the appropriate symbols,
and then have your stub not bother setting that flag.  Similarly,
CONFIG_NAMESPACES should probably depend on the new CONFIG_NON_ROOT.

Given the intentional dropping of configurability here in commit
b3a222e52e4d4be77cc4520a57af1a4a0d8222d1, I suspect that we need the
combination of the two patches before attempting to make the case for
this.  In fact, I think it might make sense to combine them into a
single config option, since if you only have root, it also doesn't make
sense to have capabilities.

- Josh Triplett

>  init/Kconfig        |    9 +++++++++
>  kernel/capability.c |   14 ++++++++++++++
>  kernel/sys_ni.c     |    2 ++
>  3 files changed, 25 insertions(+)
> 
> diff --git a/init/Kconfig b/init/Kconfig
> index 3ee28ae..fa79701 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1216,6 +1216,15 @@ config NET_NS
>  	  Allow user space to create what appear to be multiple instances
>  	  of the network stack.
>  
> +config CAPABILITIES
> +	bool "Support for capabilities" if EXPERT
> +	default y
> +	help
> +	  This option allows a process to give capabilities to non-root users.
> +	  If unset, only root will unconditionally have all capabilities.
> +
> +	  If unsure, say Yes here.
> +
>  endif # NAMESPACES
>  
>  config SCHED_AUTOGROUP
> diff --git a/kernel/capability.c b/kernel/capability.c
> index 989f5bf..e05667a 100644
> --- a/kernel/capability.c
> +++ b/kernel/capability.c
> @@ -41,6 +41,7 @@ __setup("no_file_caps", file_caps_disable);
>   *   http://www.kernel.org/pub/linux/libs/security/linux-privs/
>   */
>  
> +#ifdef CONFIG_CAPABILITIES
>  static void warn_legacy_capability_use(void)
>  {
>  	char name[sizeof(current->comm)];
> @@ -279,6 +280,7 @@ error:
>  	abort_creds(new);
>  	return ret;
>  }
> +#endif /* ifdef CONFIG_CAPABILITIES */
>  
>  /**
>   * has_ns_capability - Does a task have a capability in a specific user ns
> @@ -371,6 +373,7 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
>   * This sets PF_SUPERPRIV on the task if the capability is available on the
>   * assumption that it's about to be used.
>   */
> +#ifdef CONFIG_CAPABILITIES
>  bool ns_capable(struct user_namespace *ns, int cap)
>  {
>  	if (unlikely(!cap_valid(cap))) {
> @@ -384,6 +387,17 @@ bool ns_capable(struct user_namespace *ns, int cap)
>  	}
>  	return false;
>  }
> +#else
> +bool ns_capable(struct user_namespace *ns, int cap)
> +{
> +	if (uid_eq(ns->owner, GLOBAL_ROOT_UID) &&
> +	    uid_eq(get_current_user()->uid, GLOBAL_ROOT_UID)) {
> +		current->flags |= PF_SUPERPRIV;
> +		return true;
> +	}
> +	return false;
> +}
> +#endif /* ifdef CONFIG_CAPABILITIES */
>  EXPORT_SYMBOL(ns_capable);
>  
>  /**
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index 02aa418..bb51700 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -159,6 +159,8 @@ cond_syscall(sys_uselib);
>  cond_syscall(sys_fadvise64);
>  cond_syscall(sys_fadvise64_64);
>  cond_syscall(sys_madvise);
> +cond_syscall(sys_capget);
> +cond_syscall(sys_capset);
>  
>  /* arch-specific weak syscall entries */
>  cond_syscall(sys_pciconfig_read);
> -- 
> 1.7.10.4
> 
> -- 
> You received this message because you are subscribed to the Google Groups "opw-kernel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to opw-kernel+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Iulia Manda Jan. 13, 2015, 10:25 p.m. UTC | #2
I have a few observations/questions below:

1. compiling out non-root users and capabilties may need to be done in two
different patches.
2. tried to compile out capabilities.c as a whole, but the resulted code was
very similar to what was trying to be avoided in commit
b3a222e52e4d4be77cc4520a57af1a4a0d8222d1 (problems encountered mostly in
security/commoncap.c).
3. tested my changes in Qemu VM, e.g:
  $ adduser test
passwd: setuid: Function not implemented
  $ su test
su: can't set groups: Invalid argument
How should userspace be noticed about these changes? Or should this be left
in the hands of the developer?
4.  Mostly due to constant propagation and constant folding, this patch
decreases the size of the final image by 24447 bytes.

Patch
diff mbox

diff --git a/init/Kconfig b/init/Kconfig
index 3ee28ae..fa79701 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1216,6 +1216,15 @@  config NET_NS
 	  Allow user space to create what appear to be multiple instances
 	  of the network stack.
 
+config CAPABILITIES
+	bool "Support for capabilities" if EXPERT
+	default y
+	help
+	  This option allows a process to give capabilities to non-root users.
+	  If unset, only root will unconditionally have all capabilities.
+
+	  If unsure, say Yes here.
+
 endif # NAMESPACES
 
 config SCHED_AUTOGROUP
diff --git a/kernel/capability.c b/kernel/capability.c
index 989f5bf..e05667a 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -41,6 +41,7 @@  __setup("no_file_caps", file_caps_disable);
  *   http://www.kernel.org/pub/linux/libs/security/linux-privs/
  */
 
+#ifdef CONFIG_CAPABILITIES
 static void warn_legacy_capability_use(void)
 {
 	char name[sizeof(current->comm)];
@@ -279,6 +280,7 @@  error:
 	abort_creds(new);
 	return ret;
 }
+#endif /* ifdef CONFIG_CAPABILITIES */
 
 /**
  * has_ns_capability - Does a task have a capability in a specific user ns
@@ -371,6 +373,7 @@  bool has_capability_noaudit(struct task_struct *t, int cap)
  * This sets PF_SUPERPRIV on the task if the capability is available on the
  * assumption that it's about to be used.
  */
+#ifdef CONFIG_CAPABILITIES
 bool ns_capable(struct user_namespace *ns, int cap)
 {
 	if (unlikely(!cap_valid(cap))) {
@@ -384,6 +387,17 @@  bool ns_capable(struct user_namespace *ns, int cap)
 	}
 	return false;
 }
+#else
+bool ns_capable(struct user_namespace *ns, int cap)
+{
+	if (uid_eq(ns->owner, GLOBAL_ROOT_UID) &&
+	    uid_eq(get_current_user()->uid, GLOBAL_ROOT_UID)) {
+		current->flags |= PF_SUPERPRIV;
+		return true;
+	}
+	return false;
+}
+#endif /* ifdef CONFIG_CAPABILITIES */
 EXPORT_SYMBOL(ns_capable);
 
 /**
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 02aa418..bb51700 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -159,6 +159,8 @@  cond_syscall(sys_uselib);
 cond_syscall(sys_fadvise64);
 cond_syscall(sys_fadvise64_64);
 cond_syscall(sys_madvise);
+cond_syscall(sys_capget);
+cond_syscall(sys_capset);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);