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>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <49A242C6.1000400@numericable.fr>
Date:	Mon, 23 Feb 2009 07:31:34 +0100
From:	etienne <etienne.basset@...ericable.fr>
To:	Casey Schaufler <casey@...aufler-ca.com>
CC:	Paul Moore <paul.moore@...com>,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
	LSM <linux-security-module@...r.kernel.org>,
	paulmck@...ux.vnet.ibm.com
Subject: Re: [PATCH][SMACK] convert smack_known list to a standard linux list.

Casey Schaufler wrote:
> etienne wrote:
>> hello,
>>
>> this patch on top of [PATCH][SMACK] convert smack rule list to linux list V2
>> converts "smack_known" to a regular linux list. (rcu variant)
>>
>>   
> 
> I'm having some trouble applying this group of patches.
> I assume that I'm starting at the wrong place. Could you
> do a single patch to help me avoid confusion?
> 
> Thank you.
> 
>> regards,
>> Etienne
>>
>> Signed-off-by: <etienne.basset@...ericable.fr>
>> ---
>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>> index 0dcb907..64164f8 100644
>> --- a/security/smack/smack.h
>> +++ b/security/smack/smack.h
>> @@ -109,7 +109,6 @@ struct smk_netlbladdr {
>>   */
>>  
> 
> 
> 

here you are!
(it is still on top of my 02/20 "[PATCH] SMACK netlabel fixes v2")

happy testing ;)
Etienne

Signed-off-by: <etienne.basset@...ericable.fr>
---
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b79582e..64164f8 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -18,6 +18,8 @@
 #include <linux/security.h>
 #include <linux/in.h>
 #include <net/netlabel.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
 
 /*
  * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -59,17 +61,10 @@ struct inode_smack {
  * A label access rule.
  */
 struct smack_rule {
-	char	*smk_subject;
-	char	*smk_object;
-	int	smk_access;
-};
-
-/*
- * An entry in the table of permitted label accesses.
- */
-struct smk_list_entry {
-	struct smk_list_entry	*smk_next;
-	struct smack_rule	smk_rule;
+	struct list_head	list;
+	char			*smk_subject;
+	char			*smk_object;
+	int			smk_access;
 };
 
 /*
@@ -85,7 +80,7 @@ struct smack_cipso {
  * An entry in the table identifying hosts.
  */
 struct smk_netlbladdr {
-	struct smk_netlbladdr	*smk_next;
+	struct list_head	list;
 	struct sockaddr_in	smk_host;	/* network address */
 	struct in_addr		smk_mask;	/* network mask */
 	char			*smk_label;	/* label */
@@ -113,7 +108,7 @@ struct smk_netlbladdr {
  * the cipso direct mapping in used internally.
  */
 struct smack_known {
-	struct smack_known	*smk_next;
+	struct list_head	list;
 	char			smk_known[SMK_LABELLEN];
 	u32			smk_secid;
 	struct smack_cipso	*smk_cipso;
@@ -206,7 +201,6 @@ extern int smack_cipso_direct;
 extern char *smack_net_ambient;
 extern char *smack_onlycap;
 
-extern struct smack_known *smack_known;
 extern struct smack_known smack_known_floor;
 extern struct smack_known smack_known_hat;
 extern struct smack_known smack_known_huh;
@@ -214,8 +208,10 @@ extern struct smack_known smack_known_invalid;
 extern struct smack_known smack_known_star;
 extern struct smack_known smack_known_web;
 
-extern struct smk_list_entry *smack_list;
-extern struct smk_netlbladdr *smack_netlbladdrs;
+extern struct list_head smack_known_list;
+extern struct list_head smack_rule_list;
+extern struct list_head smk_netlbladdr_list;
+
 extern struct security_operations smack_ops;
 
 /*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 2e0b83e..b16086f 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -16,48 +16,42 @@
 #include "smack.h"
 
 struct smack_known smack_known_huh = {
-	.smk_next	= NULL,
 	.smk_known	= "?",
 	.smk_secid	= 2,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_hat = {
-	.smk_next	= &smack_known_huh,
 	.smk_known	= "^",
 	.smk_secid	= 3,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_star = {
-	.smk_next	= &smack_known_hat,
 	.smk_known	= "*",
 	.smk_secid	= 4,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_floor = {
-	.smk_next	= &smack_known_star,
 	.smk_known	= "_",
 	.smk_secid	= 5,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_invalid = {
-	.smk_next	= &smack_known_floor,
 	.smk_known	= "",
 	.smk_secid	= 6,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_web = {
-	.smk_next	= &smack_known_invalid,
 	.smk_known	= "@",
 	.smk_secid	= 7,
 	.smk_cipso	= NULL,
 };
 
-struct smack_known *smack_known = &smack_known_web;
+LIST_HEAD(smack_known_list);
 
 /*
  * The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
 int smk_access(char *subject_label, char *object_label, int request)
 {
 	u32 may = MAY_NOT;
-	struct smk_list_entry *sp;
 	struct smack_rule *srp;
 
 	/*
@@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
 	 * access (e.g. read is included in readwrite) it's
 	 * good.
 	 */
-	for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
-		srp = &sp->smk_rule;
-
+	rcu_read_lock();
+	list_for_each_entry_rcu(srp, &smack_rule_list, list) {
 		if (srp->smk_subject == subject_label ||
 		    strcmp(srp->smk_subject, subject_label) == 0) {
 			if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
 			}
 		}
 	}
+	rcu_read_unlock();
 	/*
 	 * This is a bit map operation.
 	 */
@@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
 
 	mutex_lock(&smack_known_lock);
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
+	found = 0;
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
+			found = 1;
 			break;
+		}
+	}
 
