[apparmor] environment variables

John Johansen john.johansen at canonical.com
Tue Nov 15 00:30:10 UTC 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On 11/14/2011 02:58 PM, Jamie Strandboge wrote:
> On Sat, 2011-11-12 at 05:28 -0800, John Johansen wrote:
>> Alright so here is a second pass at a proposed syntax.
>>
>> Profiles will be allowed to have env rules, that are a white listing of
>> what is allowed by a prospective profile.  Environment variables that do
>> not match will be scrubbed, at the start of an execve.  The rules will
>> not be applied for profile transitions and non-exec boundries (ie.
>> change_hat and change_profile).
>>
>>   env PATH=/home/*/bin/:/usr/bin/,	# allow
> 
> Ok, in trying to wrap my head around this, I am going to try to restate
> what you are proposing. Please correct me where I will inevitably be
> wrong. ;)
> 
> As with any other policy, we have default deny for env variables when
> doing all 'x' transitions *except* ix (I'm not totally sold on this for
err sort of, see below for the rest

> ux, cx, and px since we aren't doing secure_exec there, but then I don't
> have a strong opinion because these shouldn't really be used anyway).
Right.  I came to the conclusion they should be applied for px, ux, cx
because it just make understanding the profile easier.  You see the rules
and you know they are being applied

> Therefore we want to be able to allow certain environment variables via
> env rules. This is a pretty drastic departure over current policy and I
> imagine everything will break. Seems I may have missed something in the
> thread.... Continuing along those lines:
> 
Right, we should stay backwards compatible with this, and I don't see
applying environment filtering unless environment rules are present.
Otherwise like you said we break the world.

I am not to found of allow unless a single rule shows up and then we
start applying but I don't see a better answer, and this is a little bit
different situation than regular allow rules, as failure on these are
defaulted to filtering values instead of denying execution.

Perhaps we should require that env rules are only written in a block,
that could help with reading/understanding profiles by making sure that
they are grouped together as a single rule.


>   env PATH=/home/*/bin/:/usr/bin/,
> 
> says that the PATH is allowed to contain '/home/*/bin/:/usr/bin/'. If
> the PATH has something else (eg, '/usr/bin:/bin'), then PATH is not
> passed as part of the environment to the child.
> 
right

>> There however will be two deny style possibilities, one to filter,
>>
>>   filter env PATH=/home/jj/,
> 
> As above, but if the PATH is simply '/home/jj/', strip the PATH but
> allow execution to continue. filter's utility is not totally clear to me
> as a policy writer, unless we want to use it for blacklisting:
> env {
>      PATH=*/{,s}bin/,
>      filter PATH=/home/*,
>    }
> 
> Which (to me) says 'allow PATHs with (s)bin in the name, but if it
> has /home/jj/bin, then do not pass PATH to the child, but continue the
> exec.
>
right

>> and one to cause an exec to fail
>>
>>   deny env PATH=/home/bad,
> 
> An explicit deny rule such that if PATH is '/home/bad' then the exec is
> forbidden. When PATH is '/usr/bin:/home/bad', then the exec is not
> forbidden, but PATH is still not passed to the child (unless it matches
> the 'env PATH...' rule of course).
>
right, this is also where I think an extend syntax might help if you wanted
to deny any existence of /home/bad you are looking at an aare expression
more along the lines of

  deny PATH={**:,}/home/bad{:**,}

while for PATH it makes sense to think of : separating components, it doesn't
for some of the other environment variables.

>> environment rules can be specified in a block
>>
>>   env {
>>     PATH=/home/*/bin/:/usr/bin/,
>>     filter PATH=/home/jj,
>>     deny PATH=/home/bad,
>>   }
> 
> So this says the following:
> export PATH=/home/jamie/bin:/usr/bin      # PATH allowed and passed to child
yes

> export PATH=/home/jj/bin:/usr/bin         # PATH disallowed and not passed to child
well not as written again it comes down to thinking of : separated path components
as separate or not.  For this one to be filtered we would need to use
  filter PATH={**:,}/home/jj{:**,}

> export PATH=/home/bad                     # PATH disallowed with failed exec
yes

> export PATH=/home/bad:/usr/bin            # PATH disallowed and not passed to child
yep

> export PATH=/home/jamie/bin:/usr/bin:/bin # PATH disallowed and not passed to child
yep

> 
> I bring up the 4th because I wonder if it would be useful to instead of
> not passing PATH in that case if it would be good to simply pass
> '/home/jamie/bin:/usr/bin' as PATH since that part did match. That is a
> bit complicated.
> 
yes that is an interesting point and would be desirable for PATH, I think we could
accommodate that if we extended the filter rule, or maybe added a new rule type.

I need to think about this one more, we need a good generic way to specify what
parts to cut out of a match, not just something that just works for PATH : based
separation.


