kernel-hardening.lists.openwall.com archive mirror
 help / color / mirror / 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>,
	"Daniel Borkmann" <daniel@iogearbox.net>,
	"Daniel Mack" <daniel@zonque.org>,
	"David Drysdale" <drysdale@google.com>,
	"David S . Miller" <davem@davemloft.net>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	"James Morris" <james.l.morris@oracle.com>,
	"Jann Horn" <jann@thejh.net>, "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>, "Thomas Graf" <tgraf@suug.ch>,
	"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: [kernel-hardening] [RFC v4 07/18] landlock: Add LSM hooks
Date: Wed, 26 Oct 2016 08:56:43 +0200	[thread overview]
Message-ID: <20161026065654.19166-8-mic@digikod.net> (raw)
In-Reply-To: <20161026065654.19166-1-mic@digikod.net>

Add 8 file system-related hooks:
* file_open
* file_permission
* mmap_file
* inode_create
* inode_link
* inode_unlink
* inode_permission
* inode_getattr

This hook arguments are available to the Landlock rules in the eBPF
context as pointers. This pointers are an abstraction over the
underlying raw types. For now, the ARG_CONST_PTR_TO_LANDLOCK_ARG_FS type
is used for struct file, struct inode and struct path pointers.

Changes since v3:
* split commit
* add hooks dealing with struct inode and struct path pointers:
  inode_permission and inode_getattr
* add abstraction over eBPF helper arguments thanks to wrapping structs

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: David S. Miller <davem@davemloft.net>
Cc: James Morris <james.l.morris@oracle.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Serge E. Hallyn <serge@hallyn.com>
---
 include/linux/bpf.h        |   2 +
 include/linux/lsm_hooks.h  |   5 ++
 include/uapi/linux/bpf.h   |  10 ++-
 kernel/bpf/verifier.c      |   6 ++
 security/landlock/common.h |  18 +++++
 security/landlock/lsm.c    | 173 +++++++++++++++++++++++++++++++++++++++++++++
 security/security.c        |   1 +
 7 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 2cca9fc8b72b..e7ce49642f50 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -88,6 +88,7 @@ enum bpf_arg_type {
 	ARG_ANYTHING,		/* any (initialized) argument is ok */
 
 	ARG_CONST_PTR_TO_LANDLOCK_HANDLE_FS,	/* pointer to Landlock FS map handle */
+	ARG_CONST_PTR_TO_LANDLOCK_ARG_FS,	/* pointer to Landlock FS hook argument */
 };
 
 /* type of values returned from helper functions */
@@ -157,6 +158,7 @@ enum bpf_reg_type {
 
 	/* Landlock */
 	CONST_PTR_TO_LANDLOCK_HANDLE_FS,
+	CONST_PTR_TO_LANDLOCK_ARG_FS,
 };
 
 struct bpf_prog;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 558adfa5c8a8..069af34301d4 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1933,5 +1933,10 @@ void __init loadpin_add_hooks(void);
 #else
 static inline void loadpin_add_hooks(void) { };
 #endif
+#ifdef CONFIG_SECURITY_LANDLOCK
+extern void __init landlock_add_hooks(void);
+#else
+static inline void __init landlock_add_hooks(void) { }
+#endif /* CONFIG_SECURITY_LANDLOCK */
 
 #endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 335616ab63ff..b6b531a868c0 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -563,8 +563,16 @@ struct xdp_md {
 /* LSM hooks */
 enum landlock_hook {
 	LANDLOCK_HOOK_UNSPEC,
+	LANDLOCK_HOOK_FILE_OPEN,
+	LANDLOCK_HOOK_FILE_PERMISSION,
+	LANDLOCK_HOOK_MMAP_FILE,
+	LANDLOCK_HOOK_INODE_CREATE,
+	LANDLOCK_HOOK_INODE_LINK,
+	LANDLOCK_HOOK_INODE_UNLINK,
+	LANDLOCK_HOOK_INODE_PERMISSION,
+	LANDLOCK_HOOK_INODE_GETATTR,
 };
