lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Tue, 29 Sep 2015 15:46:17 +0200
From:	Zbigniew Jasinski <z.jasinski@...sung.com>
To:	Casey Schaufler <casey@...aufler-ca.com>,
	Jonathan Corbet <corbet@....net>,
	James Morris <james.l.morris@...cle.com>,
	"Serge E. Hallyn" <serge@...lyn.com>,
	linux-security-module@...r.kernel.org,
	linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org
Cc:	Rafal Krypa <r.krypa@...sung.com>,
	Tomasz Swierczek <t.swierczek@...sung.com>
Subject: [PATCH v2 2/2] Add new interface 'relabel-list' to smackfs

This list is used to control smack label transition mechanism.
Process can transit to new label only if label is on the list.
Only process with CAP_MAC_ADMIN capability can add label to this list.

Changes in v2:
* use list_for_each_entry instead of _rcu during label write
* added missing description in security/Smack.txt

Signed-off-by: Zbigniew Jasinski <z.jasinski@...sung.com>
Signed-off-by: Rafal Krypa <r.krypa@...sung.com>
---
 Documentation/security/Smack.txt |  13 ++++
 security/smack/smack.h           |   8 +++
 security/smack/smack_lsm.c       |  17 +++++
 security/smack/smackfs.c         | 147 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt
index 5e6d07f..0ffd194 100644
--- a/Documentation/security/Smack.txt
+++ b/Documentation/security/Smack.txt
@@ -255,6 +255,19 @@ unconfined
 	the access permitted if it wouldn't be otherwise. Note that this
 	is dangerous and can ruin the proper labeling of your system.
 	It should never be used in production.
+relabel-possible
+	This interface is used to set relabel-possible flag. A process
+	with this flag is able to change its label without CAP_MAC_ADMIN,
+	but only once. After label transition this flag is zeroed.
+	0 - default: process is not allowed to label transition
+	1 - process is allowed to one-time label tranistion
+relabel-list
+	This interface contains a list of labels, in which process can
+	transition to. The format accepted on write is:
+                "%s"
+	for adding label, and:
+		"-%s"
+	for removing label from list.
 
 If you are using the smackload utility
 you can add access rules in /etc/smack/accesses. They take the form:
diff --git a/security/smack/smack.h b/security/smack/smack.h
index d17580e..db4a1a3 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -193,6 +193,12 @@ enum {
 	Opt_fstransmute = 5,
 };
 
+struct smack_relabel {
+	struct rcu_head         rcu;
+	struct list_head	list;
+	struct smack_known	*smk_label;
+};
+
 /*
  * Mount options
  */
@@ -333,6 +339,8 @@ extern struct list_head smk_net6addr_list;
 extern struct mutex     smack_onlycap_lock;
 extern struct list_head smack_onlycap_list;
 
+extern struct list_head smack_relabel_list;
+
 #define SMACK_HASH_SLOTS 16
 extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
 
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0766a4b..596f270 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -66,6 +66,8 @@ static const match_table_t smk_mount_tokens = {
 	{Opt_error, NULL},
 };
 
+LIST_HEAD(smack_relabel_list);
+
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
 static char *smk_bu_mess[] = {
 	"Bringup Error",	/* Unused */
@@ -3554,6 +3556,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
 	struct task_smack *tsp = current_security();
 	struct cred *new;
 	struct smack_known *skp;
+	struct smack_relabel *srp;
+	int rc;
 
 	/*
 	 * Changing another process' Smack value is too dangerous
@@ -3581,6 +3585,19 @@ static int smack_setprocattr(struct task_struct *p, char *name,
 	if (skp == &smack_known_web)
 		return -EPERM;
 
+	if (tsp->smk_relabel) {
+		rc = -EPERM;
+		rcu_read_lock();
+		list_for_each_entry_rcu(srp, &smack_relabel_list, list)
+			if (srp->smk_label == skp) {
+				rc = 0;
+				break;
+			}
+		rcu_read_unlock();
+		if (rc)
+			return rc;
+	}
+
 	new = prepare_creds();
 	if (new == NULL)
 		return -ENOMEM;
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 18c1b934..11012f1 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -62,6 +62,7 @@ enum smk_inos {
 	SMK_NET6ADDR	= 23,	/* single label IPv6 hosts */
 #endif /* CONFIG_IPV6 */
 	SMK_RELABEL_POSSIBLE = 24, /* relabel possible without CAP_MAC_ADMIN */
+	SMK_RELABEL_LIST = 25,
 };
 
 /*
@@ -73,6 +74,7 @@ static DEFINE_MUTEX(smk_net4addr_lock);
 #if IS_ENABLED(CONFIG_IPV6)
 static DEFINE_MUTEX(smk_net6addr_lock);
 #endif /* CONFIG_IPV6 */