>> include rules can be user within a block
>>   env { #include <abstractions/base-env-filter>
>>         HOME=/home/jj,
>>       }
> 
> Excellent.
> 
>> In addition to a profile being able to specify the acceptable environment
>> variables, an exec rule can place further restrictions on the environment
>> by specifying an env block after the exec rule.
>>
>>   /bin/foo Ux env { PATH=/home/*:/usr/bin, HOME=/home/jj, },
>>   /bin/bar px -> /bin/bash  env {
>>                                   PATH=/foo:/bar,
>>                                   HOME=/home/jj,
>>                                  },
> 
> In this case when foo does Ux to anything it gets 'env
> { PATH=/home/*:/usr/bin, HOME=/home/jj, }', but if it execs /bin/bar,
> then the 'env { PATH=/foo:/bar, HOME=/home/jj, } is used. Is this
> correct?
> 
maybe :)

Let me be even more explicit, for a process contained by profile A containing
the above two rules.  If it execs

  /bin/foo

then the exec will filter the environment variables to contain only the PATH
and HOME variables if they match the expressions PATH=/home/*:/usr/bin
and HOME=/home/jj.  After which secure exec will be applied (which I don't
believe will end up touching these vars).  So the resultant unconfined
exec will have at most 2 variable PATH, and HOME set, but may have one
or the other or none if the original values where not acceptable.

If it execs
  /bin/bar

then the
env {
      PATH=/foo:/bar,
      HOME=/home/jj,
    },

After which any environment variable rules in the /bin/bar (or what ever profile
matched) would be applied.

> 
>> To facilitate complex conditions an & operator will be allowed, where the
>> list of rules and be thought of as |
>>
>>   env PATH=/home/*/bin/:/usr/bin/ & HOME=/home/jj,
>>
> This says 'if both PATH and HOME match the env rule, then both are
> passed', correct?
> 
yes, but only if they both match.  It extends what it is possible to
express beyond plain regexs as the PATH or HOME expression gets matched
first but it goes into a pending match state that only occurs if the second
is then seen.

>> Expressions can be quoted
>>   env "PATH=/home/path with a space/",
>>
>>   env "PATH=/home/path with a &" & "HOME=/home/jj",
> 
>> The environment variable name is a string that can contain pattern matching
>>   env "P*=/home/path",
>>
>> In the future pcre style matching syntax will be allowed (on file rules
>> as well).
>>
>>   env ^PATH=/home/.*/bin:/usr/bin/$,
>>
> This all sounds fine.
> 
> One other question-- what about 'sticky', 'session' or 'immutable' env
> vars. Eg, I'm thinking we almost always need to do something like this
> for DBus applications to work:
> 
>   env DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-*,guid=*
>
> That isn't really super helpful as a confined application could pass a
> different DBUS_SESSION_BUS_ADDRESS to anything it executes. Better would
> be:
>   session env DBUS_SESSION_BUS_ADDRESS,
> 
> I don't know the best way to express these types of session variables.
> 
Yeah those are problematic.  The problem is you need to tell the kernel
what values they should have some how.  I can envisage a few ways to do
this.

1. Manually tell the kernel by setting a kernel var
  we would need an api call

2. Automatically pin a value to a kernel var from a trusted profile
   state.
  this would require an extension to the rule set, something like

  env {
    set @{DBUS_SESSION} = DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-*,guid=*
  }

  or something like that.  I haven't thought out the detail to much
  yet because we are going to need kernel vars for our matching
  (so we can compare against the pinned value), and we won't have those
  for the first pass at this.

3. We use a user space execution helper, that can get the info it needs from
  some where.  I need to think about this one more.  But if we went this
  route we could practically force environment variables to a specific value
  where that is something I would rather avoid doing from the kernel.

> Lastly, can you show me what the env rules would look like for the
> following use cases:
> 
> 1. Say I don't care about any environment variables except FOOPATH. How
> can I say that all variables are allowed, including FOOPATH, except when
> FOOPATH=/home/*/evil?
> 
env {
  **,
  deny FOOPATH=/home/*/evil,   # or perhaps you would prefer to filter
}

> 2. Is there any concept of assigning a default value via the filter? Eg,
> if we match the filter, rather than filtering it, shove something sane
> in there? This seems rather icky but it does seem it would allow some
> flexibility.
> 
> Basically, I'm trying to think how the environment variables handling
> can be used in a general purpose way (eg, as in a distribution).
> 
No not in the current proposal.  That could be handy but setting values
will definitely require and exec handler, which is something we should
investigate more but maybe shouldn't be required for a first pass
implementation.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBCgAGBQJOwbKSAAoJEAUvNnAY1cPYw04P/3P21bu/fA03tOAQO8Coh1R9
pMdLBMuaf/gZ/WRvOmNfYHnpfcvoOnxbfEpSK/Ed0VOK9XVGLwqJXeKkttL4DbGo
O3/8si0vCeOw9IIJH0NyUKed5mOB77TVkNKbqix9xA7PkAwPuPq+HXgqqDRtmJ6g
ulCZiBx8GWGSx+sOa37v6TErYDnj6aj5xeU07uO5FIZCdc5MHygG6TsOj8B/A62r
iVooOnDw4D6F3GRXOgnWJeAogQrVopIUSGQIsX/U3J2OzXZY+duM9DPbJhsCNVif
EMXsoO3aSMuSJI+utPCUtbEO0eovEn90RcaC6sEFh3Obg8lx6qoeHz3iiBk9oPld
Vl9DJtgSvoyMsXwnMUuMBv+gHzRowxZQv8+TnjEDhherTZfV+/vWPd7SmAL6op8/
p7re4RK1oXvf6L4KXD6qtWq/i5RznX6Qm8HC5rWtooVfeVLRu2w22f1IFrVL6hnX
ib9yGrc53gGD/tAlrLzjcts9+HmIZM4FV7k0gYapVAxFUJasHN1tMpQiBzo1iNp2
fIRXltapt+5vVySS2xuaSa2g7SeBdktsQ33tJq8PuO1xqmVexxmRPaacyMLs83Kv
r4lGXogZLkTCYll+KOdNQ4OeAjynWH43xAsb/HiXk7NcilsOFiWNyqqgww+wa/Vd
r1a8kE37/Q1eg5FQ6Ti+
=WyHK
-----END PGP SIGNATURE-----



More information about the AppArmor mailing list