[apparmor] environment variables

Jamie Strandboge jamie at canonical.com
Mon Nov 14 22:58:30 UTC 2011


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
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).
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:

  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.

> 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.

> 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).

> 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
export PATH=/home/jj/bin:/usr/bin         # PATH disallowed and not passed to child
export PATH=/home/bad                     # PATH disallowed with failed exec
export PATH=/home/bad:/usr/bin            # PATH disallowed and not passed to child
export PATH=/home/jamie/bin:/usr/bin:/bin # PATH disallowed and not passed to child

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.

> 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?


> 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?

> 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.

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?

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).

Thanks!

-- 
Jamie Strandboge             | http://www.canonical.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20111114/99aee151/attachment.pgp>


More information about the AppArmor mailing list