LKML Archive on lore.kernel.org
 help / color / Atom feed
From: "Mickaël Salaün" <mic@digikod.net>
To: linux-kernel@vger.kernel.org
Cc: "Mickaël Salaün" <mic@digikod.net>,
	"Alexei Starovoitov" <ast@kernel.org>,
	"Andy Lutomirski" <luto@amacapital.net>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Casey Schaufler" <casey@schaufler-ca.com>,
	"Daniel Borkmann" <daniel@iogearbox.net>,
	"Daniel Mack" <daniel@zonque.org>,
	"David Drysdale" <drysdale@google.com>,
	"David S . Miller" <davem@davemloft.net>,
	"Elena Reshetova" <elena.reshetova@intel.com>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	"James Morris" <james.l.morris@oracle.com>,
	"Kees Cook" <keescook@chromium.org>,
	"Paul Moore" <pmoore@redhat.com>,
	"Sargun Dhillon" <sargun@sargun.me>,
	"Serge E . Hallyn" <serge@hallyn.com>,
	"Tejun Heo" <tj@kernel.org>, "Will Drewry" <wad@chromium.org>,
	kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org,
	linux-security-module@vger.kernel.org, netdev@vger.kernel.org,
	cgroups@vger.kernel.org
Subject: [RFC v3 18/22] cgroup,landlock: Add CGRP_NO_NEW_PRIVS to handle unprivileged hooks
Date: Wed, 14 Sep 2016 09:24:11 +0200
Message-ID: <20160914072415.26021-19-mic@digikod.net> (raw)
In-Reply-To: <20160914072415.26021-1-mic@digikod.net>

Add a new flag CGRP_NO_NEW_PRIVS for each cgroup. This flag is initially
set for all cgroup except the root. The flag is clear when a new process
without the no_new_privs flags is attached to the cgroup.

If a cgroup is landlocked, then any new attempt, from an unprivileged
process, to attach a process without no_new_privs to this cgroup will
be denied.

This allows to safely manage Landlock rules with cgroup delegation as
with seccomp.

Signed-off-by: Mickaël Salaün <mic@digikod.net>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Daniel Mack <daniel@zonque.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Kees Cook <keescook@chromium.org>
Cc: Tejun Heo <tj@kernel.org>
---
 include/linux/cgroup-defs.h |  7 +++++++
 kernel/bpf/syscall.c        |  7 ++++---
 kernel/cgroup.c             | 44 ++++++++++++++++++++++++++++++++++++++++++--
 security/landlock/manager.c |  7 +++++++
 4 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index fe1023bf7b9d..ce0e4c90ae7d 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -59,6 +59,13 @@ enum {
 	 * specified at mount time and thus is implemented here.
 	 */
 	CGRP_CPUSET_CLONE_CHILDREN,
+	/*
+	 * Keep track of the no_new_privs property of processes in the cgroup.
+	 * This is useful to quickly check if all processes in the cgroup have
+	 * their no_new_privs bit on. This flag is initially set to true but
+	 * ANDed with every processes coming in the cgroup.
+	 */
+	CGRP_NO_NEW_PRIVS,
 };
 
 /* cgroup_root->flags */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f90225dbbb59..ff8b53a8a2a0 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -849,9 +849,10 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 
 	case BPF_CGROUP_LANDLOCK:
 #ifdef CONFIG_SECURITY_LANDLOCK
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-
+		/*
+		 * security/capability check done in landlock_cgroup_set_hook()
+		 * called by cgroup_bpf_update()
+		 */
 		prog = bpf_prog_get_type(attr->attach_bpf_fd,
 				BPF_PROG_TYPE_LANDLOCK);
 		break;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 3bbaf3f02ed2..913e2d3b6d55 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -62,6 +62,7 @@
 #include <linux/proc_ns.h>
 #include <linux/nsproxy.h>
 #include <linux/file.h>