-#define _LANDLOCK_HOOK_LAST LANDLOCK_HOOK_UNSPEC
+#define _LANDLOCK_HOOK_LAST LANDLOCK_HOOK_INODE_GETATTR
 
 /* eBPF context and functions allowed for a rule */
 #define _LANDLOCK_SUBTYPE_ACCESS_MASK		((1ULL << 0) - 1)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 9b921a9afa3c..32b7941476ec 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -189,6 +189,7 @@ static const char * const reg_type_str[] = {
 	[PTR_TO_PACKET]		= "pkt",
 	[PTR_TO_PACKET_END]	= "pkt_end",
 	[CONST_PTR_TO_LANDLOCK_HANDLE_FS] = "landlock_handle_fs",
+	[CONST_PTR_TO_LANDLOCK_ARG_FS]	= "landlock_arg_fs",
 };
 
 static void print_verifier_state(struct bpf_verifier_state *state)
@@ -515,6 +516,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
 	case FRAME_PTR:
 	case CONST_PTR_TO_MAP:
 	case CONST_PTR_TO_LANDLOCK_HANDLE_FS:
+	case CONST_PTR_TO_LANDLOCK_ARG_FS:
 		return true;
 	default:
 		return false;
@@ -980,6 +982,10 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
 		expected_type = CONST_PTR_TO_LANDLOCK_HANDLE_FS;
 		if (type != expected_type)
 			goto err_type;
