Commit graph

261 commits

Author SHA1 Message Date
Tyler Hicks
8553727414 parser: Add policy cache function for cache removal
This function allows for a policy cache to be removed without having a
previously instatiated aa_policy_cache object. It simply works off of a
path.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
f0fcf23231 parser: Create initial interface for policy cache
This API has the same look-and-feel of the previous aa_features API.

The cache setup code was heavily dependent on globals set by CLI
options. Options such as "skip the read cache", or "skip the write
cache", or "don't clear the cache if it isn't valid", won't be useful
for all aa_policy_cache API users so some of that logic was lifted out
of the API. The constructor function still provides a bool parameter
that specifies if the cache should be created or not.

If the policy cache is invalid (currently meaning that the cache
features file doesn't match the kernel features file), then a new
aa_policy_cache object is still created but a call to
aa_policy_cache_is_valid() will return false. The caller can then decide
what to do (create a new valid cache, stop, etc.)

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d93d00cca9 parser: Deprecate the --create-cache-dir option
This option adds unneeded complexity to the parser CLI and the upcoming
aa_policy_cache API. Get rid of it and simply create the cache dir if
--write-cache is specified.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
4d1fa49c37 parser: Add functions for features support tests
Defines a function that can be called to test features support. It is
string based which allows the support tests to work with new kernel
features without any changes.

The use of global variables in the parser to store and check features
support is still preserved. The parser should probably move over to
passing the aa_features object around but that's left for later.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
45ac621f26 parser: Begin to flesh out library interface for features
The aa_features_new_*() functions create an aa_features object. They can
be thought of as the constructor of aa_features objects. A number of
constructors are available depending on whether the features are coming
from a file in the policy cache, a string specified on the command line,
or from apparmorfs.

The aa_features_ref() and aa_features_unref() functions are used to grab
and give up references to an aa_features. When the ref count hits zero,
all allocated memory is freed. Like with free(), aa_features_unref() can
be called with a NULL pointer for convenience.

Pre-processor macros are hidden behind functions so that they don't
become part of our ABI when we move this code into libapparmor later on.

A temporary convenience function, aa_features_get_string(), is provided
while code that uses aa_features is migrated from expecting raw features
string access to something more abstract. The function will be removed
in an upcoming patch.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
22993081c8 parser: Lift force_clear_cache handling from setup_cache()
This keeps us from having to use the force_clear_cache global in
policy_cache.c.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d2e3f806c0 parser: Don't use the basedir global in setup_cache()
Require the caller of setup_cache() to pass in a valid cache location
string. This removes the use of the basedir global from the
policy_cache.c file.

Additionally, it is no longer necessary to return the "cache dir" path
from setup_cache() since it will always be the same as the input path.
The return value is changed to an int so an error code can be returned
instead of using exit().

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d02bb58b70 parser: Get rid of the cacheloc global
Modify setup_cache() to accept the user-supplied cacheloc and return the
validated or created cache directory. The caller must then track that
variable and pass it into any parser/policy_cache.c functions that need
it.

The main reason for this change is that the cache location and the cache
directory will soon be two different paths. The cache location will
typically be the parent of the cache directory.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
0f12effabf parser: Move policy cache initialization code into its own function
This patch moves the logic that sets up the policy into a new function
in policy_cache.c

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
2a082ee543 parser: Move policy cache functionality into policy_cache.c
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Fixed build failures]
[tyhicks: Fixed bug where a warning was being printed when it shouldn't]
[tyhicks: Forward ported to trunk]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
4e712f6c8d split routines for loading binary policy into its own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Handle inverted return from find_subdomainfs_mountpoint()]
[tyhicks: Link test progs to libapparmor to fix make check build fail]
[tyhicks: Migrate from opendir() to open() for opening apparmorfs]
[tyhicks: Make some of the split out functions static]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
076bc6be7a With the auto cleanup changes we can now directly return the value if we have a cache hit.
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported patch to trunk]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
f62cc5c6bf Use the gcc cleanup extension attribute to handle closing temp files
While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
82904cf0e6 Use the gcc cleanup extension attribute to handle freeing temp allocations
While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
2dd3fa9383 split the policy cache handling fns into their own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Don't move globals in favor of lifting those out later]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
4959e2e2a8 Move feature handling code into its own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported patch to trunk]
[tyhicks: Don't move set_supported_features()]
[tyhicks: Don't move set_features_by_match_file()]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
c85bca38f5 fix cache write to not happen when skip-bad-cache is specified
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
2b240461a7 change cache check so that debugging can see which file caused failure
Currently the cache tracks the most recent timestamp of parsed files
and then compares that to the cache timestamp. This unfortunately
prevents the parser from being able to know which files caused the
cache check failure.

Rework the cache check so that there is a debug option, and that
the cache file timestamp is set first so that we can output
a deug message for each file that causes a cache check failure.

Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported to trunk and minor cleanups]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-25 17:09:25 -05:00
Tyler Hicks
15e9f2790e parser: Fix error checking of file opening in features_dir_cb()
The error path was being taken when openat() return 0 but openat()
returns -1 on error.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-03 20:28:22 -06:00
John Johansen
c2b8a72317 disable downgrade and not enforced rule messages by default
Currently the apparmor parser warns about rules that are not enforced or
downgraded. This is a problem for distros that are not carrying the out of
tree kernel patches, as most profile loads result in warnings.

Change the behavior to not output a message unless a warn flag is passed.
This patch adds 2 different warn flags
  --warn rule-downgraded    	 # warn if a rule is downgraded
  --warn rule-not-enforced	   # warn if a rule is not enforced at all

If the warnings are desired by default the flags can be set in the
parser.conf file.

v2 of patch
- update man page
- add --warn to usage statement
- make --quiet clear warn flags

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-10-08 13:20:20 -07:00
Steve Beattie
a44b6ce0a2 C tools: rename __unused macro to unused
Bug: https://bugzilla.novell.com/show_bug.cgi?id=895495

We define the __unused macro as a shortcut for __attribute__((unused))
to quiet compiler warnings for functions where an argument is unused,
for whatever reason. However, on 64 bit architectures, older glibc's
bits/stat.h header defines an array variable with the name __unused
that collides with our macro and causes the parser to fail to build,
because the resulting macro expansion generates invalid C code.

This commit fixes the issue by removing the __unused macro where it's
not needed (mod_apparmor) and renaming it to 'unused' elsewhere. It also
in some instances reorders the arguments so that the unused macro
appears last consistently.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2014-10-02 12:58:54 -07:00
John Johansen
9e93e6eaf5 fix: if the apparmor parser fails to load the cache try rebuilding
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-09-23 14:33:54 -07:00
John Johansen
8fb91c8e9d fix: Make the parser behave the same as when driven with xargs -n1
Currently the parser is bailing when it fails to load a profile,
not processing any potential subsequent profiles in the dir or passed
in list. This results in all policy after the first error failing
to load, instead of just the profile(s) with the error.

This is a different behavior than what has been done by initscripts
that have driven it with xargs -n1, passing it a single profile
at a time.

Fix this so that the parser only exits on first error if specifically
told to do so.

Note: this does not fix the various failure points in the parser
that call exit, instead of returning an error.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>, thanks.
2014-09-23 14:24:40 -07:00
Seth Arnold
70119a81d8 The AppArmor parser failed to build on the x32 architecture due to a
missing <sys/sysctl.h> header. This header is included by accident, a
vestige of earlier days, and wasn't removed when the sysctls were removed.
(Think Linux 2.0 or Linux 2.2 days.)

See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=760378

Thanks to Thorsten Glaser for the discovery and initial fix.
2014-09-10 10:28:00 -07:00
John Johansen
dd44858e60 parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.

The unix network rules follow the general fine grained network
rule pattern of

  [<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]

specifically for af_unix this is

  [<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]

  <qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]

  <access expr> = ( <access> | <access list> )

  <access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
               'connect' | 'shutdown' | 'getattr' | 'setattr' |
	       'getopt' | 'setopt' |
               'send' | 'receive' | 'r' | 'w' | 'rw' )
  (some access modes are incompatible with some rules or require additional
   parameters)

  <access list> = '(' <access> ( [','] <WS> <access> )* ')'

  <WS> = white space

  <rule conds> = ( <type cond> | <protocol cond> )*
     each cond can appear at most once

  <type cond> = 'type' '='  ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )

  <protocol cond> = 'protocol' '='  ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )

  <local expr> = ( <path cond> | <attr cond> | <opt cond> )*
     each cond can appear at most once

  <peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
     each cond can appear at most once

  <path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )

  <label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')

  <attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )

  <opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )

  <AARE> = ?*[]{}^ ( see man page )

 unix domain socket rules are accumulated so that the granted unix
 socket permissions are the union of all the listed unix rule permissions.

 unix domain socket rules are broad and general and become more restrictive
 as further information is specified. Policy may be specified down to
 the path and label level. The content of the communication is not
 examined.

 Some permissions are not compatible with all unix rules.

 unix socket rule permissions are implied when a rule does not explicitly
 state an access list. By default if a rule does not have an access list
 all permissions that are compatible with the specified set of local
 and peer conditionals are implied.

 The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
 server = (create, bind, listen, accept)
 r = (receive, getattr, getopt)
 w = (create, connect, send, setattr, setopt)

