All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukasz Pawelczyk <l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
To: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>,
	"Eric W. Biederman"
	<ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>,
	"Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org>,
	Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>,
	Alexey Dobriyan
	<adobriyan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Andrew Morton
	<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>,
	Andy Lutomirski <luto-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Calvin Owens <calvinowens-b10kYP2dOMg@public.gmane.org>,
	Casey Schaufler <casey-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org>,
	David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	Eric Dumazet <edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
	Eric Paris <eparis-FjpueFixGhCM4zKIHC2jIg@public.gmane.org>,
	Greg Kroah-Hartman
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	James Morris
	<james.l.morris-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>,
	Jann Horn <jann-XZ1E9jl8jIdeoWH0uzbU5w@public.gmane.org>,
	Jiri Slaby <jslaby-IBi9RG/b67k@public.gmane.org>,
	Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>,
	John Johansen
	<john.johansen-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>,
	Jonathan Corbet <corbet-T1hC0tSOHrs@public.gmane.org>,
	Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
	Lukasz Pawelczyk
	<l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>,
	Mauro Carvalho Chehab
	<mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>,
	NeilBrown <neilb-l3A5Bk7waGM@public.gmane.org>
Cc: Lukasz Pawelczyk <havner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: [PATCH v4 09/11] smack: namespace groundwork
Date: Wed, 14 Oct 2015 14:42:03 +0200	[thread overview]
Message-ID: <1444826525-9758-10-git-send-email-l.pawelczyk@samsung.com> (raw)
In-Reply-To: <1444826525-9758-1-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

This commit introduces several changes to Smack to prepare it for
namespace implementation. All the changes are related to namespaces.

Overview of the changes:
- Adds required data structures for mapped labels and functions to
  operate on them.
- Implements the proc interface /proc/$PID/attr/label_map that can be
  used for remapping of labels for a specific namespace. Also for
  checking the map.
- Modifies handling of special built-in labels. Detects them on import
  and assigns the same char* pointer regardless whether it's used in a
  normal or a mapped label. This way we can always compare them by ==
  instead of strcmp().
- Adds User namespace hooks implementation

This patch introduces both internal and user-space visible APIs to
handle namespaced labels and Smack namespaces but the behaviour of Smack
should not be changed. The APIs are there, but they have no impact yet.

Signed-off-by: Lukasz Pawelczyk <l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Reviewed-by: Casey Schaufler <casey-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org>
---
 security/smack/Kconfig        |  10 ++
 security/smack/Makefile       |   1 +
 security/smack/smack.h        |  45 ++++-
 security/smack/smack_access.c |  47 ++++-
 security/smack/smack_lsm.c    | 134 +++++++++++++-
 security/smack/smack_ns.c     | 404 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 626 insertions(+), 15 deletions(-)
 create mode 100644 security/smack/smack_ns.c

diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..b19a7fb 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -40,3 +40,13 @@ config SECURITY_SMACK_NETFILTER
 	  This enables security marking of network packets using
 	  Smack labels.
 	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_SMACK_NS
+	bool "Smack namespace"
+	depends on SECURITY_SMACK
+	depends on USER_NS
+	help
+	  This enables Smack namespace that makes it possible to map
+	  specific labels within user namespace (analogously to mapping
+	  UIDs) and to gain MAC capabilities over them.
+	  If you are unsure how to answer this question, answer N.
diff --git a/security/smack/Makefile b/security/smack/Makefile
index ee2ebd5..5faebd7 100644
--- a/security/smack/Makefile
+++ b/security/smack/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_SECURITY_SMACK) := smack.o
 
 smack-y := smack_lsm.o smack_access.o smackfs.o
 smack-$(CONFIG_SECURITY_SMACK_NETFILTER) += smack_netfilter.o
+smack-$(CONFIG_SECURITY_SMACK_NS) += smack_ns.o
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 98bb676..4b7489f 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/lsm_audit.h>
+#include <linux/user_namespace.h>
 
 /*
  * Use IPv6 port labeling if IPv6 is enabled and secmarks
@@ -74,8 +75,36 @@ struct smack_known {
 	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */
 	struct list_head		smk_rules;	/* access rules */
 	struct mutex			smk_rules_lock;	/* lock for rules */
+#ifdef CONFIG_SECURITY_SMACK_NS
+	struct list_head		smk_mapped;	/* namespaced labels */
+	struct mutex			smk_mapped_lock;
+#endif /* CONFIG_SECURITY_SMACK_NS */
 };
 
+#ifdef CONFIG_SECURITY_SMACK_NS
+
+/*
+ * User namespace security pointer content.
+ */
+struct smack_ns {
+	struct list_head		smk_mapped;	/* namespaced labels */
+	struct mutex			smk_mapped_lock;
+};
+
+/*
+ * A single entry for a namespaced/mapped label.
+ */
+struct smack_known_ns {
+	struct list_head	smk_list_known;
+	struct list_head	smk_list_ns;
+	struct user_namespace	*smk_ns;
+	char			*smk_mapped;
+	struct smack_known	*smk_unmapped;
+	bool			smk_allocated;
+};
+
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 /*
  * Maximum number of bytes for the levels in a CIPSO IP option.
  * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -295,7 +324,7 @@ int smk_tskacc(struct task_struct *, struct smack_known *,
 	       u32, struct smk_audit_info *);
 int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
 struct smack_known *smack_from_secid(const u32);
-char *smk_parse_smack(const char *string, int len);
+char *smk_parse_smack(const char *string, int len, bool *allocated);
 int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
 struct smack_known *smk_import_entry(const char *, int);
 void smk_insert_entry(struct smack_known *skp);
@@ -310,6 +339,20 @@ char *smk_find_label_name(struct smack_known *skp);
 struct smack_known *smk_get_label(const char *string, int len, bool import);
 
 /*
+ * These functions are in smack_ns.c
+ */
+#ifdef CONFIG_SECURITY_SMACK_NS
+struct user_namespace *smk_find_mapped_ns(struct user_namespace *ns);
+struct smack_known_ns *smk_find_mapped(struct smack_known *skp,
+				       struct user_namespace *ns);
+struct smack_known *smk_find_unmapped(const char *string, int len,
+				      struct user_namespace *ns);
+extern const struct seq_operations proc_label_map_seq_operations;
+ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred,
+			     void *value, size_t size);
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
+/*
  * Shared data.
  */
 extern int smack_enabled;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 750aa9c..17b7e2c 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -452,13 +452,16 @@ struct smack_known *smk_find_entry(const char *string)
 /**
  * smk_parse_smack - parse smack label from a text string
  * @string: a text string that might contain a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
+ * @len: the maximum size, or zero if it is NULL terminated
+ * @allocated: (out) indicates whether the return string has been
+ *             allocated and has to be freed with kfree() later
+ *             (built-in labels returned are not allocated)
  *
  * Returns a pointer to the clean label or an error code.
  */
-char *smk_parse_smack(const char *string, int len)
+char *smk_parse_smack(const char *string, int len, bool *allocated)
 {
-	char *smack;
+	char *smack = NULL;
 	int i;
 
 	if (len <= 0)
@@ -480,11 +483,33 @@ char *smk_parse_smack(const char *string, int len)
 	if (i == 0 || i >= SMK_LONGLABEL)
 		return ERR_PTR(-EINVAL);
 
+	/*
+	 * Look for special labels. This way we guarantee that we can compare
+	 * special labels in mapped entries by ==, without strcmp().
+	 */
+	if (len == 1 && !strcmp(string, smack_known_huh.smk_known))
+		smack = smack_known_huh.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_hat.smk_known))
+		smack = smack_known_hat.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_star.smk_known))
+		smack = smack_known_star.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_floor.smk_known))
+		smack = smack_known_floor.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_web.smk_known))
+		smack = smack_known_web.smk_known;
+
+	if (smack) {
+		*allocated = false;
+
+		return smack;
+	}
+
 	smack = kzalloc(i + 1, GFP_KERNEL);
 	if (smack == NULL)
 		return ERR_PTR(-ENOMEM);
 
 	strncpy(smack, string, i);
+	*allocated = true;
 
 	return smack;
 }
@@ -540,8 +565,9 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	char *smack;
 	int slen;
 	int rc;
+	bool allocated;
 