+	} else if (arg_type == ARG_CONST_PTR_TO_LANDLOCK_ARG_FS) {
+		expected_type = CONST_PTR_TO_LANDLOCK_ARG_FS;
+		if (type != expected_type)
+			goto err_type;
 	} else if (arg_type == ARG_PTR_TO_STACK ||
 		   arg_type == ARG_PTR_TO_RAW_STACK) {
 		expected_type = PTR_TO_STACK;
diff --git a/security/landlock/common.h b/security/landlock/common.h
index 0b5aad4a7aaa..dd64e6391dd8 100644
--- a/security/landlock/common.h
+++ b/security/landlock/common.h
@@ -12,6 +12,24 @@
 #define _SECURITY_LANDLOCK_COMMON_H
 
 #include <linux/bpf.h> /* enum landlock_hook */
+#include <linux/fs.h> /* struct file, struct inode */
+#include <linux/path.h> /* struct path */
+
+enum landlock_argtype {
+	LANDLOCK_ARGTYPE_NONE,
+	LANDLOCK_ARGTYPE_FILE,
+	LANDLOCK_ARGTYPE_INODE,
+	LANDLOCK_ARGTYPE_PATH,
+};
+
+struct landlock_arg_fs {
+	enum landlock_argtype type;
+	union {
+		struct file *file;
+		struct inode *inode;
+		const struct path *path;
+	};
+};
 
 /**
  * get_index - get an index for the rules of struct landlock_hooks
diff --git a/security/landlock/lsm.c b/security/landlock/lsm.c
index d7564540c493..b3d154275be6 100644
--- a/security/landlock/lsm.c
+++ b/security/landlock/lsm.c
@@ -15,9 +15,99 @@
 #include <linux/kernel.h> /* FIELD_SIZEOF() */
 #include <linux/landlock.h>
 #include <linux/lsm_hooks.h>
+#include <linux/types.h> /* uintptr_t */
+
+/* hook arguments */
+#include <linux/dcache.h> /* struct dentry */
+#include <linux/fs.h> /* struct inode */
+#include <linux/path.h> /* struct path */
 
 #include "common.h"
 
+#define MAP0(s, m, ...)
+#define MAP1(s, m, d, t, a) m(d, t, a)
+#define MAP2(s, m, d, t, a, ...) m(d, t, a) s() MAP1(s, m, __VA_ARGS__)
+#define MAP3(s, m, d, t, a, ...) m(d, t, a) s() MAP2(s, m, __VA_ARGS__)
+#define MAP4(s, m, d, t, a, ...) m(d, t, a) s() MAP3(s, m, __VA_ARGS__)
+#define MAP5(s, m, d, t, a, ...) m(d, t, a) s() MAP4(s, m, __VA_ARGS__)
+#define MAP6(s, m, d, t, a, ...) m(d, t, a) s() MAP5(s, m, __VA_ARGS__)
+
+/* separators */
+#define SEP_COMMA() ,
+#define SEP_NONE()
+
+/* arguments */
+#define ARG_MAP(n, ...) MAP##n(SEP_COMMA, __VA_ARGS__)
+#define ARG_REGTYPE(d, t, a) d##_REGTYPE
+#define ARG_TA(d, t, a) t a
+#define ARG_GET(d, t, a) ((u64) d##_GET(a))
+
+/* declarations */
+#define DEC_MAP(n, ...) MAP##n(SEP_NONE, DEC, __VA_ARGS__)
+#define DEC(d, t, a) d##_DEC(a)
+
+#define LANDLOCK_HOOKx(X, NAME, CNAME, ...)				\
+	static inline int landlock_hook_##NAME(				\
+		ARG_MAP(X, ARG_TA, __VA_ARGS__))			\
+	{								\
+		DEC_MAP(X, __VA_ARGS__)					\
+		__u64 args[6] = {					\
+			ARG_MAP(X, ARG_GET, __VA_ARGS__)		\
+		};							\
+		return landlock_enforce(LANDLOCK_HOOK_##CNAME, args);	\
+	}								\
+	static inline bool __is_valid_access_hook_##CNAME(		\
+			int off, int size, enum bpf_access_type type,	\
+			enum bpf_reg_type *reg_type,			\
+			union bpf_prog_subtype *prog_subtype)		\
+	{								\
+		enum bpf_reg_type arg_types[6] = {			\
+			ARG_MAP(X, ARG_REGTYPE, __VA_ARGS__)		\
+		};							\
+		return __is_valid_access(off, size, type, reg_type,	\
+				arg_types, prog_subtype);		\
+	}								\
+
+#define LANDLOCK_HOOK1(NAME, ...) LANDLOCK_HOOKx(1, NAME, __VA_ARGS__)
+#define LANDLOCK_HOOK2(NAME, ...) LANDLOCK_HOOKx(2, NAME, __VA_ARGS__)
+#define LANDLOCK_HOOK3(NAME, ...) LANDLOCK_HOOKx(3, NAME, __VA_ARGS__)
+#define LANDLOCK_HOOK4(NAME, ...) LANDLOCK_HOOKx(4, NAME, __VA_ARGS__)
+#define LANDLOCK_HOOK5(NAME, ...) LANDLOCK_HOOKx(5, NAME, __VA_ARGS__)
+#define LANDLOCK_HOOK6(NAME, ...) LANDLOCK_HOOKx(6, NAME, __VA_ARGS__)
+
+#define LANDLOCK_HOOK_INIT(NAME) LSM_HOOK_INIT(NAME, landlock_hook_##NAME)
+
+/* LANDLOCK_WRAPARG_NONE */
+#define LANDLOCK_WRAPARG_NONE_REGTYPE	NOT_INIT
+#define LANDLOCK_WRAPARG_NONE_DEC(arg)
+#define LANDLOCK_WRAPARG_NONE_GET(arg)	0
+
+/* LANDLOCK_WRAPARG_RAW */
+#define LANDLOCK_WRAPARG_RAW_REGTYPE	UNKNOWN_VALUE
+#define LANDLOCK_WRAPARG_RAW_DEC(arg)
+#define LANDLOCK_WRAPARG_RAW_GET(arg)	arg
+
+/* LANDLOCK_WRAPARG_FILE */
+#define LANDLOCK_WRAPARG_FILE_REGTYPE	CONST_PTR_TO_LANDLOCK_ARG_FS
+#define LANDLOCK_WRAPARG_FILE_DEC(arg)			\
+	const struct landlock_arg_fs wrap_##arg =	\
+	{ .type = LANDLOCK_ARGTYPE_FILE, .file = arg };
+#define LANDLOCK_WRAPARG_FILE_GET(arg)	(uintptr_t)&wrap_##arg
+
+/* LANDLOCK_WRAPARG_INODE */
+#define LANDLOCK_WRAPARG_INODE_REGTYPE	CONST_PTR_TO_LANDLOCK_ARG_FS
+#define LANDLOCK_WRAPARG_INODE_DEC(arg)			\
+	const struct landlock_arg_fs wrap_##arg =	\
+	{ .type = LANDLOCK_ARGTYPE_INODE, .inode = arg };
+#define LANDLOCK_WRAPARG_INODE_GET(arg)	(uintptr_t)&wrap_##arg
+
+/* LANDLOCK_WRAPARG_PATH */
+#define LANDLOCK_WRAPARG_PATH_REGTYPE	CONST_PTR_TO_LANDLOCK_ARG_FS
+#define LANDLOCK_WRAPARG_PATH_DEC(arg)			\
+	const struct landlock_arg_fs wrap_##arg =	\
+	{ .type = LANDLOCK_ARGTYPE_PATH, .path = arg };
+#define LANDLOCK_WRAPARG_PATH_GET(arg)	(uintptr_t)&wrap_##arg
+
 /**
  * landlock_run_prog - run Landlock program for a syscall
  *
@@ -127,6 +217,72 @@ static bool __is_valid_access(int off, int size, enum bpf_access_type type,
 	return true;
 }
 
+LANDLOCK_HOOK2(file_open, FILE_OPEN,
+	LANDLOCK_WRAPARG_FILE, struct file *, file,
+	LANDLOCK_WRAPARG_NONE, const struct cred *, cred
+)
+
+LANDLOCK_HOOK2(file_permission, FILE_PERMISSION,
+	LANDLOCK_WRAPARG_FILE, struct file *, file,
+	LANDLOCK_WRAPARG_RAW, int, mask
+)
+
+LANDLOCK_HOOK4(mmap_file, MMAP_FILE,
+	LANDLOCK_WRAPARG_FILE, struct file *, file,
+	LANDLOCK_WRAPARG_RAW, unsigned long, reqprot,
+	LANDLOCK_WRAPARG_RAW, unsigned long, prot,
+	LANDLOCK_WRAPARG_RAW, unsigned long, flags
+)
+
+/* a directory inode contains only one dentry */
+LANDLOCK_HOOK3(inode_create, INODE_CREATE,
+	LANDLOCK_WRAPARG_INODE, struct inode *, dir,
+	LANDLOCK_WRAPARG_NONE, struct dentry *, dentry,
+	LANDLOCK_WRAPARG_RAW, umode_t, mode
+)
+
+LANDLOCK_HOOK3(inode_link, INODE_LINK,
+	LANDLOCK_WRAPARG_NONE, struct dentry *, old_dentry,
+	LANDLOCK_WRAPARG_INODE, struct inode *, dir,
+	LANDLOCK_WRAPARG_NONE, struct dentry *, new_dentry
+)
+
+LANDLOCK_HOOK2(inode_unlink, INODE_UNLINK,
+	LANDLOCK_WRAPARG_INODE, struct inode *, dir,
+	LANDLOCK_WRAPARG_NONE, struct dentry *, dentry
+)
+
+LANDLOCK_HOOK2(inode_permission, INODE_PERMISSION,
+	LANDLOCK_WRAPARG_INODE, struct inode *, inode,
+	LANDLOCK_WRAPARG_RAW, int, mask
+)
+
+LANDLOCK_HOOK1(inode_getattr, INODE_GETATTR,
+	LANDLOCK_WRAPARG_PATH, const struct path *, path
+)
+
+static struct security_hook_list landlock_hooks[] = {
+	LANDLOCK_HOOK_INIT(file_open),
+	LANDLOCK_HOOK_INIT(file_permission),
+	LANDLOCK_HOOK_INIT(mmap_file),
+	LANDLOCK_HOOK_INIT(inode_create),
+	LANDLOCK_HOOK_INIT(inode_link),
+	LANDLOCK_HOOK_INIT(inode_unlink),
+	LANDLOCK_HOOK_INIT(inode_permission),
+	LANDLOCK_HOOK_INIT(inode_getattr),
+};
+
+void __init landlock_add_hooks(void)
+{
+	pr_info("landlock: Becoming ready to sandbox with seccomp\n");
+	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks));
+}
+
+#define LANDLOCK_CASE_ACCESS_HOOK(CNAME)			\
+	case LANDLOCK_HOOK_##CNAME:				\
+		return __is_valid_access_hook_##CNAME(		\
+				off, size, type, reg_type, prog_subtype);
+
 static inline bool bpf_landlock_is_valid_access(int off, int size,
 		enum bpf_access_type type, enum bpf_reg_type *reg_type,
 		union bpf_prog_subtype *prog_subtype)