In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.

This means that the rules

  network unix,
  network netlink,

are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
John Johansen
9fe1e72c44 put the gettext define in one place
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-23 23:50:43 -07:00
John Johansen
d2d6cdb1c2 Convert cache to using mtime
For some strange reason our caching use ctime instead of mtime.
However this can lead to odd cases of the cache missing even though
neither the profile data nor cache data have changed.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-06-17 10:59:15 -07:00
John Johansen
4a753029bb Update error message to indicate it is about a binary profile or cache file
Signed-off-by: John Johansen <john.johansen@canonical.com>
2014-06-17 10:58:09 -07:00
John Johansen
e08eaa39e2 Fix profile loads from cache files that contain multiple profiles
v3: fix freeing of filename when undefined
v2: address tyhicks feedback
    refactor to have a common write routine
    fix issue with set profile load being done even if !kernel_load

Profile loads from cache files that contain multiple profiles can
result in multiple reloads of the same profile or error messages about
failure to load profiles if the --add option is used. eg.

  apparmor="STATUS" operation="profile_load"
  name="/usr/lib/apache2/mpm-prefork/apache2" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058388] type=1400 audit(1395415826.937:616):
  apparmor="STATUS" operation="profile_load" name="DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058391] type=1400 audit(1395415826.937:617):
  apparmor="STATUS" operation="profile_load"
  name="HANDLING_UNTRUSTED_INPUT" pid=8631 comm="apparmor_parser"
  <sth0R> [82932.058394] type=1400 audit(1395415826.937:618):
  apparmor="STATUS" operation="profile_load" name="phpsysinfo" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059058] type=1400 audit(1395415826.937:619):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059574] type=1400 audit(1395415826.937:620):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//HANDLING_UNTRUSTED_INPUT"
  pid=8631 comm="apparmor_parser"