+#include <linux/bitops.h>
 #include <net/sock.h>
 
 #define CREATE_TRACE_POINTS
@@ -1985,6 +1986,7 @@ static void init_cgroup_root(struct cgroup_root *root,
 		strcpy(root->name, opts->name);
 	if (opts->cpuset_clone_children)
 		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags);
+	/* no CGRP_NO_NEW_PRIVS flag for the root */
 }
 
 static int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
@@ -2812,14 +2814,35 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
 	LIST_HEAD(preloaded_csets);
 	struct task_struct *task;
 	int ret;
+#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_SECURITY_LANDLOCK)
+	bool no_new_privs;
+#endif /* CONFIG_CGROUP_BPF && CONFIG_SECURITY_LANDLOCK */
 
 	if (!cgroup_may_migrate_to(dst_cgrp))
 		return -EBUSY;
 
+	task = leader;
+#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_SECURITY_LANDLOCK)
+	no_new_privs = !!(dst_cgrp->flags & BIT_ULL(CGRP_NO_NEW_PRIVS));
+	do {
+		no_new_privs = no_new_privs && task_no_new_privs(task);
+		if (!no_new_privs) {
+			if (dst_cgrp->bpf.pinned[BPF_CGROUP_LANDLOCK].hooks &&
+					security_capable_noaudit(current_cred(),
+						current_user_ns(),
+						CAP_SYS_ADMIN) != 0)
+				return -EPERM;
+			clear_bit(CGRP_NO_NEW_PRIVS, &dst_cgrp->flags);
+			break;
+		}
+		if (!threadgroup)
+			break;
+	} while_each_thread(leader, task);
+#endif /* CONFIG_CGROUP_BPF && CONFIG_SECURITY_LANDLOCK */
+
 	/* look up all src csets */
 	spin_lock_irq(&css_set_lock);
 	rcu_read_lock();
-	task = leader;
 	do {
 		cgroup_migrate_add_src(task_css_set(task), dst_cgrp,
 				       &preloaded_csets);
@@ -4345,9 +4368,22 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
 		return -EBUSY;
 
 	mutex_lock(&cgroup_mutex);
-
 	percpu_down_write(&cgroup_threadgroup_rwsem);
 
+#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_SECURITY_LANDLOCK)
+	if (!(from->flags & BIT_ULL(CGRP_NO_NEW_PRIVS))) {
+		if (to->bpf.pinned[BPF_CGROUP_LANDLOCK].hooks &&
+				security_capable_noaudit(current_cred(),
+					current_user_ns(), CAP_SYS_ADMIN) != 0) {
+			pr_warn("%s: EPERM\n", __func__);
+			ret = -EPERM;
+			goto out_unlock;
+		}
+		pr_warn("%s: no EPERM\n", __func__);
+		clear_bit(CGRP_NO_NEW_PRIVS, &to->flags);
+	}
+#endif /* CONFIG_CGROUP_BPF && CONFIG_SECURITY_LANDLOCK */
+
 	/* all tasks in @from are being moved, all csets are source */
 	spin_lock_irq(&css_set_lock);
 	list_for_each_entry(link, &from->cset_links, cset_link)
@@ -4378,6 +4414,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
 	} while (task && !ret);
 out_err:
 	cgroup_migrate_finish(&preloaded_csets);
+out_unlock:
 	percpu_up_write(&cgroup_threadgroup_rwsem);
 	mutex_unlock(&cgroup_mutex);
 	return ret;
@@ -5241,6 +5278,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
 
 	if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags))
 		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
+#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_SECURITY_LANDLOCK)
+	set_bit(CGRP_NO_NEW_PRIVS, &cgrp->flags);
+#endif /* CONFIG_CGROUP_BPF && CONFIG_SECURITY_LANDLOCK */
 
 	cgrp->self.serial_nr = css_serial_nr_next++;
 
