From patchwork Thu Jun 23 15:07:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Topi Miettinen X-Patchwork-Id: 9195427 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DB51F6075F for ; Thu, 23 Jun 2016 15:08:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C56212845F for ; Thu, 23 Jun 2016 15:08:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA0C628461; Thu, 23 Jun 2016 15:08:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F2642845F for ; Thu, 23 Jun 2016 15:08:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751308AbcFWPIW (ORCPT ); Thu, 23 Jun 2016 11:08:22 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:33285 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750874AbcFWPIU (ORCPT ); Thu, 23 Jun 2016 11:08:20 -0400 Received: by mail-wm0-f67.google.com with SMTP id r201so11726066wme.0; Thu, 23 Jun 2016 08:08:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=bmoPfPp+ui0GD+HiRjcU2cllqSancOV9CeuLJBFurx8=; b=lmkzqquDbaHV7dduX29rl5O3vGKgobyS3XtzG5RcTXwX5ZaJvTImfoDBgKO/0FvCYA E1D1sV974PZ5dct3qiPsu7QlAaLfRgY6yPremAAAfbiGHevnVx95jQRZp1e6nLq0d24a 9UGaTXyyRZsUkev4WMkD0c5W+/Opkqjtpia9j+fKYHUe8XFBwt6LJCDuFRFy7VcOS/cX obTp1SnR4rrrAC78kfIjpSg94ggXIw8cDO/ijevj2M5L2ywmXh2nMvqtTFVA4Y+DSLjU pmNDXQgZ/eRTJkijEAADYiqUc3K6ddDPEglLvuNBiA31rqiqyQEiHNNJb1l4JH5vGuIR zD7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=bmoPfPp+ui0GD+HiRjcU2cllqSancOV9CeuLJBFurx8=; b=iib3k5xwmWRYW+NrxM66boayIyR0zydjzJnNqXjorfN3JyciPkh6ugQUoG7R9Dn8D1 tftRSFW0WWC5wjfKzbm5skxYlxgydEzZnLC1Kn+JTHF8YTo5Lr4Mh2d8lz1T61lMxLqX DUdjWvzsO2zHCaKuUf6VNQJDXwrl6G/KFAaXnWM++ntgoe10ZywPcoVh6QFPu0IBzs7E v7KA8D54Jzp/cDUgkeqJXxICHyfTP1U88xlCHVjqyL9/IXWaO9MfBobaRPf8NVF4GxBg ITokiz90NYPjNaPbTq23JbEtVtS4NNF0eTWMIksKtskYHmrC316reqStj+IkwTSxPQPG hKBQ== X-Gm-Message-State: ALyK8tJyBIvaxMgy8tkA/zaoOsA2SX0UtUH5lTOP4uQFJNhwdZDl0UKt8H1/w6anVQsCpw== X-Received: by 10.194.246.4 with SMTP id xs4mr21015720wjc.96.1466694493091; Thu, 23 Jun 2016 08:08:13 -0700 (PDT) Received: from localhost.localdomain ([2001:2003:f54a:b700:2ab2:bdff:fe10:799e]) by smtp.gmail.com with ESMTPSA id bb4sm552699wjb.32.2016.06.23.08.08.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 Jun 2016 08:08:12 -0700 (PDT) From: Topi Miettinen To: linux-kernel@vger.kernel.org Cc: luto@kernel.org, serge@hallyn.com, keescook@chromium.org, Topi Miettinen , Jonathan Corbet , Tejun Heo , Li Zefan , Johannes Weiner , Serge Hallyn , James Morris , Andrew Morton , David Howells , David Woodhouse , Ard Biesheuvel , "Paul E. McKenney" , Petr Mladek , linux-doc@vger.kernel.org (open list:DOCUMENTATION), cgroups@vger.kernel.org (open list:CONTROL GROUP (CGROUP)), linux-security-module@vger.kernel.org (open list:CAPABILITIES) Subject: [PATCH] capabilities: add capability cgroup controller Date: Thu, 23 Jun 2016 18:07:10 +0300 Message-Id: <1466694434-1420-1-git-send-email-toiwoton@gmail.com> X-Mailer: git-send-email 2.8.1 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP There are many basic ways to control processes, including capabilities, cgroups and resource limits. However, there are far fewer ways to find out useful values for the limits, except blind trial and error. Currently, there is no way to know which capabilities are actually used. Even the source code is only implicit, in-depth knowledge of each capability must be used when analyzing a program to judge which capabilities the program will exercise. Add a new cgroup controller for monitoring of capabilities in the cgroup. Test case demonstrating basic capability monitoring and how the capabilities are combined at next level (boot to rdshell): (initramfs) cd /sys/fs (initramfs) mount -t cgroup2 cgroup cgroup (initramfs) cd cgroup (initramfs) echo +capability > cgroup.subtree_control (initramfs) mkdir test; cd test (initramfs) echo +capability > cgroup.subtree_control (initramfs) ls capability.used cgroup.events cgroup.subtree_control cgroup.controllers cgroup.procs (initramfs) mkdir first second (initramfs) sh BusyBox v1.22.1 (Debian 1:1.22.0-19) built-in shell (ash) Enter 'help' for a list of built-in commands. (initramfs) cd first (initramfs) echo $$ >cgroup.procs (initramfs) cat capability.used 0000000000000000 # nothing so far (initramfs) mknod /dev/z_$$ c 1 2 (initramfs) cat capability.used 0000000008000000 # CAP_MKNOD (initramfs) cat ../capability.used 0000000008000000 # also seen at next higher level (initramfs) exit (initramfs) sh BusyBox v1.22.1 (Debian 1:1.22.0-19) built-in shell (ash) Enter 'help' for a list of built-in commands. (initramfs) cd second (initramfs) echo $$ >cgroup.procs (initramfs) cat capability.used 0000000000000000 # nothing so far (initramfs) chown 1234 /dev/z_* (initramfs) cat capability.used 0000000000000001 # CAP_CHROOT (initramfs) cat ../capability.used 0000000008000001 # combined at next higher level (initramfs) exit Signed-off-by: Topi Miettinen --- Documentation/cgroup-v2.txt | 17 +++++++ include/linux/capability_cgroup.h | 7 +++ include/linux/cgroup_subsys.h | 4 ++ init/Kconfig | 6 +++ kernel/capability.c | 2 + security/Makefile | 1 + security/capability_cgroup.c | 99 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 136 insertions(+) create mode 100644 include/linux/capability_cgroup.h create mode 100644 security/capability_cgroup.c diff --git a/Documentation/cgroup-v2.txt b/Documentation/cgroup-v2.txt index 4cc07ce..2b3d277 100644 --- a/Documentation/cgroup-v2.txt +++ b/Documentation/cgroup-v2.txt @@ -1118,6 +1118,23 @@ writeback as follows. total available memory and applied the same way as vm.dirty[_background]_ratio. +5-4. Capabilities + +The "capability" controller is used to monitor capability use in the +cgroup. This can be used to discover a starting point for capability +bounding sets, even when running a shell script under ambient +capabilities, with only short-lived helper processes exercising the +capabilities. + + +5-4-1. Capability Interface Files + + capability.used + + A read-only file which exists on all cgroups. + + This reports the combined value of capability use in the + current cgroup and all its children. 6. Namespace diff --git a/include/linux/capability_cgroup.h b/include/linux/capability_cgroup.h new file mode 100644 index 0000000..c03b58d --- /dev/null +++ b/include/linux/capability_cgroup.h @@ -0,0 +1,7 @@ +#ifdef CONFIG_CGROUP_CAPABILITY +void capability_cgroup_update_used(int cap); +#else +static inline void capability_cgroup_update_used(int cap) +{ +} +#endif diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 0df0336a..a5161d0 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -56,6 +56,10 @@ SUBSYS(hugetlb) SUBSYS(pids) #endif +#if IS_ENABLED(CONFIG_CGROUP_CAPABILITY) +SUBSYS(capability) +#endif + /* * The following subsystems are not supported on the default hierarchy. */ diff --git a/init/Kconfig b/init/Kconfig index f755a60..25d17ef 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1141,6 +1141,12 @@ config CGROUP_PERF Say N if unsure. +config CGROUP_CAPABILITY + bool "Capability controller" + help + Provides a simple controller for monitoring of capabilities in the + cgroup. + config CGROUP_DEBUG bool "Example controller" default n diff --git a/kernel/capability.c b/kernel/capability.c index 45432b5..b57d7f9 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* @@ -380,6 +381,7 @@ bool ns_capable(struct user_namespace *ns, int cap) } if (security_capable(current_cred(), ns, cap) == 0) { + capability_cgroup_update_used(cap); current->flags |= PF_SUPERPRIV; return true; } diff --git a/security/Makefile b/security/Makefile index f2d71cd..2bb04f1 100644 --- a/security/Makefile +++ b/security/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ obj-$(CONFIG_SECURITY_YAMA) += yama/ obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o +obj-$(CONFIG_CGROUP_CAPABILITY) += capability_cgroup.o # Object integrity file lists subdir-$(CONFIG_INTEGRITY) += integrity diff --git a/security/capability_cgroup.c b/security/capability_cgroup.c new file mode 100644 index 0000000..f002477 --- /dev/null +++ b/security/capability_cgroup.c @@ -0,0 +1,99 @@ +/* + * Capability cgroup + * + * Copyright 2016 Topi Miettinen + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of the + * Linux distribution for more details. + */ + +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(capcg_mutex); + +struct capcg_cgroup { + struct cgroup_subsys_state css; + kernel_cap_t cap_used; /* Capabilities actually used */ +}; + +static inline struct capcg_cgroup *css_to_capcg(struct cgroup_subsys_state *s) +{ + return s ? container_of(s, struct capcg_cgroup, css) : NULL; +} + +static inline struct capcg_cgroup *task_to_capcg(struct task_struct *task) +{ + return css_to_capcg(task_css(task, capability_cgrp_id)); +} + +static struct cgroup_subsys_state *capcg_css_alloc(struct cgroup_subsys_state + *parent) +{ + struct capcg_cgroup *caps; + + caps = kzalloc(sizeof(*caps), GFP_KERNEL); + if (!caps) + return ERR_PTR(-ENOMEM); + + cap_clear(caps->cap_used); + return &caps->css; +} + +static void capcg_css_free(struct cgroup_subsys_state *css) +{ + kfree(css_to_capcg(css)); +} + +static int capcg_seq_show_used(struct seq_file *m, void *v) +{ + struct capcg_cgroup *capcg = css_to_capcg(seq_css(m)); + struct cgroup_subsys_state *pos; + u32 capi; + kernel_cap_t subsys_caps = capcg->cap_used; + + rcu_read_lock(); + + css_for_each_child(pos, &capcg->css) { + struct capcg_cgroup *pos_capcg = css_to_capcg(pos); + + subsys_caps = cap_combine(subsys_caps, pos_capcg->cap_used); + } + + rcu_read_unlock(); + + CAP_FOR_EACH_U32(capi) { + seq_printf(m, "%08x", + subsys_caps.cap[CAP_LAST_U32 - capi]); + } + seq_putc(m, '\n'); + + return 0; +} + +static struct cftype capcg_files[] = { + { + .name = "used", + .seq_show = capcg_seq_show_used, + }, + { } /* terminate */ +}; + +struct cgroup_subsys capability_cgrp_subsys = { + .css_alloc = capcg_css_alloc, + .css_free = capcg_css_free, + .dfl_cftypes = capcg_files, +}; + +void capability_cgroup_update_used(int cap) +{ + struct capcg_cgroup *caps = task_to_capcg(current); + + mutex_lock(&capcg_mutex); + cap_raise(caps->cap_used, cap); + mutex_unlock(&capcg_mutex); +}