[apparmor] environment variables

John Johansen john.johansen at canonical.com
Tue Nov 8 07:13:49 UTC 2011


So we have been looking into handling the environment variable problem, and
it was discussed at our UDS planning session.  To summarize several
applications, and frameworks are leveraging environment variables to
control execution behavior.

For glibc this behavior is controlled by secure exec which filters out,
certain environment variables, eg. LD_PRELOAD.  However secure exec only
defines a small black list, and currently only removes the specified
variables from the environment.  A more flexible and generic solution is
needed, preferably one we can tie to policy.

Python, Perl, gtk, etc. all have environment variables that can affect
program execution.  We can currently control attacks(1) using environment
variables that redirect elf object library files by ensuring w and m
permissions do not overlap, so that an application can not map something
it has written as executable.  However m does not tend to work for
scripting languages which may not map code as executable.

A dumb extension of secure exec does not seem to be a viable solution
either, as some environment variables need to be set for applications
to work, eg. the dbus session bus address, and yet we would like to be
able to control the value or range of values a variable could have.

(1) The use of m does not work for U/u x transitions, as the target is
    not confined.


There are a few potential solutions and implementations, we could extend
filtering, extend exec matching, or create a hybrid solution.  Each
solution has its own issues, and design decisions.


1. Matching

The idea here is to extend the exec matching rules, with a conditional
match.

Eg. something like

   env={LD_PRELOAD=/usr/bin/*,FOO=bar} /bin/foo Ux,

The specifics of what it would actually look like is dependent on a few
points.

1a. Should environment variable matching be on the rule, profile or both?
   Placing environment matching on the profile seems to make sense until
   you consider the Ux case, as there is no profile to match against.

   It would be possible to place the match on Ux rules, or to define
   a special dummy profile for Ux transitions.

1b. Should failing to match result in a failed exec or should it fall back,
   and try continuing the match against a more generic, or alternate target.

   This would allow things like
     env={VAR_FOO=BAR} /bin/foo  Ux,
     /bin/* ix,

   The fall back approach seems appealing at first glance but it might
   provide an attacker control over which profile is applied by setting
   the environment variables.

1c. What should the match expression look like, should it be a white list,
   or a black list.  Should it use aare syntax, or perhaps pcre syntax?

   I will note that we do want to be able to make positive assertions
   like (ie. that is the value it should have).
     DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-iOIxOeHCR6,guid=435b295c9d1fc4337e6f1ac100000271

   while at the same time, also allow many generic environment variables
   match.  This is needed because environment variables carry a lot of
   variables that change from system to system, application to application.
   Policy will be hard to write unless there is some generic env var matching.

   The is also hard to express in the current aare white listing syntax.

1d. Compatibility.  Should the env conditional matching be able to be dropped
   by the kernel if it doesn't support it and still match a profile/exec
   rule.


2. Environment filtering

Environment filtering would be like extending the existing secure exec, except
with policy involvement, so the environment variable filtering could be defined
per rule or profile.

It has many of the same questions as Matching.

2a. Should environment variable filtering be on the rule, profile or both?

2b. Should environment filtering be a white list or a black list?

2c. Should it use aare, or pcre syntax, or maybe multiple entries.

2d. Should env filtering be backwards compatible.


In general environment variable filtering should be easier to develop policy
for as it won't fail because it encounter variables it doesn't have rules for.


3. Hybrid

It would be possible to have a hybrid of matching and environment filter if
there is a compelling need and we can devise a reasonable syntax.


4. Implementation

The likely implementation seems to be in the kernel in the bprm hook called
during exec.  Environment filtering could be achieved by extending secure
exec in the libc loader.  However this solution is problematic in that it
relies on all binaries to be linked against the revised loader which
in many cases is not an assumption that can be made.



Another point is that with kernel variables we could support better matching
of values that change per session but should be static during the session.
For example the dbus session bus, shouldn't change for the duration of the
session, so a kernel var could be set when the session is setup, and then
that value would be matched against for all processes in the session.

This is of course assuming certain unimplemented features exist.  For the
moment we would be limited to asserting static values with an eye towards,
dynamic values in the future.




More information about the AppArmor mailing list