The reason this happens is that the cache file is a container that
can contain multiple profiles in sequential order
  profile1
  profile2
  profile3

The parser loads the entire cache file to memory and the writes the
whole file to the kernel interface. It then skips foward in the file
to the next profile and reloads the file from that profile into
the kernel.
  eg. First load
    profile1
    profile2
    profile3

  advance to profile2, do second load
    profile2
    profile3

  advance to profile3, do third load
    profile3


With older kernels the interface would stop after the first profile and
return that it had processed the whole file, thus while wasting compute
resources copying extra data no errors occurred. However newer kernels
now support atomic loading of multipe profiles, so that all the profiles
passed in to the interface get processed.

This means on newer kernels the current parser load behavior results
in multiple loads/replacements when a cache file contains more than
one profile (note: loads from a compile do not have this problem).

To fix this, detect if the kernel supports atomic set loads, and load
the cache file once. If it doesn't only load one profile section
from a cache file at a time.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-05-08 09:03:13 -07:00
John Johansen
a1a7c78755 Add the ability to specify ptrace rules
ptrace rules currently take the form of

  ptrace [<ptrace_perms>] [<peer_profile_name>],
  ptrace_perm := read|trace|readby|tracedby
  ptrace_perms := ptrace_perm | '(' ptrace_perm+ ')'

