[apparmor] [PATCH] enhance aa-status to deal with lack of interface patch

Steve Beattie steve at nxnw.org
Wed Apr 25 23:37:15 UTC 2012

On Wed, Apr 25, 2012 at 12:32:48PM -0700, Kees Cook wrote:
> Yeah. I've kind of always felt that this was a mis-feature. The things
> the init system wants to know are:
> - is AppArmor capable of functioning? (in kernel and enabled)
> - is it time to start loading profiles? (... in Ubuntu we cheated by
>     looking at if profiles are already loaded -- since all systems with
>     AppArmor will have preloaded the network-early-start profiles. This
>     is, however, a catch-22 and takes advantage of a specific side-effect
>     of how Ubuntu loads profiles.)
> So, if we can eliminate the need for the second thing above, then the
> problem goes away, and --enabled can stop lying. :)
> If I remember correctly, doing the profile count was to avoid loading
> profiles in certain conditions. Unfortunately, I can't remember for sure
> what those situations were. I think it was: LiveCD and release upgrades,
> but I'm pretty sure both are covered now.

Actually, there are more conditions than that, at least for operating
within an LSB compliant init script. In particular, the 'try-restart'
option needs to "restart" apparmor only if it's already running. Given
that apparmor is not a daemon, but a kernel element that needs to
be configured, we (upstream) made the decision to assume that even
if apparmor is enabled in the kernel but has 0 profiles loaded,
this was considered "not running", under the assumption that the
initscript had either been disabled or an admin had done a 'stop'
action, which would unload all profiles (and yes, I'm aware that the
ubuntu/debian initscript differs in behavior here). In other words,
we map the LSB running state to "apparmor is enabled *and* enforcing
at least one policy".

Identifying the situation where apparmor was enabled but not enforcing
anything *in a way that can be detected programmatically without
worrying about translations/locales/strings that change, etc.* was
deemed important and why it was done as a return code.

Now, that said, the initscripts we provide don't actually make use
of aa-status to determine the state of apparmor, other than for
the 'status' target (I think because we worked with the assumption
that the apparmor utils weren't guaranteed to be installed; also
that people wouldn't necessarily want to pay the costs of starting a
perl/python interpreter during boot). However, the non-verbose options
were added to aa-status to support being invoked by other programs
that could potentially make decisions/take actions like restarting
services based on its output; things like CIM providers and other
monitoring/controlling services.

> I'd like to have --enabled not lie, and work out the bugs this triggers
> as separate issues. If this isn't cool for now, how about having it only
> lie if the legacy "profiles" interface exists?
> > This should possibly be its own error code state, I think, to
> > distinguish from "apparmor enabled, no policy loaded" to "apparmor
> > loaded, but the version doesn't let me determine how many profiles
> > are loaded". (It's up to the calling program to treat the return codes
> > as fatal events -- there's no real other way for aa-status to return
> > complex results.)
> Well... as I mention in the comment, I don't think it's actually
> an error condition. I think aa-status should attempt to handle it,
> but emit a warning (which this does). It just means it can't tell the
> user about processes that are running that are unconfined by a loaded
> profile. It can still report all the other states sanely (since it reads
> /proc/$pid/attr/current).

The thing about aa-status is that it serves two purposes: 1) as a
user facing tool to get a snapshot of the state of apparmor policy and
enforcement on the system and 2) a tool intended to be used by other
programs to capture the state of apparmor. Emitting warning messages is
fine in the former situation, but less so in the latter.  Knowing *why*
'aa-status --profiled' returned 0 is useful (are there actually zero
profiles loaded or is it that this is using an upstream kernel?).

That said, I think we can construct things in such a way to satisfy
people's needs. Arguably, in hindsight, I can see the utility
of having a separate '--running' option and make the '--enabled'
strictly determine if apparmor is enabled on the host. However, I
don't know how to answer the case of whether apparmor is "running"
when the introspection interface isn't present; do you walk the
/proc/PID trees looking for the sign of any profile being applied
and return false if not?

I'll look more at coming up with a solution here.

(In an ideal world, the state detection logic would get shoved into a
python class that could be imported into any number of python utilities
and raised exceptions based on the situation it encountered, and the
caller could take and report as appropriate; the sys.exit()s would
need to go.)

Steve Beattie
<sbeattie at ubuntu.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20120425/c11a77b0/attachment.pgp>

More information about the AppArmor mailing list