@@ -134,6 +290,14 @@ static inline bool bpf_landlock_is_valid_access(int off, int size,
 	enum landlock_hook hook = prog_subtype->landlock_rule.hook;
 
 	switch (hook) {
+	LANDLOCK_CASE_ACCESS_HOOK(FILE_OPEN)
+	LANDLOCK_CASE_ACCESS_HOOK(FILE_PERMISSION)
+	LANDLOCK_CASE_ACCESS_HOOK(MMAP_FILE)
+	LANDLOCK_CASE_ACCESS_HOOK(INODE_CREATE)
+	LANDLOCK_CASE_ACCESS_HOOK(INODE_LINK)
+	LANDLOCK_CASE_ACCESS_HOOK(INODE_UNLINK)
+	LANDLOCK_CASE_ACCESS_HOOK(INODE_PERMISSION)
+	LANDLOCK_CASE_ACCESS_HOOK(INODE_GETATTR)
 	case LANDLOCK_HOOK_UNSPEC:
 	default:
 		return false;
@@ -146,6 +310,15 @@ static inline bool bpf_landlock_is_valid_subtype(
 	enum landlock_hook hook = prog_subtype->landlock_rule.hook;
 
 	switch (hook) {
+	case LANDLOCK_HOOK_FILE_OPEN:
+	case LANDLOCK_HOOK_FILE_PERMISSION:
+	case LANDLOCK_HOOK_MMAP_FILE:
+	case LANDLOCK_HOOK_INODE_CREATE:
+	case LANDLOCK_HOOK_INODE_LINK:
+	case LANDLOCK_HOOK_INODE_UNLINK:
+	case LANDLOCK_HOOK_INODE_PERMISSION:
+	case LANDLOCK_HOOK_INODE_GETATTR:
+		break;
 	case LANDLOCK_HOOK_UNSPEC:
 	default:
 		return false;
diff --git a/security/security.c b/security/security.c
index f825304f04a7..92f0f1f209b6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -61,6 +61,7 @@ int __init security_init(void)
 	capability_add_hooks();
 	yama_add_hooks();
 	loadpin_add_hooks();
+	landlock_add_hooks();
 
 	/*
 	 * Load all the remaining security modules.
-- 
2.9.3

  parent reply	other threads:[~2016-10-26  6:56 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-26  6:56 [kernel-hardening] [RFC v4 00/18] Landlock LSM: Unprivileged sandboxing Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 01/18] landlock: Add Kconfig Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 02/18] bpf: Move u64_to_ptr() to BPF headers and inline it Mickaël Salaün
2016-10-26  7:19   ` [kernel-hardening] " Arnd Bergmann
2016-10-26 13:52     ` David Sterba
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 03/18] bpf,landlock: Add a new arraymap type to deal with (Landlock) handles Mickaël Salaün
2016-10-26 19:01   ` Jann Horn
2016-10-26 20:03     ` Mickaël Salaün
2016-10-26 20:16       ` Jann Horn
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 04/18] bpf,landlock: Add eBPF program subtype and is_valid_subtype() verifier Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 05/18] bpf,landlock: Define an eBPF program type for Landlock Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 06/18] fs: Constify path_is_under()'s arguments Mickaël Salaün
2016-10-26  6:56 ` Mickaël Salaün [this message]
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 08/18] landlock: Handle file comparisons Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 09/18] landlock: Add manager functions Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 10/18] seccomp: Split put_seccomp_filter() with put_seccomp() Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 11/18] seccomp,landlock: Handle Landlock hooks per process hierarchy Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 12/18] bpf: Cosmetic change for bpf_prog_attach() Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 13/18] bpf/cgroup: Replace struct bpf_prog with struct bpf_object Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 14/18] bpf/cgroup: Make cgroup_bpf_update() return an error code Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 15/18] bpf/cgroup: Move capability check Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 16/18] bpf/cgroup,landlock: Handle Landlock hooks per cgroup Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 17/18] landlock: Add update and debug access flags Mickaël Salaün
2016-10-26  6:56 ` [kernel-hardening] [RFC v4 18/18] samples/landlock: Add sandbox example Mickaël Salaün
2016-10-26 14:52 ` [kernel-hardening] Re: [RFC v4 00/18] Landlock LSM: Unprivileged sandboxing Jann Horn
2016-10-26 16:56   ` Mickaël Salaün
2016-10-26 17:24     ` Mickaël Salaün
2016-11-13 14:23 ` Mickaël Salaün
2016-11-14 10:35   ` Sargun Dhillon
2016-11-14 20:51     ` Mickaël Salaün

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=20161026065654.19166-8-mic@digikod.net \
    --to=mic@digikod.net \
    --cc=ast@kernel.org \
    --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=james.l.morris@oracle.com \
    --cc=jann@thejh.net \
    --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=tgraf@suug.ch \
    --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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).