On Fri, Feb 08, 2013 at 01:00:55PM -0800, John Johansen wrote:
> signed-offby: John Johansen <john.johan...@canonical.com>
> ---
>  security/apparmor/domain.c           |   15 ++-
>  security/apparmor/include/apparmor.h |    6 ++
>  security/apparmor/include/policy.h   |   44 +++++++-
>  security/apparmor/policy.c           |  195 
> ++++++++++++++++++----------------
>  security/apparmor/policy_unpack.c    |    5 +
>  5 files changed, 164 insertions(+), 101 deletions(-)

I'm sorry that I haven't reviewed this entire patch yet -- it's heavier
lifting than I expected. But I'll give you what I've got now, with the
hopes that it may unblock you sooner.

> @@ -641,7 +641,10 @@ int aa_change_hat(const char *hats[], int count, u64 
> token, bool permtest)
>       if (count) {
>               /* attempting to change into a new hat or switch to a sibling */
>               struct aa_profile *root;
> -             root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
> +             if (PROFILE_IS_HAT(profile))
> +                     root = aa_get_profile_rcu(&profile->parent);
> +             else
> +                     root = aa_get_profile(profile);
>  
>               /* find first matching hat */
>               for (i = 0; i < count && !hat; i++)

'root' is get here but there's a branch where it isn't put:

                } else {
                        target = hat->base.hname;
                        if (!PROFILE_IS_HAT(hat)) {
                                info = "target not hat";
                                error = -EPERM;
                                goto audit;
                        }
                }

> @@ -42,6 +42,7 @@ extern const char *const profile_mode_names[];
>  
>  #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
>  
> +#define list_empty_rcu(X) (list_empty(X) || (X)->prev == LIST_POISON2)

This feels brittle. I haven't put the time into fully understanding the
uses of it yet, but one at least feels like an opportunity to just return
worse information to userspace (whether there are zero hats or just an
invalid hat was selected). Besides, in that case, it is racing against
replacement, perhaps just using list_empty() alone would be fine --
it might not be true by the next sync(), but it _might have been true_
at some point in the past. Learning mode is never going to be perfect.

But perhaps the other two uses are more compelling...

> +static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile **p)
> +{
> +     struct aa_profile *c;
> +
> +     rcu_read_lock();
> +     do {
> +             c = rcu_dereference(*p);
> +     } while (c && !kref_get_not0(&c->base.count));
> +     rcu_read_unlock();
> +
> +     return c;
> +}

How many iterations of this are possible, if two or more cores each
trying to aa_get_profile_rcu() the same profile... Would they step on
each other's toes in the kref_get_not0() loop, bouncing among them and
never one 'owning' it?

How long could that go on?


Wow, it seems so little after so much hair-pulling..

Thanks John :)

Attachment: signature.asc
Description: Digital signature

-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to