-	smack = smk_parse_smack(string, len);
+	smack = smk_parse_smack(string, len, &allocated);
 	if (IS_ERR(smack))
 		return ERR_CAST(smack);
 
@@ -577,6 +603,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	if (rc >= 0) {
 		INIT_LIST_HEAD(&skp->smk_rules);
 		mutex_init(&skp->smk_rules_lock);
+#ifdef CONFIG_SECURITY_SMACK_NS
+		INIT_LIST_HEAD(&skp->smk_mapped);
+		mutex_init(&skp->smk_mapped_lock);
+#endif /* CONFIG_SECURITY_SMACK_NS */
 		/*
 		 * Make sure that the entry is actually
 		 * filled before putting it on the list.
@@ -590,7 +620,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	kfree(skp);
 	skp = ERR_PTR(rc);
 freeout:
-	kfree(smack);
+	if (allocated)
+		kfree(smack);
 unlockout:
 	mutex_unlock(&smack_known_lock);
 
@@ -748,17 +779,19 @@ char *smk_find_label_name(struct smack_known *skp)
 struct smack_known *smk_get_label(const char *string, int len, bool import)
 {
 	struct smack_known *skp;
+	bool allocated;
 	char *cp;
 
 	if (import) {
 		skp = smk_import_entry(string, len);
 	} else {
-		cp = smk_parse_smack(string, len);
+		cp = smk_parse_smack(string, len, &allocated);
 		if (IS_ERR(cp))
 			return ERR_CAST(cp);
 
 		skp = smk_find_entry(cp);
-		kfree(cp);
+		if (allocated)
+			kfree(cp);
 	}
 
 	return skp;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 5a59836..206e0ce 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -42,6 +42,7 @@
 #include <linux/shm.h>
 #include <linux/binfmts.h>
 #include <linux/parser.h>
+#include <linux/user_namespace.h>
 #include "smack.h"
 
 #define TRANS_TRUE	"TRUE"
@@ -3496,6 +3497,27 @@ unlockandout:
 }
 
 /**
+ * smack_getprocattr_seq - Smack process attribute access through seq
+ * @p: the object task
+ * @name: the name of the attribute in /proc/.../attr/
+ * @ops: out, seq_operations to handle @name
+ *
+ * Returns 0 if @name is to be handled by seq, error otherwise.
+ */
+int smack_getprocattr_seq(struct task_struct *p, const char *name,
+			  const struct seq_operations **ops)
+{
+#ifdef CONFIG_SECURITY_SMACK_NS
+	if (strcmp(name, "label_map") == 0) {
+		*ops = &proc_label_map_seq_operations;
+		return 0;
+	}
+#endif
+
+	return -EOPNOTSUPP;
+}
+
+/**
  * smack_getprocattr - Smack process attribute access
  * @p: the object task
  * @name: the name of the attribute in /proc/.../attr
@@ -3527,9 +3549,8 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 }
 
 /**
- * smack_setprocattr - Smack process attribute setting
+ * proc_current_write - Smack "current" process attribute setting
  * @p: the object task
- * @name: the name of the attribute in /proc/.../attr
  * @value: the value to set
  * @size: the size of the value
  *
@@ -3538,8 +3559,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
  *
  * Returns the length of the smack label or an error code
  */
-static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
-			     char *name, void *value, size_t size)
+static int proc_current_write(struct task_struct *p, void *value, size_t size)
 {
 	struct task_smack *tsp;
 	struct cred *new;
@@ -3558,9 +3578,6 @@ static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
 	if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
 		return -EINVAL;
 
-	if (strcmp(name, "current") != 0)
-		return -EINVAL;
-
 	skp = smk_get_label(value, size, true);
 	if (IS_ERR(skp))
 		return PTR_ERR(skp);
@@ -3583,6 +3600,33 @@ static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
 }
 
 /**
+ * smack_setprocattr - Smack process attribute setting
+ * @p: the object task
+ * @cred: the credentials of the file's opener
+ * @name: the name of the attribute in /proc/.../attr
+ * @value: the value to set
+ * @size: the size of the value
+ *
+ * Sets the proc attribute
+ *
+ * Returns the length of the written data or an error code
+ */
+static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
+			     char *name, void *value, size_t size)
+{
+#ifdef CONFIG_SECURITY_SMACK_NS
+	if (strcmp(name, "label_map") == 0)
+		return proc_label_map_write(p, f_cred, value, size);
+#endif
+
+	if (strcmp(name, "current") == 0)
+		return proc_current_write(p, value, size);
+
+	return -EINVAL;
+
+}
+
+/**
  * smack_unix_stream_connect - Smack access on UDS
  * @sock: one sock
  * @other: the other sock
@@ -4434,6 +4478,53 @@ static void smack_audit_rule_free(void *vrule)
 
 #endif /* CONFIG_AUDIT */
 
+#ifdef CONFIG_SECURITY_SMACK_NS
+
+static inline int smack_userns_create(struct user_namespace *ns)
+{
+	struct smack_ns *snsp;
+
+	snsp = kzalloc(sizeof(*snsp), GFP_KERNEL);
+	if (snsp == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&snsp->smk_mapped);
+	mutex_init(&snsp->smk_mapped_lock);
+
+	ns->security = snsp;
+	return 0;
+}
+
+static inline void smack_userns_free(struct user_namespace *ns)
+{
+	struct smack_ns *snsp = ns->security;
+	struct smack_known *skp;
+	struct smack_known_ns *sknp, *n;
+
+	list_for_each_entry_safe(sknp, n, &snsp->smk_mapped, smk_list_ns) {
+		skp = sknp->smk_unmapped;
+
+		mutex_lock(&skp->smk_mapped_lock);
+		list_del_rcu(&sknp->smk_list_known);
+		if (sknp->smk_allocated)
+			kfree(sknp->smk_mapped);
+		kfree(sknp);
+		mutex_unlock(&skp->smk_mapped_lock);
+
+		list_del(&sknp->smk_list_ns);
+	}
+
+	kfree(snsp);
+}
+
+static inline int smack_userns_setns(struct nsproxy *nsproxy,
+				     struct user_namespace *ns)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 /**
  * smack_ismaclabel - check if xattr @name references a smack MAC label
  * @name: Full xattr name to check.
@@ -4610,6 +4701,7 @@ static struct security_hook_list smack_hooks[] = {
 
 	LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),
 
+	LSM_HOOK_INIT(getprocattr_seq, smack_getprocattr_seq),
 	LSM_HOOK_INIT(getprocattr, smack_getprocattr),
 	LSM_HOOK_INIT(setprocattr, smack_setprocattr),
 
@@ -4647,6 +4739,13 @@ static struct security_hook_list smack_hooks[] = {
 	LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
 #endif /* CONFIG_AUDIT */
 
+ /* Namespace hooks */
+#ifdef CONFIG_SECURITY_SMACK_NS
+	LSM_HOOK_INIT(userns_create, smack_userns_create),
+	LSM_HOOK_INIT(userns_free, smack_userns_free),
+	LSM_HOOK_INIT(userns_setns, smack_userns_setns),
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 	LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
 	LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
 	LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
