[apparmor] [PATCH 19/43] apparmor: convert profile lists to RCU based locking

John Johansen john.johansen at canonical.com
Thu Feb 21 18:54:27 UTC 2013


On 02/21/2013 10:16 AM, Seth Arnold wrote:
> Sorry this might be confusing, I had been looking at the top of your
> tree for my code inspections while reading through the details of the
> patch. So some of the references to profile->parent or __list_add_profile
> might have been added by _future_ patches -- I was afraid I'd forget
> the details if I waited until getting to those future patches.
> 
ah, ouch

> On Wed, Feb 20, 2013 at 11:30:27PM -0800, John Johansen wrote:
>>>> +static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile **p)
>>>
>>> The only use of this function is to get profile->parent in change_hat.
>>> Does profile->parent need this extra protection in the other places it
>>> is used? Or is it sufficient to just deref parent without getting its
>>
>> so lets walk through the uses
>> filesystem doesn't use profile->parent
> 
> int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
> {
>         struct aa_profile *child;
>         struct dentry *dent = NULL, *dir;
>         int error;
> 
>         if (!parent) {
>                 dent = prof_dir(profile->parent);
>                 /* adding to parent that previously didn't have children */
>                 dent = securityfs_create_dir("profiles", dent);
>                 if (IS_ERR(dent))
>                         goto fail;
>                 prof_child_dir(profile->parent) = parent = dent;
>         }
> 	/* ... */
> 
this use is fine because the profile isn't live yet. The file is being created
before the profile is added to the list.

> 
>> the use in __replace_profile is protected by locking so it isn't needed
>>
>> free_profile only after their are no more refcounts, and a quiescent
>> period.  So it should not be possible to reference it
>>
>> in the new null, etc cases the profile is not yet live, so there is
>> no chance racing with other tasks/processors
> 
> Excellent :) Thanks
> 
>>>> @@ -447,7 +433,7 @@ out:
>>>>  static void __list_add_profile(struct list_head *list,
>>>>  			       struct aa_profile *profile)
>>>>  {
>>>> -	list_add(&profile->base.list, list);
>>>> +	list_add_rcu(&profile->base.list, list);
>>>>  	/* get list reference */
>>>>  	aa_get_profile(profile);
>>>>  }
>>>
>>> Two of the three callers of this function have an aa_get_profile(profile);
>> err, I only count 2 uses of __list_add_profile, can you clarify
> 
> The first two increment the use count:
> 
> struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
> {
> 	/* ... */
>         mutex_lock(&profile->ns->lock);
>         /* add list ref */
>         aa_get_profile(profile);
>         __list_add_profile(&parent->base.profiles, profile);
>         mutex_unlock(&profile->ns->lock);
> 
> 
> struct aa_label *aa_setup_default_label(void)
> {
> 	/* ... */
>         aa_get_profile(profile);
>         /* replacedby being set needed by fs interface */
>         __list_add_profile(&root_ns->base.profiles, profile);
> 
> ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
> {
> 	/* ... */
>                         rcu_assign_pointer(new->label.replacedby->label,
>                                            aa_get_label(&new->label));
>                         __list_add_profile(&policy->profiles, new);
>                         l = aa_label_insert(&ns->labels, &new->label);
>                         aa_put_label(l);
> 
> 
Indeed this is odd, something isn't right.

thanks
Seth




More information about the AppArmor mailing list