-	if (skp == NULL) {
+	if (found == 0) {
 		skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
 		if (skp != NULL) {
-			skp->smk_next = smack_known;
 			strncpy(skp->smk_known, smack, SMK_MAXLEN);
 			skp->smk_secid = smack_next_secid++;
 			skp->smk_cipso = NULL;
@@ -245,7 +241,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
 			 * filled before putting it on the list.
 			 */
 			smp_mb();
-			smack_known = skp;
+			list_add(&skp->list, &smack_known_list);
 		}
 	}
 
@@ -283,14 +279,19 @@ char *smack_from_secid(const u32 secid)
 {
 	struct smack_known *skp;
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (skp->smk_secid == secid)
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (skp->smk_secid == secid) {
+			rcu_read_unlock();
 			return skp->smk_known;
+		}
+	}
 
 	/*
 	 * If we got this far someone asked for the translation
 	 * of a secid that is not on the list.
 	 */
+	rcu_read_unlock();
 	return smack_known_invalid.smk_known;
 }
 
@@ -305,9 +306,14 @@ u32 smack_to_secid(const char *smack)
 {
 	struct smack_known *skp;
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
+			rcu_read_unlock();
 			return skp->smk_secid;
+		}
+	}
+	rcu_read_unlock();
 	return 0;
 }
 
@@ -332,7 +338,8 @@ void smack_from_cipso(u32 level, char *cp, char *result)
 	struct smack_known *kp;
 	char *final = NULL;
 