After having used the cross check (permission needed in both profiles)
I am not sure it is correct for ptrace.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:38:04 -07:00
John Johansen
b222731c4f Add the ability to mediate signals.
Add signal rules and make sure the parser encodes support for them
if the supported feature set reports supporting them.

The current format of the signal rule is

  [audit] [deny] signal [<signal_perms>] [<signal_set>] <target_profile>,

  signal_perm  := 'send'|'receive'|'r'|'w'|'rw'
  signal_perms := <signal_perm> | '(' <signal_perm> ([,]<signal_perm>)* ')'
  signal := ("hup"|"int"|"quit"|"ill"|"trap"|"abrt"|"bus"|"fpe"|"kill"|
             "usr1"|"segv"|"usr2"|"pipe"|"alrm"|"term"|"tkflt"|"chld"|
             "cont"|"stop"|"stp"|"ttin"|"ttou"|"urg"|"xcpu"|"xfsz"|"vtalrm"|
             "prof"|"winch"|"io"|"pwr"|"sys"|"emt"|"exists")
  signal_set   := set=<signal> | '(' <signal> ([,]<signal>)* ')'


it does not currently follow the peer=() format, and there is some question
as to whether it should or not. Input welcome.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:35:29 -07:00
John Johansen
77cd2e34a0 Split dfa optimization and dump flag handling into a separate file so that it can be shared with DFA test programs
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-04-23 11:10:41 -07:00
John Johansen
746cecf4b7 Convert to htoleXX fns instead of ifdef on endian
This patch makes use of the htoleXX() functions (see endian(3))
defined as part of endian.h (already included in parser_interface.c),
instead of defining a function differently based on the detection of
endian related macros.

This fixes a build failure experienced on powerpc with John's patch
set applied. This patch has been updated with John's feedback to use
letoh16() in the le16_to_cpu() macro.


Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:07:49 -07:00
John Johansen
727489fffd Turn on diff-encoding if the kernel supports it
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:05:58 -07:00
John Johansen
6ecf828a13 Don't use the parser time stamp to determine if policy is newer.
Using the parser timestamp was a work around to force recompilation of
policy that was built with a buggy parser. There are better ways to
handle this so remove checking of the parser timestamp.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:01:33 -07:00
John Johansen
d05313f555 Add the ability to separate policy_version from kernel and parser abi
This will allow for the parser to invalidate its caches separate of whether
the kernel policy version has changed. This can be desirable if a parser
bug is discovered, a new version the parser is shipped and we need to
force cache files to be regenerated.

Policy current stores a 32 bit version number in the header binary policy.
For newer policy (> v5 kernel abi) split this number into 3 separate
fields policy_version, parser_abi, kernel_abi.

If binary policy with a split version number is loaded to an older
kernel it will be correctly rejected as unsupported as those kernels
will see it as a none v5 version. For kernels that only support v5
policy on the kernel abi version is written.

The rules for policy versioning should be
policy_version:
  Set by text policy language version. Parsers that don't understand
  a specified version may fail, or drop rules they are unaware of.

parser_abi_version:
  gets bumped when a userspace bug is discovered that requires policy be
  recompiled. The policy version could be reset for each new kernel version
  but since the parser needs to support multiple kernel versions tracking
  this is extra work and should be avoided.

kernel_abi_version:
  gets bumped when semantic changes need to be applied. Eg unix domain
  sockets being mediated at connect.

  the kernel abi version does not encapsulate all supported features.
  As kernels could have different sets of patches supplied. Basic feature
  support is determined by the policy_mediates() encoding in the policydb.

  As such comparing cache features to kernel features is still needed
  to determine if cached policy is best matched to the kernel.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 11:00:32 -07:00
John Johansen
b9b99508e8 Add tag indicating file policy is mediated.
Tag start of entries in the policydb as being mediated. This makes
the start state for any class being mediated be none 0. The kernel
can detect this to determine whether the parser expected mediation
for the class.

