[apparmor] trouble with nested grandchild profiles

John Johansen john.johansen at canonical.com
Wed Sep 9 12:26:42 UTC 2015


On 09/09/2015 03:50 AM, apparmor at raf.org wrote:
> debian-8.1, apparmor-2.9.0
> 
> Hi,
> 
> I'm having trouble getting nested grandchild profiles working.
I bet, unfortunately grandchild profiles are not properly supported
yet.

Neither the compiler or the utils properly support them, however
the kernel does, and uses them in the case of null- learning
profiles.

The parser (policy compiler) is the next piece that will be
updated to support this, which enable you to do this as long
as you are only manually editing your profiles. Unfortunately
I do not have a time line as to when this change will be ready.

Now with that said if you really need them you can actually
use them by using the external hats notation. And using Px
instead of Cx for '->' style transitions (due to an error in
the parser).

> 
> When I tried something like this:
> 
>   /usr/sbin/apache2 flags=(complain) {
>     /path/to/index.cgi rCx -> indexcgi_profile,
>     profile indexcgi_profile flags=(complain) {
>       /usr/bin/mutt-org rCx -> mutt_profile,
>       profile mutt_profile flags=(complain) {
>       }
>     }
>   }
> 
> I got this error when trying to load it:
> 
>   /sbin/apparmor_parser: Unable to replace "mutt_profile".
>   Profile doesn't exist
> 
gah, sorry

the parser is supposed to have check that bails earlier with a message
explaining this isn't supported yet.

> So I tried moving the mutt_profile grandchild profile out
> of indexcgi_profile like this:
> 
> /usr/sbin/apache2 flags=(complain) {
>   /path/to/index.cgi rCx -> indexcgi_profile,
>   profile indexcgi_profile flags=(complain) {
>     /usr/bin/mutt-org rCx -> mutt_profile,
>   }
>   profile indexcgi_profile//mutt_profile flags=(complain) {
>   }
> }
> 
> And apparmor_parser loaded it without complaint and aa-status shows:
> 
>   /usr/sbin/apache2//indexcgi_profile
>   /usr/sbin/apache2//indexcgi_profile//mutt_profile
> 
> Which looks promising but then I got this apparmor log message:

Indeed you are on the right track, but there is a little Cx when used
with -> bug that will bite you.
> 
>   audit: type=1400 audit(1441794360.161:74384): apparmor="ALLOWED"
>   operation="exec" info="profile not found" error=-2
>   profile="/usr/sbin/apache2//indexcgi_profile"
>   name="/usr/bin/mutt-org" pid=13884
>   comm="index.cgi" requested_mask="x" denied_mask="x"
>   fsuid=33 ouid=0
> 
> So, the first concern is that either of the two versions should
> be equivalent as far as I can tell from what I've read.
> Why does apparmor_parser reject the first version but not the second?
> Is it a bug in apparmor_parser or have I misunderstood something?
> 
It is an incomplete implementation, we have been working towards
supporting multiple levels (beyond the basic 2) but it hasn't been 
a high priority item

> Secondly, why is it not working? The indexcgi_profile profile has a rule to
> allow index.cgi to execute /usr/bin/mutt-org but the log message says that
> it failed, saying "profile not found". Which profile hasn't been found? Why?
> What do I have to do to make it findable?
> 
It should work if you transform you Cx rule in the indexcgi_profile to a Px
rule.


/usr/sbin/apache2 flags=(complain) {
  /path/to/index.cgi rCx -> indexcgi_profile,
  profile indexcgi_profile flags=(complain) {
    #use Px to -> to grandchild so we can avoid parser broken Cx mapping for grandchildren
    /usr/bin/mutt-org rPx -> /usr/sbin/apache2//indexcgi_profile//mutt_profile,
  }
}
#external grandchild profile, must come after grand parent and parent are defined
profile /usr/sbin/apache2//indexcgi_profile//mutt_profile flags=(complain) {
}

should work for you.

A few things to note:
// acts something like a directory separator between profile levels in apparmor

so
A - top level profile
A//B - fully qualified name of subprofile B in profile a
A//B//C - grand child

profile names are not allowed to end with / so
A///B is unambiguous, the first two of the three /s indicate a level separator and
the child profile is /B

ie. this is the fully qualified name for the child profile declared by
profile A {
  profile /B { }
}

apparmor supports declaring children external to the profile, if the fully qualified
name is used. This is discouraged for various reasons but it can be used as a work
around, So you can do

profile A { }
profile A//B { }

to get the same as what we did above

And for grand children

profile A {
profile B {
profile C { }
}
}

we can just do the grand child as an external profile
profile A {
profile B { }
}
profile A//B//C { }

or the parent and the grand child
profile A { }
profile A//B { }
profile A//B//C { }

doing this requires that the parent profiles be declared before the child, ie.
profile A//B//C { }
profile A//B { }
profile A

will break

As for the Cx bug, using a plan Cx should work, eg.

profile A {
profile B {
/foo Cx,
}
}
profile A//B///foo { }

but when using the -> variant you will need to use Px and fully qualified names
profile A {
profile B {
/foo Cx -> C,
}
}
profile A//B//C { }




More information about the AppArmor mailing list