@@ -4659,6 +4758,27 @@ static struct security_hook_list smack_hooks[] = {
 
 static __init void init_smack_known_list(void)
 {
+#ifdef CONFIG_SECURITY_SMACK_NS
+	/*
+	 * Initialize mapped list locks
+	 */
+	mutex_init(&smack_known_huh.smk_mapped_lock);
+	mutex_init(&smack_known_hat.smk_mapped_lock);
+	mutex_init(&smack_known_floor.smk_mapped_lock);
+	mutex_init(&smack_known_star.smk_mapped_lock);
+	mutex_init(&smack_known_invalid.smk_mapped_lock);
+	mutex_init(&smack_known_web.smk_mapped_lock);
+	/*
+	 * Initialize mapped lists
+	 */
+	INIT_LIST_HEAD(&smack_known_huh.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_hat.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_star.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_floor.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_invalid.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_web.smk_mapped);
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 	/*
 	 * Initialize rule list locks
 	 */
diff --git a/security/smack/smack_ns.c b/security/smack/smack_ns.c
new file mode 100644
index 0000000..49223c4
--- /dev/null
+++ b/security/smack/smack_ns.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics.
+ *
+ * Smack namespaces
+ *
+ * Author(s):
+ *    Lukasz Pawelczyk <l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
+ *
+ * This program is free software, you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/file.h>
+#include <linux/ctype.h>
+#include <linux/rculist.h>
+#include <linux/seq_file.h>
+#include <linux/user_namespace.h>
+#include "smack.h"
+
+/**
+ * smk_find_mapped_ns - Finds a first namespace from this one through
+ * its parrents that has a map. This map is the effective map in this
+ * namespace.
+ * @ns: a user namespace for which we search for a mapped ns
+ *
+ * Returns a namespace that has a non-NULL map, or NULL if there is
+ * no mapped namespace.
+ *
+ * Can be effectively used to answer a question: "is there a Smack
+ * map for this namespace?"
+ */
+struct user_namespace *smk_find_mapped_ns(struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = ns;
+
+	do {
+		struct smack_ns *sns = user_ns->security;
+
+		if (sns && !list_empty(&sns->smk_mapped))
+			break;
+
+		user_ns = user_ns->parent;
+	} while (user_ns);
+
+	return user_ns;
+}
+
+/**
+ * __smk_find_mapped - an internal version of smk_find_mapped
+ *                     that doesn't use smk_find_mapped_ns, but
+ *                     operates directly on the passed one.
+ */
+static struct smack_known_ns *__smk_find_mapped(struct smack_known *skp,
+						struct user_namespace *ns)
+{
+	struct smack_known_ns *sknp;
+
+	if (ns == NULL)
+		return NULL;
+
+	list_for_each_entry_rcu(sknp, &skp->smk_mapped, smk_list_known)
+		if (sknp->smk_ns == ns)
+			return sknp;
+
+	return NULL;
+}
+
+/**
+ * smk_find_mapped - Finds a mapped label on the smack_known's mapped list
+ * @skp: a label which mapped label we look for
+ * @ns: a user namespace the label we search for is assigned to
+ *
+ * Returns a pointer to the mapped label if one exists that is
+ * assigned to the specified user namespace or NULL if not found.
+ */
+struct smack_known_ns *smk_find_mapped(struct smack_known *skp,
+				       struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = smk_find_mapped_ns(ns);
+
+	return __smk_find_mapped(skp, user_ns);
+}
+
+/**
+ * __smk_find_unmapped - an internal version of smk_find_unmapped
+ *                       that doesn't use smk_find_mapped_ns, but
+ *                       operates directly on the passed one.
+ */
+static struct smack_known *__smk_find_unmapped(const char *string, int len,
+					       struct user_namespace *ns)
+{
+	struct smack_ns *snsp;
+	struct smack_known *skp = NULL;
+	struct smack_known_ns *sknp;
+	char *smack;
+	bool allocated = false;
+
+	if (ns == NULL)
+		return NULL;
+
+	snsp = ns->security;
+
+	smack = smk_parse_smack(string, len, &allocated);
+	if (IS_ERR(smack))
+		return ERR_CAST(smack);
+
+	list_for_each_entry_rcu(sknp, &snsp->smk_mapped, smk_list_ns) {
+		if (strcmp(smack, sknp->smk_mapped) == 0) {
+			skp = sknp->smk_unmapped;
+			break;
+		}
+	}
+
+	if (allocated)
+		kfree(smack);
+	return skp;
+}
+
+/**
+ * smk_find_unmapped - Finds an original label by a mapped label string
+ *                     and the namespace it could be mapped in
+ * @string: a name of a mapped label we look for
+ * @len: the string size, or zero if it is NULL terminated.
+ * @ns: a namespace the looked for label should be mapped in
+ *
+ * Returns a smack_known label that is mapped as 'string' in 'ns',
+ * NULL if not found or an error code.
+ */
+struct smack_known *smk_find_unmapped(const char *string, int len,
+				      struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = smk_find_mapped_ns(ns);
+
+	return __smk_find_unmapped(string, len, user_ns);
+}
+
+/**
+ * smk_import_mapped - Imports a mapped label effectively creating a mapping.
+ * @skp: a label we map
+ * @ns: a user namespace this label will be mapped in
+ * @string: a text string of the mapped label
+ * @len: the maximum size, or zero if it is NULL terminanted
+ *
+ * Returns a pointer to the mapped label entry or an error code.
+ *
+ * The mapped label will be added to 2 lists:
+ *   - a list of mapped labels of skp
+ *   - a list of labels mapped in ns
+ */
+static struct smack_known_ns *smk_import_mapped(struct smack_known *skp,
+						struct user_namespace *ns,
+						const char *string, int len)
+{
+	struct smack_ns *snsp = ns->security;
+	struct smack_known_ns *sknp;
+	char *mapped;
+	bool allocated;
+
+	/* Mapping init_user_ns is against the design and pointless */
+	if (ns == &init_user_ns)
+		return ERR_PTR(-EBADR);
+
+	mapped = smk_parse_smack(string, len, &allocated);
+	if (IS_ERR(mapped))
+		return ERR_CAST(mapped);
+
+	mutex_lock(&skp->smk_mapped_lock);
+
+	/*
+	 * Don't allow one<->many mappings in namespace, rename.
+	 * This code won't get triggered for now as trying to assign
+	 * a duplicate is forbidden in proc_label_map_write().
+	 * Leaving this as this function might be also used elsewhere.
+	 */
+	sknp = smk_find_mapped(skp, ns);
+	if (sknp != NULL) {
+		if (sknp->smk_allocated)
+			kfree(sknp->smk_mapped);
+		sknp->smk_mapped = mapped;
+		sknp->smk_allocated = allocated;
+		goto unlockout;
+	}
+
+	sknp = kzalloc(sizeof(*sknp), GFP_KERNEL);
+	if (sknp == NULL) {
+		sknp = ERR_PTR(-ENOMEM);
+		if (allocated)
+			kfree(mapped);
+		goto unlockout;
+	}
+
+	sknp->smk_ns = ns;
+	sknp->smk_mapped = mapped;
+	sknp->smk_allocated = allocated;
+	sknp->smk_unmapped = skp;
+	list_add_rcu(&sknp->smk_list_known, &skp->smk_mapped);
+
+	mutex_lock(&snsp->smk_mapped_lock);
+	list_add_rcu(&sknp->smk_list_ns, &snsp->smk_mapped);
+	mutex_unlock(&snsp->smk_mapped_lock);
+
+unlockout:
+	mutex_unlock(&skp->smk_mapped_lock);
+
+	return sknp;
+}
+
+static void *proc_label_map_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct smack_known *skp;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+	loff_t counter = *pos;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list)
+		if (smk_find_mapped(skp, ns) && counter-- == 0)
+			return skp;
+
+	return NULL;
+}
+
+static void proc_label_map_seq_stop(struct seq_file *seq, void *v)
+{
+	rcu_read_unlock();
+}
+
+static void *proc_label_map_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct smack_known *skp = v;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+
+	list_for_each_entry_continue_rcu(skp, &smack_known_list, list) {
+		if (smk_find_mapped(skp, ns)) {
+			(*pos)++;
+			return skp;
+		}
+	}
+
+	return NULL;
+}
+
+static int proc_label_map_seq_show(struct seq_file *seq, void *v)
+{
+	struct smack_known *skp = v;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+	struct smack_known_ns *sknp;
+
+	sknp = smk_find_mapped(skp, ns);
+	if (sknp)
+		seq_printf(seq, "%s -> %s\n", skp->smk_known, sknp->smk_mapped);
+
+	return 0;
+}
+
+const struct seq_operations proc_label_map_seq_operations = {
+	.start = proc_label_map_seq_start,
+	.stop = proc_label_map_seq_stop,
+	.next = proc_label_map_seq_next,
+	.show = proc_label_map_seq_show,
+};
+
+static DEFINE_MUTEX(smk_map_mutex);
+
+static bool mapping_permitted(const struct cred *f_cred,
+			      struct user_namespace *user_ns)
+{
+	/*
+	 * Do not allow mapping own label. This is in contrast to user
+	 * namespace where you can always map your own UID. In Smack having
+	 * administrative privileges over your own label (which Smack
+	 * namespace would effectively give you) is not equivalent to user
+	 * namespace. E.g. things like setting exec/transmute labels that
+	 * otherwise would be denied. Hence no own_label param here.
+	 */
+
+	/*
+	 * Adjusting namespace settings requires capabilities on the target.
+	 */
+	if (security_capable(f_cred, user_ns, CAP_MAC_ADMIN) != 0)
+		return false;
+
+	/*
+	 * And it requires capabilities in the parent.
+	 *
+	 * If the Smack namespace was properly hierarchical the user_ns to
+	 * check against could be 'user_ns->parent'. Right now because of
+	 * security concerns only privileged initial namespace is allowed
+	 * to fill the map. For a hierarchical namespaces one would
+	 * implement mapping (in the child namespaces) of only mapped labels
+	 * (in parent namespace) and change '&init_user_ns' to
+	 * 'user_ns->parent'. This will be added in the future.
+	 */
+	if (smack_ns_privileged(&init_user_ns, CAP_MAC_ADMIN) &&
+	    security_capable(f_cred, &init_user_ns, CAP_MAC_ADMIN) == 0)
+		return true;
+
+	return false;
+}
+
+ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred,
+			     void *value, size_t size)
+{
+	struct user_namespace *ns = ns_of_task_struct(p);
+	struct user_namespace *cur_ns = ns_of_current();
+	struct smack_known *skp;
+	struct smack_known_ns *sknp;
+	char *pos, *next_line, *tok[2];
+	ssize_t ret;
+	int i;
+
+	/* Mapping labels for the init ns makes no sense */
+	if (ns == &init_user_ns)
+		return -EBADR;
+
+	if (cur_ns != ns->parent)
+		return -EPERM;
+
+	if (!mapping_permitted(f_cred, ns))
+		return -EPERM;
+
+	if (value == NULL || size == 0 || size >= PAGE_SIZE)
+		return -EINVAL;
+
+	mutex_lock(&smk_map_mutex);
+
+	/* Parse the user data */
+	pos = value;
+	pos[size] = '\0';
+
+	for (; pos; pos = next_line) {
+		ret = -EINVAL;
+
+		/* Find the end of line and ensure I don't look past it */
+		next_line = strchr(pos, '\n');
+		if (next_line) {
+			*next_line = '\0';
+			next_line++;
+			if (*next_line == '\0')
+				next_line = NULL;
+		}
+
+		/* Find tokens in line */
+		for (i = 0; i < 2; ++i) {
+			while (isspace(*pos))
+				*(pos++) = '\0';
+
+			/* unexpected end of file */
+			if (*pos == '\0')
+				goto out;
+
+			tok[i] = pos;
+
+			/* find the end of the token */
+			while (*pos != '\0' && !isspace(*pos))
+				++pos;
+		}
+
+		/* NUL terminate the last token if not EOL */
+		while (isspace(*pos))
+			*(pos++) = '\0';
+
+		/* there should not be any trailing data */
+		if (*pos != '\0')
+			goto out;
+
+		ret = -EEXIST;
+
+		/* do not allow to map 2 different labels to one name */
+		skp = __smk_find_unmapped(tok[1], 0, ns);
+		if (IS_ERR(skp)) {
+			ret = PTR_ERR(skp);
+			goto out;
+		}
+		if (skp != NULL)
+			goto out;
+
+		skp = smk_import_entry(tok[0], 0);
+		if (IS_ERR(skp)) {
+			ret = PTR_ERR(skp);
+			goto out;
+		}
+
+		/* do not allow remapping */
+		if (__smk_find_mapped(skp, ns))
+			goto out;
+
+		sknp = smk_import_mapped(skp, ns, tok[1], 0);
+		if (IS_ERR(sknp)) {
+			ret = PTR_ERR(sknp);
+			goto out;
+		}
+	}
+
+	ret = size;
+
+out:
+	mutex_unlock(&smk_map_mutex);
+
+	return ret;
+}
-- 
2.4.3