diff --git a/security/landlock/manager.c b/security/landlock/manager.c
index 50aa1305d0d1..479f6990aeff 100644
--- a/security/landlock/manager.c
+++ b/security/landlock/manager.c
@@ -11,6 +11,7 @@
 #include <asm/atomic.h> /* atomic_*() */
 #include <asm/page.h> /* PAGE_SIZE */
 #include <asm/uaccess.h> /* copy_from_user() */
+#include <linux/bitops.h> /* BIT_ULL() */
 #include <linux/bpf.h> /* bpf_prog_put() */
 #include <linux/filter.h> /* struct bpf_prog */
 #include <linux/kernel.h> /* round_up() */
@@ -267,6 +268,12 @@ struct landlock_hooks *landlock_cgroup_set_hook(struct cgroup *cgrp,
 	if (!prog)
 		return ERR_PTR(-EINVAL);
 
+	/* check no_new_privs for tasks in the cgroup */
+	if (!(cgrp->flags & BIT_ULL(CGRP_NO_NEW_PRIVS)) &&
+			security_capable_noaudit(current_cred(),
+				current_user_ns(), CAP_SYS_ADMIN) != 0)
+		return ERR_PTR(-EPERM);
+
 	/* copy the inherited hooks and append a new one */
 	return landlock_set_hook(cgrp->bpf.effective[BPF_CGROUP_LANDLOCK].hooks,
 			prog, NULL);
-- 
2.9.3

  parent reply index

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-14  7:23 [RFC v3 00/22] Landlock LSM: Unprivileged sandboxing Mickaël Salaün
2016-09-14  7:23 ` [RFC v3 01/22] landlock: Add Kconfig Mickaël Salaün
2016-09-14  7:23 ` [RFC v3 02/22] bpf: Move u64_to_ptr() to BPF headers and inline it Mickaël Salaün
2016-09-14  7:23 ` [RFC v3 03/22] bpf,landlock: Add a new arraymap type to deal with (Landlock) handles Mickaël Salaün
2016-09-14 18:51   ` Alexei Starovoitov
2016-09-14 23:22     ` Mickaël Salaün
2016-09-14 23:28       ` Alexei Starovoitov
2016-09-15 21:51         ` Mickaël Salaün
2016-10-03 23:53   ` Kees Cook
2016-10-05 22:02     ` Mickaël Salaün
2016-09-14  7:23 ` [RFC v3 04/22] bpf: Set register type according to is_valid_access() Mickaël Salaün
2016-10-19 14:54   ` Thomas Graf
2016-10-19 15:10     ` Daniel Borkmann
2016-09-14  7:23 ` [RFC v3 05/22] bpf,landlock: Add eBPF program subtype and is_valid_subtype() verifier Mickaël Salaün
2016-10-19 15:01   ` Thomas Graf
2016-09-14  7:23 ` [RFC v3 06/22] landlock: Add LSM hooks Mickaël Salaün
2016-10-19 15:19   ` Thomas Graf
2016-10-19 22:42     ` Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 07/22] landlock: Handle file comparisons Mickaël Salaün
2016-09-14 19:07   ` Jann Horn
2016-09-14 22:39     ` Mickaël Salaün
2016-09-14 21:06   ` Alexei Starovoitov
2016-09-14 23:02     ` Mickaël Salaün
2016-09-14 23:24       ` Alexei Starovoitov
2016-09-15 21:25         ` Mickaël Salaün
2016-09-20  0:12           ` lsm naming dilemma. " Alexei Starovoitov
2016-09-20  1:10             ` Sargun Dhillon
2016-09-20 16:58               ` Mickaël Salaün
2016-10-03 23:30   ` Kees Cook
2016-09-14  7:24 ` [RFC v3 08/22] seccomp: Fix documentation for struct seccomp_filter Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 09/22] seccomp: Move struct seccomp_filter in seccomp.h Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 10/22] seccomp: Split put_seccomp_filter() with put_seccomp() Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 11/22] seccomp,landlock: Handle Landlock hooks per process hierarchy Mickaël Salaün
2016-09-14 18:43   ` Andy Lutomirski
2016-09-14 22:34     ` Mickaël Salaün
2016-10-03 23:52       ` Kees Cook
2016-10-05 21:05         ` Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 12/22] bpf: Cosmetic change for bpf_prog_attach() Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 13/22] bpf/cgroup: Replace struct bpf_prog with union bpf_object Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 14/22] bpf/cgroup: Make cgroup_bpf_update() return an error code Mickaël Salaün
2016-09-14 21:16   ` Alexei Starovoitov
2016-09-14  7:24 ` [RFC v3 15/22] bpf/cgroup: Move capability check Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 16/22] bpf/cgroup,landlock: Handle Landlock hooks per cgroup Mickaël Salaün
2016-10-03 23:43   ` Kees Cook
2016-10-05 20:58     ` Mickaël Salaün
2016-10-05 21:25       ` Kees Cook
2016-09-14  7:24 ` [RFC v3 17/22] cgroup: Add access check for cgroup_get_from_fd() Mickaël Salaün
2016-09-14 22:06   ` Mickaël Salaün
2016-09-14  7:24 ` Mickaël Salaün [this message]
2016-09-14 18:27   ` [RFC v3 18/22] cgroup,landlock: Add CGRP_NO_NEW_PRIVS to handle unprivileged hooks Andy Lutomirski
2016-09-14 22:11     ` Mickaël Salaün
2016-09-15  1:25       ` Andy Lutomirski
2016-09-15  2:19         ` Alexei Starovoitov
2016-09-15  2:27           ` Andy Lutomirski
2016-09-15  4:00             ` Alexei Starovoitov
2016-09-15  4:08               ` Andy Lutomirski
2016-09-15  4:31                 ` Alexei Starovoitov
2016-09-15  4:38                   ` Andy Lutomirski
2016-09-15  4:48                     ` Alexei Starovoitov
2016-09-15 19:41                       ` Mickaël Salaün
2016-09-20  4:37                         ` Sargun Dhillon
2016-09-20 17:02                           ` Mickaël Salaün
2016-09-15 19:35         ` Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 19/22] landlock: Add interrupted origin Mickaël Salaün
2016-09-14 18:29   ` Andy Lutomirski
2016-09-14 22:14     ` Mickaël Salaün
2016-09-15  1:19       ` Andy Lutomirski
2016-10-03 23:46         ` Kees Cook
2016-10-05 21:01           ` Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 20/22] landlock: Add update and debug access flags Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 21/22] bpf,landlock: Add optional skb pointer in the Landlock context Mickaël Salaün
2016-09-14 21:20   ` Alexei Starovoitov
2016-09-14 22:46     ` Mickaël Salaün
2016-09-14  7:24 ` [RFC v3 22/22] samples/landlock: Add sandbox example Mickaël Salaün
2016-09-14 21:24   ` Alexei Starovoitov
2016-09-14 14:36 ` [RFC v3 00/22] Landlock LSM: Unprivileged sandboxing David Laight

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160914072415.26021-19-mic@digikod.net \
    --to=mic@digikod.net \
    --cc=arnd@arndb.de \
    --cc=ast@kernel.org \
    --cc=casey@schaufler-ca.com \
    --cc=cgroups@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=daniel@zonque.org \
    --cc=davem@davemloft.net \
    --cc=drysdale@google.com \
    --cc=ebiederm@xmission.com \
    --cc=elena.reshetova@intel.com \
    --cc=james.l.morris@oracle.com \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=netdev@vger.kernel.org \
    --cc=pmoore@redhat.com \
    --cc=sargun@sargun.me \
    --cc=serge@hallyn.com \
    --cc=tj@kernel.org \
    --cc=wad@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git
	git clone --mirror https://lore.kernel.org/lkml/9 lkml/git/9.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git