[apparmor] Apparmor rules for dconf confinement

Simon McVittie simon.mcvittie at collabora.co.uk
Fri May 29 16:29:53 UTC 2015


On 28/05/15 11:14, John Johansen wrote:
> With reducing this to a single blob of data I think we could consider
> having a more generic command, to just ask for a named blob of data.
> This way the command isn't dconf specific but could serve dconf and
> maybe other uses in the future.

One concrete thing that might benefit from a more generic approach to
user-space mediation is polkit (formerly PolicyKit). You probably all
know how polkit works and how it interacts with AppArmor, but in case
anyone reading this doesn't, here is a summary.

The ideal situation for AppArmor is when a process does a
"controversial" operation, e.g. mounting a disk, directly (a direct
request to the kernel), in which case AppArmor code in the kernel can
mediate the operation in the obvious way. This is fine for actions that
would be allowed by DAC and are only being denied by MAC, like writing
to an owned file; but not so good for actions that DAC would deny
anyway, like mounting disks.

However, many processes on a modern system do operations by submitting
an IPC request to a more-privileged service which will do the actual
operation: for instance, desktop environments don't mount USB drives,
they ask udisks2 to mount USB drives for them. In these cases, the
kernel's normal DAC permissions checks and AppArmor checks are not
particularly useful: they only determine whether the process can
talk to the service at all. Some applications have absolutely no
legitimate reason to talk to udisks2, so AppArmor rules can just block
it altogether; but this is rather coarse-grained, and does not allow
(for instance) inspecting filesystems' types but not mounting them.

For the specific case where the IPC is via D-Bus, we do have
fine-grained checks on the header part of the D-Bus message. However,
those checks are not particularly useful, because neither AppArmor nor
dbus-daemon really understands what is happening. For instance, we can't
know whether a call to org.freedesktop.UDisks2.Filesystem.Mount() is
acting on a USB drive (in which case it's probably OK) or on an
internal/system drive (in which case it probably isn't). This is where
components like freedesktop.org's polkit (and Tizen's Cynara, which
competes directly with polkit) come in.

Another factor here is that the authors of kdbus strongly oppose
applying in-kernel controls to kdbus messages that parse the message's
payload (the body, and all parts of the traditional D-Bus header not
used for routing, i.e. everything except the source and destination), on
the basis that the interpretation of the payload is entirely up to the
recipient anyway; so these fine-grained checks are not going to be
available on kdbus, unless AppArmor incorporates a strictly
validating[1] GVariant parser into the kernel (in practice this seems
unlikely).

The service to which the operation was delegated understands more about
the context and high-level meaning of the request than generic
infrastructure like AppArmor and dbus-daemon can: for instance, udisks2
understands the domain-specific difference between mounting a USB drive,
which is potentially OK, and altering the root filesystem's mount
options, which is dangerous and shouldn't be allowed. This means it can
do a finer-grained check, taking into account the high-level meaning of
what is being done. Because the service understands the request, the
question it asks when checking a policy can be a lot more specific: for
instance, for USB storage, instead of asking "is this process allowed to
mount filesystems?" (which would, in general, be dangerous, so we would
have to say no), it can ask "is this process allowed to mount removable
disks with sane options?" (which is a special case, and is OK to allow).

In the case of polkit, the approach that services are encouraged to take
is to use the polkit client library to call out to the polkit daemon,
specifying an abstract "action" like
org.freedesktop.udisks2.modify-device-system or
org.freedesktop.udisks2.modify-device-other-seat; the definition of the
action has a default policy designed to be reasonable in most cases, and
sysadmins can override that policy to impose their preferred local
security policy. Because these actions are defined by the service, which
knows about the specifics of the problem it solves, they can take into
account any domain-specific distinctions that the service author thinks
are likely to be interesting to a security policy author.

At the moment, the polkit daemon bases its policy on the uid and pid of
the requesting process (usually determined by the service using
dbus-daemon's APIs). On dbus 1.9+, it could use
GetConnectionCredentials() to receive the uid, pid and LSM context
simultaneously, after which it could do an AppArmor query in much the
same way that dbus-daemon does.

Here's a sketch of how this could look, for instance:

    audit polkit action=org.freedesktop.udisks2.filesystem-mount,
    audit deny polkit \
        action=org.freedesktop.udisks2.filesystem-mount-system,

or if the syntax in policy files was entirely generic, perhaps something
more like:

    userspace class=polkit \
        action=org.freedesktop.udisks2.filesystem-mount,
    audit deny userspace class=polkit \
        action=org.freedesktop.udisks2.filesystem-mount-system,

Does this sound like a reasonable generalization?

    S

[1] it needs to validate, to avoid malformed messages being interpreted
in one way by the routing infrastructure, but in a different way by the
recipient - at least, that's the justification for dbus-daemon
validating messages strictly

-- 
Simon McVittie
Collabora Ltd. <http://www.collabora.com/>




More information about the AppArmor mailing list