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] [day] [month] [year] [list]
Date:	Thu, 26 Mar 2009 09:18:35 +1100 (EST)
From:	James Morris <jmorris@...ei.org>
To:	Casey Schaufler <casey@...aufler-ca.com>
cc:	Etienne Basset <etienne.basset@...ericable.fr>,
	LSM <linux-security-module@...r.kernel.org>,
	Paul Moore <paul.moore@...com>,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH][SMACK][2.6.30] convert smack to standard linux lists

On Wed, 25 Mar 2009, Casey Schaufler wrote:

> Etienne Basset wrote:
> > hello,
> >
> > the following patch (on top of 2.6.29) converts Smack lists to standard linux lists
> > Please review and consider for inclusion in 2.6.30-rc
> >
> > regards,
> > Etienne
> >
> > Signed-off-by: Etienne Basset <etienne.basset@...ericable.fr>
> >   
> 
> Acked-by: Casey Schaufler <casey@...aufler-ca.com>
> 
> My tests are passing. Thank you for doing this, it was long
> overdue.

Applied to 
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next

Please make sure the 'Subject' line is correct in future.

See Documentation/SubmittingPatches section 15.


> 
> > ---
> > 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..5648c2f 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;
> > @@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
> >  			 * Make sure that the entry is actually
> >  			 * filled before putting it on the list.
> >  			 */
> > -			smp_mb();
> > -			smack_known = skp;
> > +			list_add_rcu(&skp->list, &smack_known_list);
> >  		}
> >  	}
> >  
> > @@ -283,14 +278,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 +305,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 +337,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 +350,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 +367,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..fdbb065 100644
> > --- a/security/smack/smack_lsm.c
> > +++ b/security/smack/smack_lsm.c
> > @@ -1510,7 +1510,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 +1519,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 +2936,17 @@ struct security_operations smack_ops = {
> >  	.release_secctx = 		smack_release_secctx,
> >  };
> >  
> > +
> > +static __init void 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 +2967,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..45a975c 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.next;
> >  }
> >  
> >  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, &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 =
> > +		 list_entry(list, 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;
> >  
> > -	rule.smk_access = 0;
> > +	rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
> > +	if (rule->smk_object == NULL)
> > +		goto out_free_rule;
> > +
> > +	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_rule;
> >  	}
> >  
> >  	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_rule;
> >  	}
> >  
> >  	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_rule;
> >  	}
> >  
> >  	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_rule;
> >  	}
> >  
> > -	rc = smk_set_access(&rule);
> > +	rc = smk_set_access(rule);
> >  
> >  	if (!rc)
> >  		rc = count;
> > +	goto out;
> >  
> > +out_free_rule:
> > +	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.next;
> >  }
> >  
> >  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, &smack_known_list)) {
> >  		*pos = SEQ_READ_FINISHED;
> > +		return NULL;
> > +	}
> >  
> > -	return skp;
> > +	return list->next;
> >  }
> >  
> >  /*
> > @@ -458,7 +463,9 @@ 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 =
> > +		 list_entry(list, struct smack_known, list);
> >  	struct smack_cipso *scp = skp->smk_cipso;
> >  	char *cbp;
> >  	char sep = '/';
> > @@ -637,18 +644,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.next;
> >  }
> >  
> >  static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
> >  {
> > -	struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
> > +	struct list_head *list = v;
> >  
> > -	if (skp == NULL)
> > +	if (list_is_last(list, &smk_netlbladdr_list)) {
> >  		*pos = SEQ_READ_FINISHED;
> > +		return NULL;
> > +	}
> >  
> > -	return skp;
> > +	return list->next;
> >  }
> >  #define BEBITS	(sizeof(__be32) * 8)
> >  
> > @@ -657,7 +667,9 @@ 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 =
> > +			 list_entry(list, 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,30 +713,36 @@ 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;
> > +	if (list_empty(&smk_netlbladdr_list)) {
> > +		list_add_rcu(&new->list, &smk_netlbladdr_list);
> >  		return;
> >  	}
> >  
> > +	m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
> > +			 struct smk_netlbladdr, list);
> > +
> >  	/* 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;
> > +	if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
> > +		list_add_rcu(&new->list, &smk_netlbladdr_list);
> >  		return;
> >  	}
> > -	for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
> > -		if (m->smk_next == NULL) {
> > -			m->smk_next = new;
> > +
> > +	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;
> >  		}
> > -		if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
> > -			new->smk_next = m->smk_next;
> > -			m->smk_next = new;
> > +		m_next = list_entry(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 +772,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 +826,17 @@ 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)
> > +		    skp->smk_mask.s_addr == mask.s_addr) {
> > +			found = 1;
> >  			break;
> > -
> > +		}
> > +	}
> >  	smk_netlabel_audit_set(&audit_info);
> >  
> > -	if (skp == NULL) {
> > +	if (found == 0) {
> >  		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/
> >
> >
> >   
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
James Morris
<jmorris@...ei.org>
--
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