All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serue@us.ibm.com>
To: Pavel Emelyanov <xemul@openvz.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Serge Hallyn <serue@us.ibm.com>
Subject: Re: [PATCH] devcgroup: relax white-list protection down to RCU
Date: Fri, 27 Jun 2008 15:29:43 -0500	[thread overview]
Message-ID: <20080627202943.GA13956@us.ibm.com> (raw)
In-Reply-To: <48651BDC.5030104@openvz.org>

Quoting Pavel Emelyanov (xemul@openvz.org):
> Currently this list is protected with a simple spinlock, even
> for reading from one. This is OK, but can be better.
> 
> Actually I want it to be better very much, since after replacing
> the OpenVZ device permissions engine with the cgroup-based one
> I noticed, that we set 12 default device permissions for each newly
> created container (for /dev/null, full, terminals, ect devices),
> and people sometimes have up to 20 perms more, so traversing the
> ~30-40 elements list under a spinlock doesn't seem very good.
> 
> Here's the liter RCU protection for white-list.
> 
> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
> 
> ---
> 
> diff --git a/security/device_cgroup.c b/security/device_cgroup.c
> index 4ea5836..9d940c3 100644
> --- a/security/device_cgroup.c
> +++ b/security/device_cgroup.c
> @@ -41,6 +41,7 @@ struct dev_whitelist_item {
>  	short type;
>  	short access;
>  	struct list_head list;
> +	struct rcu_head rcu;
>  };
> 
>  struct dev_cgroup {
> @@ -110,11 +111,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
> 
>  	memcpy(whcopy, wh, sizeof(*whcopy));
>  	spin_lock(&dev_cgroup->lock);
> -	list_add_tail(&whcopy->list, &dev_cgroup->whitelist);
> +	list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
>  	spin_unlock(&dev_cgroup->lock);
>  	return 0;
>  }
> 
> +static void whitelist_item_free(struct rcu_head *rcu)
> +{
> +	struct dev_whitelist_item *item;
> +
> +	item = container_of(rcu, struct dev_whitelist_item, rcu);
> +	kfree(item);
> +}
> +
>  /*
>   * called under cgroup_lock()
>   * since the list is visible to other tasks, we need the spinlock also
> @@ -138,8 +147,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
>  remove:
>  		walk->access &= ~wh->access;
>  		if (!walk->access) {
> -			list_del(&walk->list);
> -			kfree(walk);
> +			list_del_rcu(&walk->list);
> +			call_rcu(&walk->rcu, whitelist_item_free);

The only thing I'd suggest is that a call_rcu() really isn't necessary.
You'd avoid the rcu_head in each dev_whitelist_item if you just did

			synchronize_rcu();
			kfree(walk);

here.  Downside is you're keeping the cgroup_lock() a little longer
then...

But that's just an idea.  Whether you do that or not,

Acked-by: Serge Hallyn <serue@us.ibm.com>

Thanks for doing this.

-serge

>  		}
>  	}
>  	spin_unlock(&dev_cgroup->lock);
> @@ -246,15 +255,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
>  	struct dev_whitelist_item *wh;
>  	char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
> 
> -	spin_lock(&devcgroup->lock);
> -	list_for_each_entry(wh, &devcgroup->whitelist, list) {
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
>  		set_access(acc, wh->access);
>  		set_majmin(maj, wh->major);
>  		set_majmin(min, wh->minor);
>  		seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
>  			   maj, min, acc);
>  	}
> -	spin_unlock(&devcgroup->lock);
> +	rcu_read_unlock();
> 
>  	return 0;
>  }
> @@ -516,8 +525,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
>  	if (!dev_cgroup)
>  		return 0;
> 
> -	spin_lock(&dev_cgroup->lock);
> -	list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
>  		if (wh->type & DEV_ALL)
>  			goto acc_check;
>  		if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
> @@ -533,10 +542,10 @@ acc_check:
>  			continue;
>  		if ((mask & MAY_READ) && !(wh->access & ACC_READ))
>  			continue;
> -		spin_unlock(&dev_cgroup->lock);
> +		rcu_read_unlock();
>  		return 0;
>  	}
> -	spin_unlock(&dev_cgroup->lock);
> +	rcu_read_unlock();
> 
>  	return -EPERM;
>  }
> @@ -552,7 +561,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
>  	if (!dev_cgroup)
>  		return 0;
> 
> -	spin_lock(&dev_cgroup->lock);
> +	rcu_read_lock();
>  	list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
>  		if (wh->type & DEV_ALL)
>  			goto acc_check;
> @@ -567,9 +576,9 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
>  acc_check:
>  		if (!(wh->access & ACC_MKNOD))
>  			continue;
> -		spin_unlock(&dev_cgroup->lock);
> +		rcu_read_unlock();
>  		return 0;
>  	}
> -	spin_unlock(&dev_cgroup->lock);
> +	rcu_read_unlock();
>  	return -EPERM;
>  }

  reply	other threads:[~2008-06-27 20:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-27 16:57 [PATCH] devcgroup: relax white-list protection down to RCU Pavel Emelyanov
2008-06-27 20:29 ` Serge E. Hallyn [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-07-11 15:27 Pavel Emelyanov

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=20080627202943.GA13956@us.ibm.com \
    --to=serue@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=xemul@openvz.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.