-	for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) {
+	rcu_read_lock();
+	list_for_each_entry(kp, &smack_known_list, list) {
 		if (kp->smk_cipso == NULL)
 			continue;
 
@@ -344,6 +351,7 @@ void smack_from_cipso(u32 level, char *cp, char *result)
 
 		spin_unlock_bh(&kp->smk_cipsolock);
 	}
+	rcu_read_unlock();
 	if (final == NULL)
 		final = smack_known_huh.smk_known;
 	strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +368,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
 int smack_to_cipso(const char *smack, struct smack_cipso *cp)
 {
 	struct smack_known *kp;
+	int found = 0;
 
-	for (kp = smack_known; kp != NULL; kp = kp->smk_next)
+	rcu_read_lock();
+	list_for_each_entry_rcu(kp, &smack_known_list, list) {
 		if (kp->smk_known == smack ||
-		    strcmp(kp->smk_known, smack) == 0)
+		    strcmp(kp->smk_known, smack) == 0) {
+			found = 1;
 			break;
+		}
+	}
+	rcu_read_unlock();
 
-	if (kp == NULL || kp->smk_cipso == NULL)
+	if (found == 0 || kp->smk_cipso == NULL)
 		return -ENOENT;
 
 	memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e7ded13..e6f89d6 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1509,8 +1509,8 @@ static char *smack_host_label(struct sockaddr_in *sip)
 
 	if (siap->s_addr == 0)
 		return NULL;
-
-	for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
 		/*
 		 * we break after finding the first match because
 		 * the list is sorted from longest to shortest mask
@@ -1518,10 +1518,11 @@ static char *smack_host_label(struct sockaddr_in *sip)
 		 */
 		if ((&snp->smk_host.sin_addr)->s_addr  ==
 			(siap->s_addr & (&snp->smk_mask)->s_addr)) {
+			rcu_read_unlock();
 			return snp->smk_label;
 		}
 	}
-
+	rcu_read_unlock();
 	return NULL;
 }
 
@@ -2934,6 +2935,17 @@ struct security_operations smack_ops = {
 	.release_secctx = 		smack_release_secctx,
 };
 
+
+static __init init_smack_know_list(void)
+{
+	list_add(&smack_known_huh.list, &smack_known_list);
+	list_add(&smack_known_hat.list, &smack_known_list);
+	list_add(&smack_known_star.list, &smack_known_list);
+	list_add(&smack_known_floor.list, &smack_known_list);
+	list_add(&smack_known_invalid.list, &smack_known_list);
+	list_add(&smack_known_web.list, &smack_known_list);
+}
+
 /**
  * smack_init - initialize the smack system
  *
@@ -2954,6 +2966,8 @@ static __init int smack_init(void)
 	cred = (struct cred *) current->cred;
 	cred->security = &smack_known_floor.smk_known;
 
+	/* initilize the smack_know_list */
+	init_smack_know_list();
 	/*
 	 * Initialize locks
 	 */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 51f0efc..665e2cc 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -80,10 +80,11 @@ char *smack_onlycap;
  * Packets are sent there unlabeled, but only from tasks that
  * can write to the specified label.
  */
-struct smk_netlbladdr *smack_netlbladdrs;
+
+LIST_HEAD(smk_netlbladdr_list);
+LIST_HEAD(smack_rule_list);
 
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
-struct smk_list_entry *smack_list;
 
 #define	SEQ_READ_FINISHED	1
 
@@ -134,24 +135,27 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
-
-	return smack_list;
+	if (list_empty(&smack_rule_list))
+		return NULL;
+	return &smack_rule_list;
 }
 
 static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next;
+	struct list_head *list = v;
 