WARNING: multiple messages have this Message-ID (diff)
From: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
To: "David S. Miller" <davem@davemloft.net>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Alexey Dobriyan <adobriyan@gmail.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Andy Lutomirski <luto@kernel.org>,
	Calvin Owens <calvinowens@fb.com>,
	Casey Schaufler <casey@schaufler-ca.com>,
	David Howells <dhowells@redhat.com>,
	Eric Dumazet <edumazet@google.com>,
	Eric Paris <eparis@parisplace.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	James Morris <james.l.morris@oracle.com>,
	Jann Horn <jann@thejh.net>, Jiri Slaby <jslaby@suse.com>,
	Joe Perches <joe@perches.com>,
	John Johansen <john.johansen@canonical.com>,
	Jonathan Corbet <corbet@lwn.net>,
	Kees Cook <keescook@chromium.org>,
	Lukasz Pawelczyk <l.pawelczyk@samsung.com>,
	Mauro Carvalho Chehab <mchehab@osg.samsung.com>,
	NeilBrown <neilb@suse.de>, Paul Moore <paul@paul-moore.com>,
	Serge Hallyn <serge.hallyn@canonical.com>,
	Stephen Smalley <sds@tycho.nsa.gov>, Tejun Heo <tj@kernel.org>,
	Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
	containers@lists.linuxfoundation.org, linux-doc@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-security-module@vger.kernel.org, selinux@tycho.nsa.gov
Cc: Lukasz Pawelczyk <havner@gmail.com>
Subject: [PATCH v4 09/11] smack: namespace groundwork
Date: Wed, 14 Oct 2015 14:42:03 +0200	[thread overview]
Message-ID: <1444826525-9758-10-git-send-email-l.pawelczyk@samsung.com> (raw)
In-Reply-To: <1444826525-9758-1-git-send-email-l.pawelczyk@samsung.com>

This commit introduces several changes to Smack to prepare it for
namespace implementation. All the changes are related to namespaces.

Overview of the changes:
- Adds required data structures for mapped labels and functions to
  operate on them.
- Implements the proc interface /proc/$PID/attr/label_map that can be
  used for remapping of labels for a specific namespace. Also for
  checking the map.
- Modifies handling of special built-in labels. Detects them on import
  and assigns the same char* pointer regardless whether it's used in a
  normal or a mapped label. This way we can always compare them by ==
  instead of strcmp().
- Adds User namespace hooks implementation

This patch introduces both internal and user-space visible APIs to
handle namespaced labels and Smack namespaces but the behaviour of Smack
should not be changed. The APIs are there, but they have no impact yet.

Signed-off-by: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
---
 security/smack/Kconfig        |  10 ++
 security/smack/Makefile       |   1 +
 security/smack/smack.h        |  45 ++++-
 security/smack/smack_access.c |  47 ++++-
 security/smack/smack_lsm.c    | 134 +++++++++++++-
 security/smack/smack_ns.c     | 404 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 626 insertions(+), 15 deletions(-)
 create mode 100644 security/smack/smack_ns.c

diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..b19a7fb 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -40,3 +40,13 @@ config SECURITY_SMACK_NETFILTER
 	  This enables security marking of network packets using
 	  Smack labels.
 	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_SMACK_NS
+	bool "Smack namespace"
+	depends on SECURITY_SMACK
+	depends on USER_NS
+	help
+	  This enables Smack namespace that makes it possible to map
+	  specific labels within user namespace (analogously to mapping
+	  UIDs) and to gain MAC capabilities over them.
+	  If you are unsure how to answer this question, answer N.
diff --git a/security/smack/Makefile b/security/smack/Makefile
index ee2ebd5..5faebd7 100644
--- a/security/smack/Makefile
+++ b/security/smack/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_SECURITY_SMACK) := smack.o
 
 smack-y := smack_lsm.o smack_access.o smackfs.o
 smack-$(CONFIG_SECURITY_SMACK_NETFILTER) += smack_netfilter.o
+smack-$(CONFIG_SECURITY_SMACK_NS) += smack_ns.o
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 98bb676..4b7489f 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/lsm_audit.h>
+#include <linux/user_namespace.h>
 
 /*
  * Use IPv6 port labeling if IPv6 is enabled and secmarks
@@ -74,8 +75,36 @@ struct smack_known {
 	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */
 	struct list_head		smk_rules;	/* access rules */
 	struct mutex			smk_rules_lock;	/* lock for rules */
+#ifdef CONFIG_SECURITY_SMACK_NS
+	struct list_head		smk_mapped;	/* namespaced labels */
+	struct mutex			smk_mapped_lock;
+#endif /* CONFIG_SECURITY_SMACK_NS */
 };
 