This is just a way of encoding what features expect mediation within
the policydb it self so that a separate table isn't needed.

This is also used to indicate the new unix semantics for mediation of
unix domain sockets on connect should be applied.

Note: this does cause a fail open on situation on Ubuntu Saucy, which
did not properly indicate support. That is if a kernel using this patch
is installed on an Ubuntu Saucy system, unix domain socket mediation
on connect won't happen, instead the older behavior will be applied.
This won't cause policy failures as it is less strict than what
Ubuntu Saucy applies.

This is necessary so that AppArmor can properly function on older
userspaces without a compile time configuration on the kernel to determine
behavior. A kernel expecting this behavior will function correctly
with all old userspaces expect it will not enforce connect time mediation
on Ubuntu Saucy. However Ubuntu does not support Trusty (or newer)
kernels as backports to Saucy, so this does not break them.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 10:59:07 -07:00
John Johansen
873ae31d29 fix: network detection
The features file patch broke detection of network support.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 10:55:46 -07:00
John Johansen
0d42a832c1 Hack rework of the feature/match file support
This is not the cleanup this code needs, but a quick hack to add the
-M flag so we can specify a feature file (or directory) to use for
the compile.

It mostly just moves around existing code and adds the -M option,
though it does introduce a few changes.

While I didn't do it in this patch I propose we drop support for
the match file without create support. This is several years old
now and would clean things up a lot.

Note: that the manually input -m or -M drop support for it already
I just can't see a good way to support a single input stream indicating
the result/existance of two separate files.

This needs more work but is needed to support tests and the policy_mediates
frame work depends on the policydb getting generated with the special
stub rules to indicate whether policy was compiled expecting a certain
feature. But this can break the current tests, at least once a bug
in the policy rule counting is fixed in a follow on patch.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-04-23 10:53:46 -07:00
Steve Beattie
192ca1dc57 parser: exit with error on invalid arguments
The parser currently indicates that it exited successfully if invalid
arguments are passed to it, which makes it difficult to detect when
other tools are calling it incorrectly. This patch causes it to return
'1' indicating a failure.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-02-20 16:53:18 -08:00
John Johansen
5df1ac3610 Move short_options next to long_options to make them easier to keep in sync
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-02-05 09:10:53 -05:00
Steve Beattie
0a8e97098d parser: fix --cache-loc short arg option (-L)
When the --cache-loc option was added in trunk commit 1916, it was
intended that -L would be the short form of the option (based on
documentation and usage changes). However, the commit mistakenly
did not include the short option in the list include in the call
to getopt_long(3). This patch adds it along with the indicator
that it requires an argument (the different cache location) to the
getopt_long() call.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-02-04 14:28:21 -08:00
Steve Beattie
1fd3b5ed5a parser: close file handle left opened
Close file handle left opened if parser.cfg is found and read from.
Found by cppcheck.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-24 10:59:30 -08:00
John Johansen
7ba571395e Fixes to that where dropped from the diff-encode patch
This diff is part of the diffencode patch but was dropped when it was
applied to bzr. I have no idea why and status showed a clean tree.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2014-01-09 17:24:40 -08:00
John Johansen
f0b154528d Fix dfa minimization
So DFA minimization has a bug and feature that keeps it from  minimizing
some dfas completely. This feature/bug did not result in incorrect dfas,
it just fails to result in full minimization.

The same mappings comparison is wrong. Or more correctly it is right when
transitions are not remapped to minimization partitions, but it may be
wrong when states are remapped. This means it will cause excess
partitioning (not removing all the states it should).

The trans hashing does a "guess" at partition splitting as a performance
enhancement. Basically it leverages the information that states that have
different transitions or transitions on different characters are not the
same. However this isn't always the case, because minimization can cause
some of those transitions to be altered. In previous testing this was
always a win, with only a few extra states being added some times. However
this changes with when the same mappings are fixed, as the hashing that was
done was based on the same flawed mapping as the broken same mappings.

If the same mappings are fixed and the hashing is not removed then there
is little to no change. However with both changes applied some dfas see
significant improvements. These improvements often result in performance
improvements despite minimization doing more work, because it means less
work to be done in the chfa comb compression