+static DEFINE_MUTEX(smack_relabel_list_lock);
 
 /*
  * This is the "ambient" label for network traffic.
@@ -2770,6 +2772,148 @@ static const struct file_operations smk_relabel_possible_ops = {
 	.llseek		= default_llseek,
 };
 
+/*
+ * Seq_file read operations for /smack/relabel-list
+ */
+
+static void *relabel_list_seq_start(struct seq_file *s, loff_t *pos)
+{
+	return smk_seq_start(s, pos, &smack_relabel_list);
+}
+
+static void *relabel_list_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	return smk_seq_next(s, v, pos, &smack_relabel_list);
+}
+
+static int relabel_list_seq_show(struct seq_file *s, void *v)
+{
+	struct list_head *list = v;
+	struct smack_relabel *srp =
+		list_entry_rcu(list, struct smack_relabel, list);
+
+	seq_printf(s, "%s\n", srp->smk_label->smk_known);
+
+	return 0;
+}
+
+static const struct seq_operations relabel_list_seq_ops = {
+	.start = relabel_list_seq_start,
+	.next  = relabel_list_seq_next,
+	.show  = relabel_list_seq_show,
+	.stop  = smk_seq_stop,
+};
+
+/**
+ * smk_open_relabel_list - open() for /smack/relabel-list
+ * @inode: inode structure representing file
+ * @file: "relabel-list" file pointer
+ *
+ * For reading, use load2_seq_* seq_file reading operations.
+ */
+static int smk_open_relabel_list(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &relabel_list_seq_ops);
+}
+
+/**
+ * smk_write_relabel_list - write() for /smack/relabel-list
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ *
+ */
+static ssize_t smk_write_relabel_list(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct smack_known *skp;
+	struct smack_relabel *srp;
+	int rc = count;
+	int remove;
+	char *data;
+	char *label;
+
+	/*
+	 * Must have privilege.
+	 */
+	if (!smack_privileged(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	/*
+	 * Enough data must be present.
+	 * One label per line.
+	 */
+	if (*ppos != 0 || count >= SMK_LONGLABEL)
+		return -EINVAL;
+
+	data = kzalloc(count + 1, GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(data, buf, count) != 0) {
+		kfree(data);
+		return -EFAULT;
+	}
+
+	if (data[0] == '-') {
+		remove = 1;
+		label = smk_parse_smack(data + 1, count - 1);
+		if (IS_ERR(label)) {
+			kfree(data);
+			return PTR_ERR(label);
+		}
+		skp = smk_find_entry(label);
+		kfree(label);
+	} else {
+		remove = 0;
+		skp = smk_import_entry(data, count);
+	}
+	kfree(data);
+
+	if (IS_ERR(skp))
+		return PTR_ERR(skp);
+
+	mutex_lock(&smack_relabel_list_lock);
+	list_for_each_entry(srp, &smack_relabel_list, list)
+		if (srp->smk_label == skp) {
+			if (remove) {
+				list_del_rcu(&srp->list);
+				mutex_unlock(&smack_relabel_list_lock);
+				kfree_rcu(srp, rcu);
+				return rc;
+			} else
+				goto out;
+		}
+
+	/* Entry not found on smack_relabel_list */
+	if (remove) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	srp = kzalloc(sizeof(*srp), GFP_KERNEL);
+	if (srp == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	srp->smk_label = skp;
+	list_add_rcu(&srp->list, &smack_relabel_list);
+
+out:
+	mutex_unlock(&smack_relabel_list_lock);
+	return rc;
+}
+
+static const struct file_operations smk_relabel_list_ops = {
+	.open           = smk_open_relabel_list,
+	.read		= seq_read,
+	.llseek         = seq_lseek,
+	.write		= smk_write_relabel_list,
+	.release        = seq_release,
+};
+
 /**
  * smk_read_ptrace - read() for /smack/ptrace
  * @filp: file pointer, not actually used
@@ -2898,6 +3042,9 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
 		[SMK_RELABEL_POSSIBLE] = {
 			"relabel-possible", &smk_relabel_possible_ops,
 				S_IRUGO|S_IWUGO},
+		[SMK_RELABEL_LIST] = {
+			"relabel-list", &smk_relabel_list_ops,
+				S_IRUGO|S_IWUGO},
 		/* last one */
 			{""}
 	};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