+#ifdef CONFIG_SECURITY_SMACK_NS
+
+/*
+ * User namespace security pointer content.
+ */
+struct smack_ns {
+	struct list_head		smk_mapped;	/* namespaced labels */
+	struct mutex			smk_mapped_lock;
+};
+
+/*
+ * A single entry for a namespaced/mapped label.
+ */
+struct smack_known_ns {
+	struct list_head	smk_list_known;
+	struct list_head	smk_list_ns;
+	struct user_namespace	*smk_ns;
+	char			*smk_mapped;
+	struct smack_known	*smk_unmapped;
+	bool			smk_allocated;
+};
+
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 /*
  * Maximum number of bytes for the levels in a CIPSO IP option.
  * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -295,7 +324,7 @@ int smk_tskacc(struct task_struct *, struct smack_known *,
 	       u32, struct smk_audit_info *);
 int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
 struct smack_known *smack_from_secid(const u32);
-char *smk_parse_smack(const char *string, int len);
+char *smk_parse_smack(const char *string, int len, bool *allocated);
 int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
 struct smack_known *smk_import_entry(const char *, int);
 void smk_insert_entry(struct smack_known *skp);
@@ -310,6 +339,20 @@ char *smk_find_label_name(struct smack_known *skp);
 struct smack_known *smk_get_label(const char *string, int len, bool import);
 
 /*
+ * These functions are in smack_ns.c
+ */
+#ifdef CONFIG_SECURITY_SMACK_NS
+struct user_namespace *smk_find_mapped_ns(struct user_namespace *ns);
+struct smack_known_ns *smk_find_mapped(struct smack_known *skp,
+				       struct user_namespace *ns);
+struct smack_known *smk_find_unmapped(const char *string, int len,
+				      struct user_namespace *ns);
+extern const struct seq_operations proc_label_map_seq_operations;
+ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred,
+			     void *value, size_t size);
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
+/*
  * Shared data.
  */
 extern int smack_enabled;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 750aa9c..17b7e2c 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -452,13 +452,16 @@ struct smack_known *smk_find_entry(const char *string)
 /**
  * smk_parse_smack - parse smack label from a text string
  * @string: a text string that might contain a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
+ * @len: the maximum size, or zero if it is NULL terminated
+ * @allocated: (out) indicates whether the return string has been
+ *             allocated and has to be freed with kfree() later
+ *             (built-in labels returned are not allocated)
  *
  * Returns a pointer to the clean label or an error code.
  */
-char *smk_parse_smack(const char *string, int len)
+char *smk_parse_smack(const char *string, int len, bool *allocated)
 {
-	char *smack;
+	char *smack = NULL;
 	int i;
 
 	if (len <= 0)
@@ -480,11 +483,33 @@ char *smk_parse_smack(const char *string, int len)
 	if (i == 0 || i >= SMK_LONGLABEL)
 		return ERR_PTR(-EINVAL);
 
+	/*
+	 * Look for special labels. This way we guarantee that we can compare
+	 * special labels in mapped entries by ==, without strcmp().
+	 */
+	if (len == 1 && !strcmp(string, smack_known_huh.smk_known))
+		smack = smack_known_huh.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_hat.smk_known))
+		smack = smack_known_hat.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_star.smk_known))
+		smack = smack_known_star.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_floor.smk_known))
+		smack = smack_known_floor.smk_known;
+	else if (len == 1 && !strcmp(string, smack_known_web.smk_known))
+		smack = smack_known_web.smk_known;
+
+	if (smack) {
+		*allocated = false;
+
+		return smack;
+	}
+
 	smack = kzalloc(i + 1, GFP_KERNEL);
 	if (smack == NULL)
 		return ERR_PTR(-ENOMEM);
 
 	strncpy(smack, string, i);
+	*allocated = true;
 
 	return smack;
 }
@@ -540,8 +565,9 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	char *smack;
 	int slen;
 	int rc;
+	bool allocated;
 
-	smack = smk_parse_smack(string, len);
+	smack = smk_parse_smack(string, len, &allocated);
 	if (IS_ERR(smack))
 		return ERR_CAST(smack);
 
@@ -577,6 +603,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	if (rc >= 0) {
 		INIT_LIST_HEAD(&skp->smk_rules);
 		mutex_init(&skp->smk_rules_lock);
+#ifdef CONFIG_SECURITY_SMACK_NS
+		INIT_LIST_HEAD(&skp->smk_mapped);
+		mutex_init(&skp->smk_mapped_lock);
+#endif /* CONFIG_SECURITY_SMACK_NS */
 		/*
 		 * Make sure that the entry is actually
 		 * filled before putting it on the list.
@@ -590,7 +620,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
 	kfree(skp);
 	skp = ERR_PTR(rc);
 freeout:
-	kfree(smack);
+	if (allocated)
+		kfree(smack);
 unlockout:
 	mutex_unlock(&smack_known_lock);
 
@@ -748,17 +779,19 @@ char *smk_find_label_name(struct smack_known *skp)
 struct smack_known *smk_get_label(const char *string, int len, bool import)
 {
 	struct smack_known *skp;
+	bool allocated;
 	char *cp;
 
 	if (import) {
 		skp = smk_import_entry(string, len);
 	} else {
-		cp = smk_parse_smack(string, len);
+		cp = smk_parse_smack(string, len, &allocated);
 		if (IS_ERR(cp))
 			return ERR_CAST(cp);
 
 		skp = smk_find_entry(cp);
-		kfree(cp);
+		if (allocated)
+			kfree(cp);
 	}
 
 	return skp;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 5a59836..206e0ce 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -42,6 +42,7 @@
 #include <linux/shm.h>
 #include <linux/binfmts.h>
 #include <linux/parser.h>
+#include <linux/user_namespace.h>
 #include "smack.h"
 
 #define TRANS_TRUE	"TRUE"
@@ -3496,6 +3497,27 @@ unlockandout:
 }
 
 /**
+ * smack_getprocattr_seq - Smack process attribute access through seq
+ * @p: the object task
+ * @name: the name of the attribute in /proc/.../attr/
+ * @ops: out, seq_operations to handle @name
+ *
+ * Returns 0 if @name is to be handled by seq, error otherwise.
+ */
+int smack_getprocattr_seq(struct task_struct *p, const char *name,
+			  const struct seq_operations **ops)
+{
+#ifdef CONFIG_SECURITY_SMACK_NS
+	if (strcmp(name, "label_map") == 0) {
+		*ops = &proc_label_map_seq_operations;
+		return 0;
+	}
+#endif
+
+	return -EOPNOTSUPP;
+}
+
+/**
  * smack_getprocattr - Smack process attribute access
  * @p: the object task
  * @name: the name of the attribute in /proc/.../attr
@@ -3527,9 +3549,8 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 }
 
 /**
- * smack_setprocattr - Smack process attribute setting
+ * proc_current_write - Smack "current" process attribute setting
  * @p: the object task
- * @name: the name of the attribute in /proc/.../attr
  * @value: the value to set
  * @size: the size of the value
  *
@@ -3538,8 +3559,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
  *
  * Returns the length of the smack label or an error code
  */
-static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
-			     char *name, void *value, size_t size)
+static int proc_current_write(struct task_struct *p, void *value, size_t size)
 {
 	struct task_smack *tsp;
 	struct cred *new;
@@ -3558,9 +3578,6 @@ static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
 	if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
 		return -EINVAL;
 
-	if (strcmp(name, "current") != 0)
-		return -EINVAL;
-
 	skp = smk_get_label(value, size, true);
 	if (IS_ERR(skp))
 		return PTR_ERR(skp);
@@ -3583,6 +3600,33 @@ static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
 }
 
 /**
+ * smack_setprocattr - Smack process attribute setting
+ * @p: the object task
+ * @cred: the credentials of the file's opener
+ * @name: the name of the attribute in /proc/.../attr
+ * @value: the value to set
+ * @size: the size of the value
+ *
+ * Sets the proc attribute
+ *
+ * Returns the length of the written data or an error code
+ */
+static int smack_setprocattr(struct task_struct *p, const struct cred *f_cred,
+			     char *name, void *value, size_t size)
+{
+#ifdef CONFIG_SECURITY_SMACK_NS
+	if (strcmp(name, "label_map") == 0)
+		return proc_label_map_write(p, f_cred, value, size);
+#endif
+
+	if (strcmp(name, "current") == 0)
+		return proc_current_write(p, value, size);
+
+	return -EINVAL;
+
+}
+
+/**
  * smack_unix_stream_connect - Smack access on UDS
  * @sock: one sock
  * @other: the other sock
@@ -4434,6 +4478,53 @@ static void smack_audit_rule_free(void *vrule)
 
 #endif /* CONFIG_AUDIT */
 