eg. test case that raised the issue (thanks tyler)
  /t { mount fstype=ext2, mount, }

  used to be minimized to
   {1} <== (allow/deny/audit/quiet)
   {6} (0x 2/0/0/0)

   {1} -> {2}: 0x7
   {2} -> {3}: 0x0
   {2} -> {2}: []
   {3} -> {4}: 0x0
   {3} -> {3}: []
   {4} -> {6}: 0x0
   {4} -> {7}: 0x65 e
   {4} -> {5}: []
   {5} -> {6}: 0x0
   {5} -> {5}: []
   {6}  (0x 2/0/0/0) -> {6}: [^\0x0]
   {7} -> {6}: 0x0
   {7} -> {8}: 0x78 x
   {7} -> {5}: []
   {8} -> {6}: 0x0
   {8} -> {5}: 0x74 t
   {8} -> {5}: []

  with the patch it is now properly minimized to
    {1} <== (allow/deny/audit/quiet)
    {6} (0x 2/0/0/0)

    {1} -> {2}: 0x7
    {2} -> {3}: 0x0
    {2} -> {2}: []
    {3} -> {4}: 0x0
    {3} -> {3}: []
    {4} -> {6}: 0x0
    {4} -> {4}: []
    {6}  (0x 2/0/0/0) -> {6}: [^\0x0]


The evince profile set sees some significant improvements picking a couple
example from its "minimized" dfas (it has 12) we see a reduction from 9720
states to 6232 states, and 6537 states to 3653 states. All told seeing the
performance/profile size going from
  2.8 parser: 4.607s 1007267 bytes
  dev head:   3.48s  1007267 bytes
  min fix:    2.68s  549603 bytes

of course evince is an extreme example so a few more

firefox
   2.066s   404549 bytes
 to
   1.336s   250585 bytes


cupsd
   0.365s   90834 bytes
 to
   0.293s   58855 bytes

dnsmasq
   0.118s   35689 bytes
 to
   0.112s   27992 bytes


smbd
   0.187s   40897 bytes
 to
   0.162s   33665 bytes


weather applet profile from ubuntu touch
   0.618s   105673 bytes
 to
   0.432s   89300 bytes


I have not seen a case where the parser regresses on performance but it is
possible. This patch will not cause a regression on generated policy size,
at worst it will result in policy that is the same size

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-01-09 17:06:48 -08:00
John Johansen
22855508e8 Add Differential State Compression to the DFA
Differential state compression encodes a state's transitions as the
difference between the state and its default state (the state it is
relative too).

This reduces the number of transitions that need to be stored in the
transition table, hence reducing the size of the dfa.  There is a
trade off in that a single input character may have to traverse more
than one state.  This is somewhat offset by reduced table sizes providing
better locality and caching properties.

With carefully encoding we can still make constant match time guarentees.
This patch guarentees that a state that is differentially encoded will do at
most 3m state traversal to match an input of length m (as opposed to a
non-differentially compressed dfa doing exactly m state traversals).
In practice the actually number of extra traversals is less than this becaus
we selectively choose which states are differentially encoded.

In addition to reducing the size of the dfa by reducing the number of
transitions that have to be stored.  Differential encoding reduces the
number of transitions that need to be considered by comb compression,
which can result in tighter packing, due to a reduction in sparseness, and
also reduces the time spent in comb compression which currently uses an
O(n^2) algorithm.

Differential encoding will always result in a DFA that is smaller or equal
in size to the encoded DFA, and will usually improve compilation times,
with the performance improvements increasing as the DFA gets larger.

Eg. Given a example DFA that created 8991 states after minimization.
* If only comb compression (current default) is used

 52057 transitions are packed into a table of 69591 entries. Achieving an
 efficiency of about 75% (an average of about 7.74 table entries per state).
 With a resulting compressed dfa16 size of 404238 bytes and a run time for
 the dfa compilation of
   real 0m9.037s
   user 0m8.893s
   sys  0m0.036s