-	if (skp == NULL)
+	if (list_is_last(list->next, &smack_rule_list)) {
 		*pos = SEQ_READ_FINISHED;
-
-	return skp;
+		return NULL;
+	}
+	return list->next;
 }
 
 static int load_seq_show(struct seq_file *s, void *v)
 {
-	struct smk_list_entry *slp = (struct smk_list_entry *) v;
-	struct smack_rule *srp = &slp->smk_rule;
+	struct list_head *list = v;
+	struct smack_rule *srp =
+		 container_of(list->next, struct smack_rule, list);
 
 	seq_printf(s, "%s %s", (char *)srp->smk_subject,
 		   (char *)srp->smk_object);
@@ -212,32 +216,23 @@ static int smk_open_load(struct inode *inode, struct file *file)
  */
 static int smk_set_access(struct smack_rule *srp)
 {
-	struct smk_list_entry *sp;
-	struct smk_list_entry *newp;
+	struct smack_rule *sp;
 	int ret = 0;
-
+	int found;
 	mutex_lock(&smack_list_lock);
 
-	for (sp = smack_list; sp != NULL; sp = sp->smk_next)
-		if (sp->smk_rule.smk_subject == srp->smk_subject &&
-		    sp->smk_rule.smk_object == srp->smk_object) {
-			sp->smk_rule.smk_access = srp->smk_access;
+	found = 0;
+	list_for_each_entry_rcu(sp, &smack_rule_list, list) {
+		if (sp->smk_subject == srp->smk_subject &&
+		    sp->smk_object == srp->smk_object) {
+			found = 1;
+			sp->smk_access = srp->smk_access;
 			break;
 		}
-
-	if (sp == NULL) {
-		newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
-		if (newp == NULL) {
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		newp->smk_rule = *srp;
-		newp->smk_next = smack_list;
-		smack_list = newp;
 	}
+	if (found == 0)
+		list_add_rcu(&srp->list, &smack_rule_list);
 
-out:
 	mutex_unlock(&smack_list_lock);
 
 	return ret;
@@ -261,7 +256,7 @@ out:
 static ssize_t smk_write_load(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos)
 {
-	struct smack_rule rule;
+	struct smack_rule *rule;
 	char *data;
 	int rc = -EINVAL;
 
@@ -272,9 +267,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 	 */
 	if (!capable(CAP_MAC_ADMIN))
 		return -EPERM;
-	if (*ppos != 0)
-		return -EINVAL;
-	if (count != SMK_LOADLEN)
+
+	if (*ppos != 0 || count != SMK_LOADLEN)
 		return -EINVAL;
 
 	data = kzalloc(count, GFP_KERNEL);
@@ -286,25 +280,31 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 		goto out;
 	}
 
-	rule.smk_subject = smk_import(data, 0);
-	if (rule.smk_subject == NULL)
+	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
+	if (rule == NULL) {
+		rc = -ENOMEM;
 		goto out;
+	}
 
-	rule.smk_object = smk_import(data + SMK_LABELLEN, 0);
-	if (rule.smk_object == NULL)
-		goto out;
+	rule->smk_subject = smk_import(data, 0);
+	if (rule->smk_subject == NULL)
+		goto out_free;
 
-	rule.smk_access = 0;
+	rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
+	if (rule->smk_object == NULL)
+		goto out_free;
+
+	rule->smk_access = 0;
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
 	case '-':
 		break;
 	case 'r':
 	case 'R':
-		rule.smk_access |= MAY_READ;
+		rule->smk_access |= MAY_READ;
 		break;
 	default:
-		goto out;
+		goto out_free;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
@@ -312,10 +312,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 		break;
 	case 'w':
 	case 'W':
-		rule.smk_access |= MAY_WRITE;
+		rule->smk_access |= MAY_WRITE;
 		break;
 	default:
-		goto out;
+		goto out_free;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
@@ -323,10 +323,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 		break;
 	case 'x':
 	case 'X':
-		rule.smk_access |= MAY_EXEC;
+		rule->smk_access |= MAY_EXEC;
 		break;
 	default:
-		goto out;
+		goto out_free;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
@@ -334,17 +334,20 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 		break;
 	case 'a':
 	case 'A':
-		rule.smk_access |= MAY_APPEND;
+		rule->smk_access |= MAY_APPEND;
 		break;
 	default:
-		goto out;
+		goto out_free;
 	}
 
-	rc = smk_set_access(&rule);
+	rc = smk_set_access(rule);
 
 	if (!rc)
 		rc = count;
+	goto out;
 
+out_free:
+	kfree(rule);
 out:
 	kfree(data);
 	return rc;
@@ -432,24 +435,26 @@ static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
+	if (list_empty(&smack_known_list))
+		return NULL;
 
-	return smack_known;
+	return &smack_known_list;
 }
 
 static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smack_known *skp = ((struct smack_known *) v)->smk_next;
+	struct list_head  *list = v;
 
 	/*
-	 * Omit labels with no associated cipso value
+	 * labels with no associated cipso value wont be printed
+	 * in cipso_seq_show
 	 */
-	while (skp != NULL && !skp->smk_cipso)
-		skp = skp->smk_next;
-
-	if (skp == NULL)
+	if (list_is_last(list->next, &smack_known_list)) {
 		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
 
-	return skp;
+	return list->next;
 }
 
 /*
@@ -458,7 +463,8 @@ static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
  */
 static int cipso_seq_show(struct seq_file *s, void *v)
 {
-	struct smack_known *skp = (struct smack_known *) v;
+	struct list_head  *list = v;
+	struct smack_known *skp = container_of(list->next, struct smack_known, list);
 	struct smack_cipso *scp = skp->smk_cipso;
 	char *cbp;
 	char sep = '/';
@@ -637,18 +643,21 @@ static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
-
-	return smack_netlbladdrs;
+	if (list_empty(&smk_netlbladdr_list))
+		return NULL;
+	return &smk_netlbladdr_list;
 }
 
 static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
-
-	if (skp == NULL)
+	struct list_head *list = v;
+	
+	if (list_is_last(list->next, &smk_netlbladdr_list)) {
 		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
 
-	return skp;
+	return list->next;
 }
 #define BEBITS	(sizeof(__be32) * 8)
 
@@ -657,7 +666,8 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
  */
 static int netlbladdr_seq_show(struct seq_file *s, void *v)
 {
-	struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
+	struct list_head *list = v;
+	struct smk_netlbladdr *skp = container_of(list->next, struct smk_netlbladdr, list);
 	unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
 	int maskn;
 	u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -701,33 +711,37 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
  *
  * This helper insert netlabel in the smack_netlbladdrs list
  * sorted by netmask length (longest to smallest)
+ * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
+ *
  */
 static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
 {
-	struct smk_netlbladdr *m;
+	struct smk_netlbladdr *m, *m_next;
 
-	if (smack_netlbladdrs == NULL) {
-		smack_netlbladdrs = new;
-		return;
-	}
+        if (list_empty(&smk_netlbladdr_list)) {
+                list_add_rcu(&new->list, &smk_netlbladdr_list);
+                return;
+        }
 
 	/* the comparison '>' is a bit hacky, but works */
-	if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
-		new->smk_next = smack_netlbladdrs;
-		smack_netlbladdrs = new;
-		return;
-	}
-	for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
-		if (m->smk_next == NULL) {
-			m->smk_next = new;
-			return;
-		}
-		if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
-			new->smk_next = m->smk_next;
-			m->smk_next = new;
-			return;
-		}
-	}
+	m = container_of(rcu_dereference(smk_netlbladdr_list.next), struct smk_netlbladdr, list);
+
+        if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
+                list_add_rcu(&new->list, &smk_netlbladdr_list);
+                return;
+        }
+
+	list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
+                if (list_is_last(&m->list, &smk_netlbladdr_list)) {
+                        list_add_rcu(&new->list, &m->list);
+                        return;
+                }
+                m_next = container_of(rcu_dereference(m->list.next), struct smk_netlbladdr, list);
+                if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
+                        list_add_rcu(&new->list, &m->list);
+                        return;
+                }
+        }
 }
 
 
@@ -754,6 +768,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 	struct netlbl_audit audit_info;
 	struct in_addr mask;
 	unsigned int m;
+	int found;
 	u32 mask_bits = (1<<31);
 	__be32 nsa;
 	u32 temp_mask;
@@ -807,14 +822,18 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 
 	nsa = newname.sin_addr.s_addr;
 	/* try to find if the prefix is already in the list */
-	for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
+	found = 0;
+	list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
 		if (skp->smk_host.sin_addr.s_addr == nsa &&
-		    skp->smk_mask.s_addr == mask.s_addr)
-			break;
+		    skp->smk_mask.s_addr == mask.s_addr) {
+			found = 1;
+			break;	
+		}
+	}
 
 	smk_netlabel_audit_set(&audit_info);
 
-	if (skp == NULL) {
+	if (!found) {
 		skp = kzalloc(sizeof(*skp), GFP_KERNEL);
 		if (skp == NULL)
 			rc = -ENOMEM;
--
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