+#ifdef CONFIG_SECURITY_SMACK_NS
+
+static inline int smack_userns_create(struct user_namespace *ns)
+{
+	struct smack_ns *snsp;
+
+	snsp = kzalloc(sizeof(*snsp), GFP_KERNEL);
+	if (snsp == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&snsp->smk_mapped);
+	mutex_init(&snsp->smk_mapped_lock);
+
+	ns->security = snsp;
+	return 0;
+}
+
+static inline void smack_userns_free(struct user_namespace *ns)
+{
+	struct smack_ns *snsp = ns->security;
+	struct smack_known *skp;
+	struct smack_known_ns *sknp, *n;
+
+	list_for_each_entry_safe(sknp, n, &snsp->smk_mapped, smk_list_ns) {
+		skp = sknp->smk_unmapped;
+
+		mutex_lock(&skp->smk_mapped_lock);
+		list_del_rcu(&sknp->smk_list_known);
+		if (sknp->smk_allocated)
+			kfree(sknp->smk_mapped);
+		kfree(sknp);
+		mutex_unlock(&skp->smk_mapped_lock);
+
+		list_del(&sknp->smk_list_ns);
+	}
+
+	kfree(snsp);
+}
+
+static inline int smack_userns_setns(struct nsproxy *nsproxy,
+				     struct user_namespace *ns)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 /**
  * smack_ismaclabel - check if xattr @name references a smack MAC label
  * @name: Full xattr name to check.
@@ -4610,6 +4701,7 @@ static struct security_hook_list smack_hooks[] = {
 
 	LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),
 
+	LSM_HOOK_INIT(getprocattr_seq, smack_getprocattr_seq),
 	LSM_HOOK_INIT(getprocattr, smack_getprocattr),
 	LSM_HOOK_INIT(setprocattr, smack_setprocattr),
 
@@ -4647,6 +4739,13 @@ static struct security_hook_list smack_hooks[] = {
 	LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
 #endif /* CONFIG_AUDIT */
 
+ /* Namespace hooks */
+#ifdef CONFIG_SECURITY_SMACK_NS
+	LSM_HOOK_INIT(userns_create, smack_userns_create),
+	LSM_HOOK_INIT(userns_free, smack_userns_free),
+	LSM_HOOK_INIT(userns_setns, smack_userns_setns),
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 	LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
 	LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
 	LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