* If differential encoding + comb compression is used, 8292 of the 8991
  states are differentially encoded, with 31557 trans removed.  Resulting in

  20500 transitions are packed into a table of 20675 entries.  Acheiving an
  efficiency of about 99.2% (an average of about 2.3 table entries per state
  With a resulting compressed dfa16 size of 207874 bytes (about 48.6%
  reduction) and a run time for the dfa compilation of
   real 0m5.416s (about 40% faster)
   user 0m5.280s
   sys  0m0.040s

Repeating with a larger DFA that has 17033 states after minimization.
* If only comb compression (current default) is used

 102992 transitions are packed into a table of 137987 entries.  Achieving
 an efficiency of about 75% (an average of about 8.10 entries per state).
 With a resultant compressed dfa16 size of 790410 bytes and a run time for d
 compilation of
  real  0m28.153s
  user  0m27.634s
  sys   0m0.120s

* with differential encoding
 39374 transition are packed into a table of 39594 entries. Achieving an
 efficiency of about 99.4% (an average of about 2.32 entries per state).
 With a resultant compressed dfa16 size of 396838 bytes (about 50% reduction
 and a run time for dfa compilation of
  real  0m11.804s (about 58% faster)
  user  0m11.657s
  sys   0m0.084s

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-01-09 16:55:55 -08:00
Steve Beattie
260d73f752 parser: Add make variable to build against local or system libapparmor [v3]
By default, statically link against the in-tree libapparmor. If the
in-tree libapparmor is not yet built, print a helpful error message. To
build against the system libapparmor, the USE_SYSTEM make
variable can be set on the command line like so:

  $ make USE_SYSTEM=1

This patch also fixes issues around the inclusion of the apparmor.h
header. Previously, the in-tree apparmor.h was always being included
even if the parser was being linked against the system libapparmor.
It modifies the apparmor.h include path based on the previous patch
separating them out in the libapparmor source. This was needed because
header file name collisions were already occurring.

For source files needing to include apparmor.h, the make targets were
also updated to depend on the local apparmor.h when building against
the in-tree libapparmor.  When building against the system libapparmor,
the variable used in the dependency list is empty. Likewise, a
libapparmor.a dependency is added to the apparmor_parser target when
building against the in-tree apparmor.

Patch history:
  v1: from Tyler Hicks <tyhicks@canonical.com>
      - initial version
  v2: revert to altering the include search path rather than including
      the apparmor.h header directly via cpp arguments, alter the
      include statements to <sys/apparmor.h> which will work against
      either in-tree or (default) system paths.
  v3: convert controlling variable to USE_SYSTEM from SYSTEM_LIBAPPARMOR
      to unify between the parser and the regression tests.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Steve Beattie <steve@nxnw.org>
2014-01-06 14:46:10 -08:00
Tyler Hicks
825f5864d3 parser: Check for kernel support prior to processing dbus entries
When a parser that is aware of dbus rules is running under a kernel
that is unaware of dbus rules, the parser should ignore the dbus rules
instead of attempting to load them into the kernel. Otherwise, the
kernel will reject the entire profile, leaving the application
unconfined.

Similar to what is done for mount rules, the features listed in
apparmorfs should be checked to see if dbus is supported under the
current kernel.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-10-29 17:03:23 -07:00
John Johansen
38934d74ae allow directories to be passed to the parser
Allow directories to be passed directly to the parser and handled instead
of needing an initscript to find the files in the directory.

eg. load all profiles in profiles dir
  apparmor_parser -r /etc/apparmor.d/

eg. load all binary files in the cache dir
  apparmor_parser -Br /etc/apparmor.d/cache/

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-10-26 00:15:13 -07:00
Steve Beattie
aa53ef66e2 parser - build against in-tree libapparmor
With trunk commit 2205 "use libapparmor's find mountpoint fn",
the parser now builds against and uses libapparmor at runtime. However,
it currently builds against the system installed libapparmor library and
header files, which fails if either aren't installed, and is thus
painful for bootstrapping in a new environment.

Instead, the parser, like pam_apparmor and mod_apparmor, should build
against the in-tree libapparmor header and library. This patch does
that and adjusts the tests to point LD_LIBRARY_PATH at the location
of the built library as well.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-10-15 16:46:18 -07:00