[apparmor] [PATCH 02/36] apparmor: convert profile lists to RCU based locking

Seth Arnold seth.arnold at canonical.com
Wed May 8 21:37:18 UTC 2013


On Wed, May 01, 2013 at 02:30:47PM -0700, John Johansen wrote:

I just noticed that these changes have swapped the order of two
operations. Previously, ns->unconfined was updated to
ns->parent->unconfined before all the profiles in the namespace are
released. With this change, all the profiles in the namespace are
released (which means they take ns->unconfined->label for themselves),
and then ns->unconfined is replaced with ns->parent->unconfined.

While destroy_namespace() in newer iterations populates the replacedby
struct, I'm worried that the aa_put_profile(unconfined) means the refcount
is dropped despite processes actively using the original ns->unconfined.

Here's the parts that worry me:

> @@ -510,17 +494,40 @@ static void __ns_list_release(struct list_head *head);
>   */
>  static void destroy_namespace(struct aa_namespace *ns)
>  {
> +	struct aa_profile *unconfined;
> +
>  	if (!ns)
>  		return;
>  
> -	write_lock(&ns->lock);
> +	mutex_lock(&ns->lock);
>  	/* release all profiles in this namespace */
>  	__profile_list_release(&ns->base.profiles);
>  
>  	/* release all sub namespaces */
>  	__ns_list_release(&ns->sub_ns);
>  
> -	write_unlock(&ns->lock);
> +	unconfined = ns->unconfined;
> +	/*
> +	 * break the ns, unconfined profile cyclic reference and forward
> +	 * all new unconfined profiles requests to the parent namespace
> +	 * This will result in all confined tasks that have a profile
> +	 * being removed, inheriting the parent->unconfined profile.
> +	 */
> +	if (ns->parent)
> +		ns->unconfined = aa_get_profile(ns->parent->unconfined);
> +
> +	/* release original ns->unconfined ref */
> +	aa_put_profile(unconfined);
> +
> +	mutex_unlock(&ns->lock);
> +}
> +
> +static void aa_put_ns_rcu(struct rcu_head *head)
> +{
> +	struct aa_namespace *ns = container_of(head, struct aa_namespace,
> +					       base.rcu);
> +	/* release ns->base.list ref */
> +	aa_put_namespace(ns);
>  }
>  
>  /**
> @@ -531,26 +538,12 @@ static void destroy_namespace(struct aa_namespace *ns)
>   */
>  static void __remove_namespace(struct aa_namespace *ns)
>  {
> -	struct aa_profile *unconfined = ns->unconfined;
> -
>  	/* remove ns from namespace list */
> -	list_del_init(&ns->base.list);
> -
> -	/*
> -	 * break the ns, unconfined profile cyclic reference and forward
> -	 * all new unconfined profiles requests to the parent namespace
> -	 * This will result in all confined tasks that have a profile
> -	 * being removed, inheriting the parent->unconfined profile.
> -	 */
> -	if (ns->parent)
> -		ns->unconfined = aa_get_profile(ns->parent->unconfined);
> +	list_del_rcu(&ns->base.list);
>  
>  	destroy_namespace(ns);
>  
> -	/* release original ns->unconfined ref */
> -	aa_put_profile(unconfined);
> -	/* release ns->base.list ref, from removal above */
> -	aa_put_namespace(ns);
> +	call_rcu(&ns->base.rcu, aa_put_ns_rcu);
>  }
>  
>  /**


Thanks
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20130508/256f0311/attachment.pgp>


More information about the AppArmor mailing list