@@ -4659,6 +4758,27 @@ static struct security_hook_list smack_hooks[] = {
 
 static __init void init_smack_known_list(void)
 {
+#ifdef CONFIG_SECURITY_SMACK_NS
+	/*
+	 * Initialize mapped list locks
+	 */
+	mutex_init(&smack_known_huh.smk_mapped_lock);
+	mutex_init(&smack_known_hat.smk_mapped_lock);
+	mutex_init(&smack_known_floor.smk_mapped_lock);
+	mutex_init(&smack_known_star.smk_mapped_lock);
+	mutex_init(&smack_known_invalid.smk_mapped_lock);
+	mutex_init(&smack_known_web.smk_mapped_lock);
+	/*
+	 * Initialize mapped lists
+	 */
+	INIT_LIST_HEAD(&smack_known_huh.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_hat.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_star.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_floor.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_invalid.smk_mapped);
+	INIT_LIST_HEAD(&smack_known_web.smk_mapped);
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 	/*
 	 * Initialize rule list locks
 	 */
diff --git a/security/smack/smack_ns.c b/security/smack/smack_ns.c
new file mode 100644
index 0000000..49223c4
--- /dev/null
+++ b/security/smack/smack_ns.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics.
+ *
+ * Smack namespaces
+ *
+ * Author(s):
+ *    Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+ *
+ * This program is free software, you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/file.h>
+#include <linux/ctype.h>
+#include <linux/rculist.h>
+#include <linux/seq_file.h>
+#include <linux/user_namespace.h>
+#include "smack.h"
+
+/**
+ * smk_find_mapped_ns - Finds a first namespace from this one through
+ * its parrents that has a map. This map is the effective map in this
+ * namespace.
+ * @ns: a user namespace for which we search for a mapped ns
+ *
+ * Returns a namespace that has a non-NULL map, or NULL if there is
+ * no mapped namespace.
+ *
+ * Can be effectively used to answer a question: "is there a Smack
+ * map for this namespace?"
+ */
+struct user_namespace *smk_find_mapped_ns(struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = ns;
+
+	do {
+		struct smack_ns *sns = user_ns->security;
+
+		if (sns && !list_empty(&sns->smk_mapped))
+			break;
+
+		user_ns = user_ns->parent;
+	} while (user_ns);
+
+	return user_ns;
+}
+
+/**
+ * __smk_find_mapped - an internal version of smk_find_mapped
+ *                     that doesn't use smk_find_mapped_ns, but
+ *                     operates directly on the passed one.
+ */
+static struct smack_known_ns *__smk_find_mapped(struct smack_known *skp,
+						struct user_namespace *ns)
+{
+	struct smack_known_ns *sknp;
+
+	if (ns == NULL)
+		return NULL;
+
+	list_for_each_entry_rcu(sknp, &skp->smk_mapped, smk_list_known)
+		if (sknp->smk_ns == ns)
+			return sknp;
+
+	return NULL;
+}
+
+/**
+ * smk_find_mapped - Finds a mapped label on the smack_known's mapped list
+ * @skp: a label which mapped label we look for
+ * @ns: a user namespace the label we search for is assigned to
+ *
+ * Returns a pointer to the mapped label if one exists that is
+ * assigned to the specified user namespace or NULL if not found.
+ */
+struct smack_known_ns *smk_find_mapped(struct smack_known *skp,
+				       struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = smk_find_mapped_ns(ns);
+
+	return __smk_find_mapped(skp, user_ns);
+}
+
+/**
+ * __smk_find_unmapped - an internal version of smk_find_unmapped
+ *                       that doesn't use smk_find_mapped_ns, but
+ *                       operates directly on the passed one.
+ */
+static struct smack_known *__smk_find_unmapped(const char *string, int len,
+					       struct user_namespace *ns)
+{
+	struct smack_ns *snsp;
+	struct smack_known *skp = NULL;
+	struct smack_known_ns *sknp;
+	char *smack;
+	bool allocated = false;
+
+	if (ns == NULL)
+		return NULL;
+
+	snsp = ns->security;
+
+	smack = smk_parse_smack(string, len, &allocated);
+	if (IS_ERR(smack))
+		return ERR_CAST(smack);
+
+	list_for_each_entry_rcu(sknp, &snsp->smk_mapped, smk_list_ns) {
+		if (strcmp(smack, sknp->smk_mapped) == 0) {
+			skp = sknp->smk_unmapped;
+			break;
+		}
+	}
+
+	if (allocated)
+		kfree(smack);
+	return skp;
+}
+
+/**
+ * smk_find_unmapped - Finds an original label by a mapped label string
+ *                     and the namespace it could be mapped in
+ * @string: a name of a mapped label we look for
+ * @len: the string size, or zero if it is NULL terminated.
+ * @ns: a namespace the looked for label should be mapped in
+ *
+ * Returns a smack_known label that is mapped as 'string' in 'ns',
+ * NULL if not found or an error code.
+ */
+struct smack_known *smk_find_unmapped(const char *string, int len,
+				      struct user_namespace *ns)
+{
+	struct user_namespace *user_ns = smk_find_mapped_ns(ns);
+
+	return __smk_find_unmapped(string, len, user_ns);
+}
+
+/**
+ * smk_import_mapped - Imports a mapped label effectively creating a mapping.
+ * @skp: a label we map
+ * @ns: a user namespace this label will be mapped in
+ * @string: a text string of the mapped label
+ * @len: the maximum size, or zero if it is NULL terminanted
+ *
+ * Returns a pointer to the mapped label entry or an error code.
+ *
+ * The mapped label will be added to 2 lists:
+ *   - a list of mapped labels of skp
+ *   - a list of labels mapped in ns
+ */
+static struct smack_known_ns *smk_import_mapped(struct smack_known *skp,
+						struct user_namespace *ns,
+						const char *string, int len)
+{
+	struct smack_ns *snsp = ns->security;
+	struct smack_known_ns *sknp;
+	char *mapped;
+	bool allocated;
+
+	/* Mapping init_user_ns is against the design and pointless */
+	if (ns == &init_user_ns)
+		return ERR_PTR(-EBADR);
+
+	mapped = smk_parse_smack(string, len, &allocated);
+	if (IS_ERR(mapped))
+		return ERR_CAST(mapped);
+
+	mutex_lock(&skp->smk_mapped_lock);
+
+	/*
+	 * Don't allow one<->many mappings in namespace, rename.
+	 * This code won't get triggered for now as trying to assign
+	 * a duplicate is forbidden in proc_label_map_write().
+	 * Leaving this as this function might be also used elsewhere.
+	 */
+	sknp = smk_find_mapped(skp, ns);
+	if (sknp != NULL) {
+		if (sknp->smk_allocated)
+			kfree(sknp->smk_mapped);
+		sknp->smk_mapped = mapped;
+		sknp->smk_allocated = allocated;
+		goto unlockout;
+	}
+
+	sknp = kzalloc(sizeof(*sknp), GFP_KERNEL);
+	if (sknp == NULL) {
+		sknp = ERR_PTR(-ENOMEM);
+		if (allocated)
+			kfree(mapped);
+		goto unlockout;
+	}
+
+	sknp->smk_ns = ns;
+	sknp->smk_mapped = mapped;
+	sknp->smk_allocated = allocated;
+	sknp->smk_unmapped = skp;
+	list_add_rcu(&sknp->smk_list_known, &skp->smk_mapped);
+
+	mutex_lock(&snsp->smk_mapped_lock);
+	list_add_rcu(&sknp->smk_list_ns, &snsp->smk_mapped);
+	mutex_unlock(&snsp->smk_mapped_lock);
+
+unlockout:
+	mutex_unlock(&skp->smk_mapped_lock);
+
+	return sknp;
+}
+
+static void *proc_label_map_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct smack_known *skp;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+	loff_t counter = *pos;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list)
+		if (smk_find_mapped(skp, ns) && counter-- == 0)
+			return skp;
+
+	return NULL;
+}
+
+static void proc_label_map_seq_stop(struct seq_file *seq, void *v)
+{
+	rcu_read_unlock();
+}
+
+static void *proc_label_map_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct smack_known *skp = v;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+
+	list_for_each_entry_continue_rcu(skp, &smack_known_list, list) {
+		if (smk_find_mapped(skp, ns)) {
+			(*pos)++;
+			return skp;
+		}
+	}
+
+	return NULL;
+}
+
+static int proc_label_map_seq_show(struct seq_file *seq, void *v)
+{
+	struct smack_known *skp = v;
+	struct task_struct *task = seq->private;
+	struct user_namespace *ns = ns_of_task_struct(task);
+	struct smack_known_ns *sknp;
+
+	sknp = smk_find_mapped(skp, ns);
+	if (sknp)
+		seq_printf(seq, "%s -> %s\n", skp->smk_known, sknp->smk_mapped);
+
+	return 0;
+}
+
+const struct seq_operations proc_label_map_seq_operations = {
+	.start = proc_label_map_seq_start,
+	.stop = proc_label_map_seq_stop,
+	.next = proc_label_map_seq_next,
+	.show = proc_label_map_seq_show,
+};
+
+static DEFINE_MUTEX(smk_map_mutex);
+
+static bool mapping_permitted(const struct cred *f_cred,
+			      struct user_namespace *user_ns)
+{
+	/*
+	 * Do not allow mapping own label. This is in contrast to user
+	 * namespace where you can always map your own UID. In Smack having
+	 * administrative privileges over your own label (which Smack
+	 * namespace would effectively give you) is not equivalent to user
+	 * namespace. E.g. things like setting exec/transmute labels that
+	 * otherwise would be denied. Hence no own_label param here.
+	 */
+
+	/*
+	 * Adjusting namespace settings requires capabilities on the target.
+	 */
+	if (security_capable(f_cred, user_ns, CAP_MAC_ADMIN) != 0)
+		return false;
+
+	/*
+	 * And it requires capabilities in the parent.
+	 *
+	 * If the Smack namespace was properly hierarchical the user_ns to
+	 * check against could be 'user_ns->parent'. Right now because of
+	 * security concerns only privileged initial namespace is allowed
+	 * to fill the map. For a hierarchical namespaces one would
+	 * implement mapping (in the child namespaces) of only mapped labels
+	 * (in parent namespace) and change '&init_user_ns' to
+	 * 'user_ns->parent'. This will be added in the future.
+	 */
+	if (smack_ns_privileged(&init_user_ns, CAP_MAC_ADMIN) &&
+	    security_capable(f_cred, &init_user_ns, CAP_MAC_ADMIN) == 0)
+		return true;
+
+	return false;
+}
+
+ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred,
+			     void *value, size_t size)
+{
+	struct user_namespace *ns = ns_of_task_struct(p);
+	struct user_namespace *cur_ns = ns_of_current();
+	struct smack_known *skp;
+	struct smack_known_ns *sknp;
+	char *pos, *next_line, *tok[2];
+	ssize_t ret;
+	int i;
+
+	/* Mapping labels for the init ns makes no sense */
+	if (ns == &init_user_ns)
+		return -EBADR;
+
+	if (cur_ns != ns->parent)
+		return -EPERM;
+
+	if (!mapping_permitted(f_cred, ns))
+		return -EPERM;
+
+	if (value == NULL || size == 0 || size >= PAGE_SIZE)
+		return -EINVAL;
+
+	mutex_lock(&smk_map_mutex);
+
+	/* Parse the user data */
+	pos = value;
+	pos[size] = '\0';
+
+	for (; pos; pos = next_line) {
+		ret = -EINVAL;
+
+		/* Find the end of line and ensure I don't look past it */
+		next_line = strchr(pos, '\n');
+		if (next_line) {
+			*next_line = '\0';
+			next_line++;
+			if (*next_line == '\0')
+				next_line = NULL;
+		}
+
+		/* Find tokens in line */
+		for (i = 0; i < 2; ++i) {
+			while (isspace(*pos))
+				*(pos++) = '\0';
+
+			/* unexpected end of file */
+			if (*pos == '\0')
+				goto out;
+
+			tok[i] = pos;
+
+			/* find the end of the token */
+			while (*pos != '\0' && !isspace(*pos))
+				++pos;
+		}
+
+		/* NUL terminate the last token if not EOL */
+		while (isspace(*pos))
+			*(pos++) = '\0';
+
+		/* there should not be any trailing data */
+		if (*pos != '\0')
+			goto out;
+
+		ret = -EEXIST;
+
+		/* do not allow to map 2 different labels to one name */
+		skp = __smk_find_unmapped(tok[1], 0, ns);
+		if (IS_ERR(skp)) {
+			ret = PTR_ERR(skp);
+			goto out;
+		}
+		if (skp != NULL)
+			goto out;
+
+		skp = smk_import_entry(tok[0], 0);
+		if (IS_ERR(skp)) {
+			ret = PTR_ERR(skp);
+			goto out;
+		}
+
+		/* do not allow remapping */
+		if (__smk_find_mapped(skp, ns))
+			goto out;
+
+		sknp = smk_import_mapped(skp, ns, tok[1], 0);
+		if (IS_ERR(sknp)) {
+			ret = PTR_ERR(sknp);
+			goto out;
+		}
+	}
+
+	ret = size;
+
+out:
+	mutex_unlock(&smk_map_mutex);
+
+	return ret;
+}
-- 
2.4.3


  parent reply	other threads:[~2015-10-14 12:42 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-14 12:41 [PATCH v4 00/11] Smack namespace Lukasz Pawelczyk
2015-10-14 12:41 ` Lukasz Pawelczyk
2015-10-14 12:41 ` [PATCH v4 01/11] user_ns: 3 new LSM hooks for user namespace operations Lukasz Pawelczyk
2015-10-14 12:41 ` [PATCH v4 02/11] lsm: /proc/$PID/attr/label_map file and getprocattr_seq hook Lukasz Pawelczyk
2015-10-14 12:41 ` [PATCH v4 03/11] lsm: add file opener's cred to a setprocattr arguments Lukasz Pawelczyk
2015-10-14 12:41 ` [PATCH v4 04/11] lsm: inode_pre_setxattr hook Lukasz Pawelczyk
2015-10-29 22:50   ` Casey Schaufler
     [not found]   ` <1444826525-9758-5-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:50     ` Casey Schaufler
2015-11-05  5:16     ` John Johansen
2015-10-29 22:50   ` Casey Schaufler
2015-11-05  5:16   ` John Johansen
2015-11-05  5:16   ` John Johansen
2015-10-14 12:41 ` Lukasz Pawelczyk
2015-10-14 12:41 ` [PATCH v4 05/11] smack: extend capability functions and fix 2 checks Lukasz Pawelczyk
     [not found] ` <1444826525-9758-1-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-14 12:41   ` [PATCH v4 01/11] user_ns: 3 new LSM hooks for user namespace operations Lukasz Pawelczyk
2015-10-14 12:41     ` Lukasz Pawelczyk
     [not found]     ` <1444826525-9758-2-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:49       ` Casey Schaufler
2015-10-29 22:49     ` Casey Schaufler
2015-10-29 22:49     ` Casey Schaufler
2015-10-14 12:41   ` [PATCH v4 02/11] lsm: /proc/$PID/attr/label_map file and getprocattr_seq hook Lukasz Pawelczyk
2015-10-14 12:41     ` Lukasz Pawelczyk
2015-10-29 22:49     ` Casey Schaufler
2015-10-29 22:49     ` Casey Schaufler
     [not found]     ` <1444826525-9758-3-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:49       ` Casey Schaufler
2015-10-14 12:41   ` [PATCH v4 03/11] lsm: add file opener's cred to a setprocattr arguments Lukasz Pawelczyk
2015-10-14 12:41     ` Lukasz Pawelczyk
2015-10-29 22:49     ` Casey Schaufler
     [not found]     ` <1444826525-9758-4-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:49       ` Casey Schaufler
2015-10-29 22:49         ` Casey Schaufler
2015-11-10  4:16       ` Al Viro
2015-11-10  4:16     ` Al Viro
2015-11-10  4:16       ` Al Viro
     [not found]       ` <20151110041625.GA19875-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2015-11-10 10:15         ` Lukasz Pawelczyk
2015-11-10 10:15           ` Lukasz Pawelczyk
2015-11-10 10:15           ` Lukasz Pawelczyk
2015-10-14 12:41   ` [PATCH v4 04/11] lsm: inode_pre_setxattr hook Lukasz Pawelczyk
2015-10-14 12:41   ` [PATCH v4 05/11] smack: extend capability functions and fix 2 checks Lukasz Pawelczyk
2015-10-14 12:41     ` Lukasz Pawelczyk
2015-10-29 22:50     ` Casey Schaufler
2015-10-29 22:50     ` Casey Schaufler
     [not found]     ` <1444826525-9758-6-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:50       ` Casey Schaufler
2015-10-14 12:42   ` [PATCH v4 06/11] smack: don't use implicit star to display smackfs/syslog Lukasz Pawelczyk
2015-10-14 12:42   ` [PATCH v4 07/11] smack: abstraction layer for 2 common Smack operations Lukasz Pawelczyk
2015-10-14 12:42     ` Lukasz Pawelczyk
2015-10-29 22:51     ` Casey Schaufler
     [not found]     ` <1444826525-9758-8-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:51       ` Casey Schaufler
2015-10-29 22:51         ` Casey Schaufler
2015-10-14 12:42   ` [PATCH v4 08/11] smack: misc cleanups in preparation for a namespace patch Lukasz Pawelczyk
2015-10-14 12:42   ` Lukasz Pawelczyk [this message]
2015-10-14 12:42     ` [PATCH v4 09/11] smack: namespace groundwork Lukasz Pawelczyk
     [not found]     ` <1444826525-9758-10-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:51       ` Casey Schaufler
2015-10-29 22:51     ` Casey Schaufler
2015-10-29 22:51     ` Casey Schaufler
2015-10-14 12:42   ` [PATCH v4 10/11] smack: namespace implementation Lukasz Pawelczyk
2015-10-14 12:42   ` [PATCH v4 11/11] smack: documentation for the Smack namespace Lukasz Pawelczyk
2015-10-14 12:42     ` Lukasz Pawelczyk
     [not found]     ` <1444826525-9758-12-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:52       ` Casey Schaufler
2015-10-29 22:52         ` Casey Schaufler
2015-10-29 22:52     ` Casey Schaufler
2015-11-09 15:40   ` [PATCH v4 00/11] " Lukasz Pawelczyk
2015-11-09 15:40     ` Lukasz Pawelczyk
2015-10-14 12:42 ` [PATCH v4 06/11] smack: don't use implicit star to display smackfs/syslog Lukasz Pawelczyk
     [not found]   ` <1444826525-9758-7-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:50     ` Casey Schaufler
2015-10-29 22:50       ` Casey Schaufler
2015-10-29 22:50   ` Casey Schaufler
2015-10-14 12:42 ` Lukasz Pawelczyk
2015-10-14 12:42 ` [PATCH v4 07/11] smack: abstraction layer for 2 common Smack operations Lukasz Pawelczyk
2015-10-14 12:42 ` [PATCH v4 08/11] smack: misc cleanups in preparation for a namespace patch Lukasz Pawelczyk
2015-10-14 12:42   ` Lukasz Pawelczyk
2015-10-29 22:51   ` Casey Schaufler
     [not found]   ` <1444826525-9758-9-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:51     ` Casey Schaufler
2015-10-29 22:51       ` Casey Schaufler
2015-10-14 12:42 ` [PATCH v4 09/11] smack: namespace groundwork Lukasz Pawelczyk
2015-10-14 12:42 ` [PATCH v4 10/11] smack: namespace implementation Lukasz Pawelczyk
2015-10-14 12:42 ` Lukasz Pawelczyk
     [not found]   ` <1444826525-9758-11-git-send-email-l.pawelczyk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-10-29 22:52     ` Casey Schaufler
2015-10-29 22:52       ` Casey Schaufler
2015-10-29 22:52   ` Casey Schaufler
2015-10-14 12:42 ` [PATCH v4 11/11] smack: documentation for the Smack namespace Lukasz Pawelczyk
2015-11-09 15:40 ` [PATCH v4 00/11] " Lukasz Pawelczyk
     [not found] <019801d1071b$2c124000$8436c000$@alibaba-inc.com>
2015-10-15  7:38 ` [PATCH v4 09/11] smack: namespace groundwork Hillf Danton
2015-10-15 12:41   ` Lukasz Pawelczyk
2015-10-15 12:53     ` Lukasz Pawelczyk
2015-10-16  3:04       ` Hillf Danton
2015-10-16 10:13         ` Lukasz Pawelczyk

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=1444826525-9758-10-git-send-email-l.pawelczyk@samsung.com \
    --to=l.pawelczyk-sze3o3uu22jbdgjk7y7tuq@public.gmane.org \
    --cc=adobriyan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=calvinowens-b10kYP2dOMg@public.gmane.org \
    --cc=casey-iSGtlc1asvQWG2LlvL+J4A@public.gmane.org \
    --cc=corbet-T1hC0tSOHrs@public.gmane.org \
    --cc=davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org \
    --cc=dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org \
    --cc=edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=eparis-FjpueFixGhCM4zKIHC2jIg@public.gmane.org \
    --cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
    --cc=havner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=james.l.morris-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org \
    --cc=jann-XZ1E9jl8jIdeoWH0uzbU5w@public.gmane.org \
    --cc=joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org \
    --cc=john.johansen-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org \
    --cc=jslaby-IBi9RG/b67k@public.gmane.org \
    --cc=keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
    --cc=luto-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org \
    --cc=neilb-l3A5Bk7waGM@public.gmane.org \
    --cc=serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org \
    --cc=viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.