2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-02 23:35:37 +00:00

Compare commits

..

84 Commits

Author SHA1 Message Date
Steve Beattie
b37bd8a1aa Point makefile at correct launchpad branch to generate tarball from. 2015-04-23 12:46:45 -07:00
Christian Boltz
ead71a306a Enable testloops for nosetests
Ensure nosetests sees all tests in the tests[] tuples. This requires
some name changes because nosetests thinks all function names containing
"test" are tests. (A "not a test" docorator would be an alternative, but
that would require some try/except magic to avoid a dependency on nose.)

To avoid nosetests thinks the functions are a test,
- rename setup_all_tests() to setup_all_loops()
- rename regex_test() to _regex_test() (in test-regex_matches.py)

Also add the module_name as parameter to setup_all_loops and always run
it (not only if __name__ == '__main__').

Known issue: nosetests errors out with
    ValueError: no such test method in <class ...>: stub_test
when trying to run a single test generated out of tests[].
(debugging hint: stub_test is the name used in setup_test_loop().)
But that's still an improvement over not seeing those tests at all ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-22 22:03:36 +02:00
Christian Boltz
aa45be1c10 Fix crash in serialize_profile_from_old_profiles()
Assume you have a profile like

    /bin/foo {
      /etc/ r,
      network,
      /usr/ r,
    }

(important: there must be be a non-path rule between the two path blocks)

Then run aa-logprof and add another path event. When choosing (V)iew changes,
it will crash with a misleading

  File ".../utils/apparmor/aamode.py", line 205, in split_mode
      other = mode - user
      TypeError: unsupported operand type(s) for -: 'collections.defaultdict' and 'set'

The reason for this is our beloved hasher, which is playing funny games
another time.

The patch wraps the hasher usage with a check for the parent element to
avoid auto-creation of empty childs, which then lead to the above crash.


BTW: This is another issue uncovered by the LibreOffice profile ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-16 13:11:39 +02:00
Steve Beattie
c1c5192532 profiles: update postfix-common abstraction
Merge from trunk revision 3012

Update the postfix-common abstraction to cope with signal and unix
socket mediation, update the access to the sasl library locations
in a multiarch compliant way, and allow access to limited bits
of the filesystem paths under which postfix chroots itself to
(/var/spool/postfix/ on Ubuntu).

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-04-15 23:35:52 -07:00
Christian Boltz
2b9260f27a Fix serialize_profile_from_old_profiles() to not crash on "@{var} +="
serialize_profile_from_old_profiles() calls store_list_var() with an
empty hasher. This fails for "+=" because in this case store_list_var()
expects a non-empty hasher with the variable already defined, and raises
an exception because of the empty hasher.

This patch sets "correct = False" if a "+=" operation appears, which
means the variable will be written in "clean" mode instead.

Adding proper support for "add to variable" needs big changes (like
storing a variable's "history" - where it was initially defined and what
got added where).



Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-16 02:02:02 +02:00
Christian Boltz
4063647a5f fix handling of adding to variables
the LibreOffice profile uncovered that handling of @{var} += is broken:

  File ".../utils/apparmor/aa.py", line 3272, in store_list_var
    var[list_var] = set(var[list_var] + vlist)
TypeError: unsupported operand type(s) for +: 'set' and 'list'

This patch fixes it:
- change separate_vars() to use and return a set instead of a list
  (FYI: separate_vars() is only called by store_list_var())
- adoptstore_list_var() to expect a set
- remove some old comments in these functions
- explain the less-intuitive parameters of store_list_var()

Also add some tests for separate_vars() and store_list_var().
The tests were developed based on the old code, but not all of them
succeed with the old code.

As usual, the tests uncovered some interesting[tm] behaviour in
separate_vars() (see the XXX comments and tell me what the really
expected behaviour is ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-16 01:59:10 +02:00
Christian Boltz
b4048cf3de logparser.py: change mask only for path events
Move the code that does the c -> a and d -> w replacement in denied_mask
and requested_mask so that it only runs for path and exec events, but not
for other events (like dbus and ptrace). The validate_log_mode() and
log_str_to_mode() calls are also moved.

Technically, this means moving code from parse_event() to the path
and exec sections in add_event_to_tree().

This also means aa-logprof no longer crashes if it hits a ptrace or
dbus event in the log.

The "if dmask:" and "if rmask:" checks are removed - if a path event
doesn't have these two, it is totally broken and worth a aa-logprof
crash ;-)

Also adjust the parse_event() tests to expect the "raw" mask instead of
a set.

Note: the 2.9 branch doesn't contain test-capability.py, therefore I
skipped this part of the patch for obvious reasons ;-)

This patch fixes
https://bugs.launchpad.net/apparmor/+bug/1426651 and
https://bugs.launchpad.net/apparmor/+bug/1243932


I manually tested that
- c and d log events are still converted to a and w
- aa-logprof handles exec events correctly
- ptrace events no longer crash aa-logprof

Note: add_event_to_tree() is not covered by tests.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-16 01:53:39 +02:00
Christian Boltz
8a475341e8 utils: simplify serialize_parse_profile_start()
Merge from trunk revision 3001

Change serialize_parse_profile_start() to use parse_profile_start()
instead of using duplicated code.

The behaviour is mostly kept, with the exception that the function is
more strict now and raises exceptions instead of ignoring errors.

In practise, this won't change anything because the profiles are parsed
with parse_profile() (which calls parse_profile_start()) - and that
already errors out.

The tests are updated to match the more strict behaviour.

The next step would be to drop serialize_parse_profile_start()
completely, but this isn't urgent and can/should be done when we have
test coverage for serialize_profile_from_old_profile() one day ;-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 19:07:47 -07:00
Christian Boltz
5ca6986b43 utils: fix is_skippable_dir() and add tests
Merge from trunk revision 3000

Fix is_skippable_dir() - the regex also matched things like
/etc/apparmor.d/dont_disable, while it should match on the full
directory name.

Also add some tests based on a real-world aa-logprof run (with "print (path)"
in is_skippable_dir()) and some additional "funny"[tm] dirs.

Needless to say that the tests
        ('dont_disable',                False),
        ('/etc/apparmor.d/cache_foo',   False),
will fail with the old is_skippable_dir().

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 19:00:47 -07:00
Christian Boltz
4b58cf3bc4 utils: replace RE_PROFILE_START
Merge from trunk revision 2999

Replace RE_PROFILE_START with RE_PROFILE_START_2 and adjust all
code sections that used RE_PROFILE_START_2.

The only real change is that test_get_flags_invalid_01 and
test_get_flags_invalid_02 now expect AppArmorException instead of
AppArmorBug.

Acked-by: Steve Beattie <steve@nxnw.org> for trunk
2015-04-13 18:58:25 -07:00
Christian Boltz
a373b4ee93 utils: implement attachment handling after rewriting set_profile_flags()
to use write_header(), and making set_profile_flags
more strict.

Merge from trunk revisions 2996, 2997, and 2998.

Changes in set_profile_flags():
- rewrite set_profile_flags to use parse_profile_start_line() and
  write_header().
- replace the silent failure for non-existing files with a proper
  exception (using lazy programming - the check is done by removing the
  "if os.path.isfile()" check, open_file_read then raises the
  exception ;-)
- comment out regex_hat_flag and the code that was supposed to handle
  hat flags, which were totally broken. We'll need another patch to fix
  it, and we also need to decide if we want to do that because it
  introduces a behaviour change (currently, aa-complain etc. don't
  change hat flags).

The tests for set_profile_flags() are also updated:
- prepend a space to comments because write_header always adds a space
  between '{' and the comment
- remove a test with superfluous quotes that are no longer kept
  (that's
  just a profile cleanup, so dropping that test is the easiest way)
- update test_set_flags_10 and test_set_flags_12 to use the correct
  profile name
- enable the tests for invalid (empty) flags
- update the test for a non-existing file

this patch makes set_profile_flags more strict:
- raise AppArmorBug if newflags contains only whitespace
- raise AppArmorBug if the file doesn't contain the specified profile or
  no profile at all

The tests are adjusted to expect AppArmorBug instead of a silent
failure. Also, some tests are added for profile=None, which means to
change the flags for all profiles in a file.
- test_set_flags_08 is now test_set_flags_invalid_04
- test_set_flags_invalid_03 is changed to only contain one reason for
  a failure, not two ;-)

Finally implement attachment handling

This patch implements attachment handling - aa-logprof now works with
profiles that have an attachment defined, instead of ignoring audit.log
entries for those profiles.

Changes:
- parse_profile_start_line(): remove workaround that merged the
  attachment into the profile name
- parse_profile_data(): store attachment when parsing a profile
- update test_parse_profile_start_03,
  test_serialize_parse_profile_start_03,
  test_set_flags_nochange_09 and some parse_profile_start_line() tests -
  they now expect correct attachment handling

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:53:59 -07:00
Christian Boltz
8d5569f20b utils: rewrite parse_profile_start()
Merge from trunk revision 2990

Rewrite parse_profile_start() in aa.py to a more readable version.
The behaviour remains unchanged (and is covered by tests).

Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-13 18:49:37 -07:00
Christian Boltz
5390777e45 utils: add tests for RE_PROFILE_START_2 and parse_profile_start_line()
Merge from trunk revision 2989

Also add AANamedRegexTest class that can be used to test a regex with
named match groups.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:47:12 -07:00
Christian Boltz
79240e7ddd utils: test new parameters of write_header()
Merge from trunk revision 2988

Change the write_header tests so that the 'profile_keyword' and
'header_comment' parameters can be (and are) tested:
- add a None for both to the existing tests
- add some tests that come with the profile keyword and/or a comment

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:45:05 -07:00
Christian Boltz
494daee246 utils: extend and partially rewrite write_header()
Merge from trunk revision 2987

- add support for prof_data['header_comment'] (comment after '{')
  and prof_data['profile_keyword'] (to force the 'profile' keyword, even
  if it isn't needed) to write_header().
  (set_profile_flags() will be the only user of these two for now)

- fix a crash if depth is not an integer - for example,
      len('   ')/2   # 3 spaces = 1.5
  would cause a crash.
  Also add a test for 1.5 and 1.3 spaces.

- rewrite the handling of flags to avoid we have to maintain two
  different template lines.

- update the tests to set 'profile_keyword' and 'header_comment' to None.
  This avoids big changes in the test code. I'll send another patch that
  makes sure profile_keyword and header_comment are tested ;-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:41:59 -07:00
Christian Boltz
194cbfa94c utils: add attachment to parse_profile_start() return values
Merge from trunk revision 2986

Add the attachment to the parse_profile_start() and
serialize_parse_profile_start() return values, and adjust the functions
calling the *parse_profile_start() functions to save the attachment in
the "attachment" variable (which isn't used yet).

Also adjust the tests for the added return value.

(Sorry for not getting the resultset right from the beginning!)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:36:42 -07:00
Christian Boltz
9452e1e2af utils: Add support for attachments to write_header()
Merge from trunk revision 2985

Also fix a little bug that added the profile keyword if the path needed
quotes (profile "/foo bar" - but "/foo bar" is enough). This was caused
by a regex that always matched on quoted paths (hint: "/ matches
^[^/] ;-)

Also add some tests with attachments and update the test for the bugfix
mentioned above.

Now the remaining part is to make sure that prof_data['attachment'] gets
set when parsing the profiles :-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:34:33 -07:00
Christian Boltz
1556f782e3 utils: add tests for set_profile_flags() (and some fun)
Merge from trunk commit 2983

Add various tests for set_profile_flags, and document various
interesting[tm] things I discovered while writing the tests (see
the inline comments for details).

Also adds a read_file() function to common_test.py.

The most interesting[tm] thing I found is:
    regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$')
which matches various unexpected things - but not a hat :-/
(see mailinglist for all funny details)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:31:53 -07:00
Christian Boltz
7d1ff607fe utils: add and use parse_profile_start_line(); convert
serialize_parse_profile_start() to use parse_profile_start_line();
update test-aa.py to match parse_profile_start() and
get_profile_flags() changes

Merge from trunk commits 2978, 2979, and 2982

Add the parse_profile_start_line() function to regex.py, which is
a wrapper for RE_PROFILE_START_2 and returns an array with named matches.

Also change some places in aa.py from using RE_PROFILE_START to
the parse_profile_start_line() function.

Notes: - until everything is migrated to the new function, I'll
keep the old
  RE_PROFILE_START unchanged - that's the reason to add the new
  regex as RE_PROFILE_START_2
- the patch changes only aa.py sections that are covered by tests
  already (which means some users of RE_PROFILE_START are remaining)
- parse_profile_start_line() merges 'profile' and 'attachment' into
  'profile' (aka the old, broken behaviour) until aa.py can handle
  the attachment properly. The alternative would be to ignore
'attachment', which would be worse.

Convert serialize_parse_profile_start() to use
parse_profile_start_line(), and adjust a test to expect an AppArmorBug
instead of an AttributeError exception.

Also add two tests (they succeed with the old and the new code).
Note that these tests document interesting[tm] behaviour - I tend to
think that those cases should raise an exception, but I'm not sure about
this because serialize_profile_from_old_profile() is a good example for
interesting[tm] code :-/

I couldn't come up with a real-world test profile that would hit those
cases without erroring out aa-logprof earlier - maybe the (more
sane-looking) parse_profiles() / serialize_parse_profile_start()
protects us from hitting this interesting[tm] behaviour.

The previous patch slightly changed the behaviour of parse_profile_start()
and get_profile_flags() - they raise AppArmorBug instead of
AppArmorException when specifying a line that is not the start of a
profile and therefore doesn't match RE_PROFILE_START_2.

This patch updates test-aa.py to expect the correct exceptions, and adds
another test with quoted profile name to ensure that stripping the
quotes works as expected.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:24:20 -07:00
Steve Beattie
242ece320a utils: merge test-only changes from trunk
Merge from trunk revisions 2976+2980, 2977, 2981, and 2984.
2015-04-13 18:03:55 -07:00
Christian Boltz
dc1d8e5253 add tests for write_header()
Merge from trunk revision 2984

Also add loop support to test-aa.py.

BTW: In case you wonder - the need to replace unittest.TestCase with
AATest is intentional. It might look annoying, but it makes sure that
a test-*.py file doesn't contain a test class where tests = [...] is
ignored because it's still unittest.TestCase.
(Technically, setup_all_tests() will error out if a test class doesn't
contain tests = [...] - either explicit or via its parent AATest.)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:42:40 -07:00
Christian Boltz
0ac23ee34a add tests for serialize_parse_profile_start() to test-aa.py
to document the function's behaviour.
Merge from trunk revision 2981.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:38:08 -07:00
Christian Boltz
5bc15cda41 Convert test-regex_matches.py to the new tests[] loop.
Merge from trunk revision 2977

The test behaviour is the same with and without this patch - 166 tests
run, all successful.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:32:15 -07:00
Christian Boltz
9ebb1913bd add better loop support to common_test.py
Merge from trunk revisions 2976 and 2980

Add better support for looping over a tests[] array to common_test.py:
- class AATest - a base class we can use for all tests, and that will
  probably get more features in the future (for example tempdir
  handling)
- setup_all_tests() - a function that iterates over all classes in the
  given file and calls setup_test_loops() for each of them
- setup_tests_loop() - a function that creates tests based on tests[]
  in the given class. Those tests call the class' _run_test() method for
  each test specified in tests[]  (inspired by setup_regex_tests() ;-)

This means we can get rid of the manually maintained tests list in
test-regex_matches.py and just need to call setup_all_tests() once in
each file.

The patch also adds test-example.py, which is
- a demo of the code added to common_test.py
- a template file that we can copy for future test-*.py

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:28:48 -07:00
Christian Boltz
720f6624e6 write_net_rules() fixes, part 3
Thanks to the used data structure, write_net_rules() replaces bare
'network,' rules with the invalid 'network all,' when saving a profile.
This patch makes sure a correct 'network,' rule is written.

Also reset 'audit' to avoid all (remaining) rules get the audit flag
after writing an audit network rule.

Note: The first section of the function (that claims to be responsible
for bare 'network,' rules) is probably never hit - but I'm not too keen
to remove it and try it out ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-11 02:21:05 +02:00
Christian Boltz
387de4458f Fix doubled arrow in exec rules
When parsing a profile with named exec rules, the exec target included
the arrow. This resulted in two arrows when writing the profile (and one
more each time the profile was updated).

Fix this by using the match group that only contains the exec target
without the arrow in parse_profile_data() and
serialize_profile_from_old_profile().

References: https://bugs.launchpad.net/apparmor/+bug/1437901


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-11 02:16:08 +02:00
Steve Beattie
38a69f5ebc profiles: allow ubuntu-helpers to generate texlive fonts
Merge from trunk revision 3004

When evince opens a dvi file, it updates the user fonts using
texlive commands in /usr/share/texlive/texmf-dist/web2c/ (or possibly
/usr/share/texlive/texmf/web2c/ in older releases). This patch adjusts
the sanitized_helper profile to allow these tools to run.

Bug: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1010909

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2015-04-10 09:52:36 -07:00
Christian Boltz
7d84c61b6c Fix writing network rules, part 2
write_net_rules() doesn't add a space after 'audit' in two of three
cases, leading to invalid network rules.
This patch adds the missing spaces.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9
2015-04-10 01:53:42 +02:00
Christian Boltz
f836ebd42b Fix writing network rules
write_net_rules() creates invalid rules for network rules with one
parameter (for example "network bluetooth").
Add a trailing comma to create valid rules.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9.
2015-04-09 13:29:09 +02:00
Christian Boltz
52b6aeb04c logparser.py: merge path handling in add_event_to_tree()
Merge path handling for 'inode_*' in add_event_to_tree() with the
handling for other path events.

The code is slightly more strict now - 'inode_' in e['operation'] is
replaced with e['operation'].startswith('inode_').

This patch is a cleanup and also a preparation to fix
https://bugs.launchpad.net/apparmor/+bug/1426651 and
https://bugs.launchpad.net/apparmor/+bug/1243932


Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked for both 2.9 and trunk.
2015-04-03 17:45:48 +02:00
Christian Boltz
475a9bc691 honor 'chmod' events in logparser.py / aa-logprof
aa-logprof doesn't ask anything for

type=AVC msg=audit(1427633461.202:281): apparmor="DENIED" operation="chmod" profile="/usr/lib64/firefox/plugin-container" name="/home/cb/.config/ibus/bus/" pid=7779 comm="plugin-containe" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000

This patch fixes this by adding 'chmod' to the list of file operation
types in logparser.py.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9.
2015-04-03 17:44:38 +02:00
Christian Boltz
0f7bf53afb Tell python2 about math
if 3/2 == 1:
    print("python2 inside")

Add "from __future__ import division" so that python2 returns the
correct result (if needed, as float)

On related news: At least python3 knows how to calculate correctly.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-02 23:40:15 +02:00
Jamie Strandboge
8dcd54e365 cherrypick from trunk:
add --include-templates-dir and --include-policy-groups-dir options to easyprof
  to support framework policy on Snappy for Ubuntu Core

  Signed-off-by: Jamie Strandboge <jamie@canonical.com>
  Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-31 16:24:31 -05:00
Steve Beattie
097eb4258f fix two issues for older linux releases
Merge from trunk revision 2975

The following patch addresses two issues on older releases:

1) In trunk commit 2911, the line 'undefine VERBOSE' was added to
   parser/tst/Makefile so that the equality tests would not generate
   verbose output when $VERBOSE != 1. Unfortunately, the 'undefine'
   keyword was not introduced in GNU Make until version 3.82. On
   distro releases like Ubuntu 12.04 LTS that include versions of Make
   older than that, make check and make clean abort when VERBOSE is
   not set to 1. The patch fixes that by setting VERBOSE to a zero
   length string if does not already equal 1.

2) In trunk commit 2923, a workaround for systemd as init was added
   to the pivot_root regression test. The workaround included a
   call to ps(1) to determine if systemd is pid 1. Unfortunately,
   in older versions of the procps package (such as the version in
   Ubuntu 12.04 LTS), 'ps -hp1' emits the warning

     Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html

   The patch below converts the ps call to 'ps hp1' which does not
   generate the warning.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-31 02:50:40 -07:00
Cameron Norman
9bc15eb6b8 profiles: update dnsmasq profile for lxc support
Merge from trunk revision 2974

Patch from Cameron Norman <camerontnorman@gmail.com> based on a patch
from Christian Boltz <apparmor@cboltz.de>.

This patch allows /var/lib/misc/dnsmasq.*.leases rw and
/{,var/}run/lxc/dnsmasq.pid rw for LXC networking setup.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-30 22:26:32 -07:00
Seth Arnold
9d6f7f53cb Add new gdm path for Xauthority file
Bruce Pieterse reports that AppArmor denied evince, among other
applications, from starting properly:
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1432126

He tested a slight variant of the attached patch and reported success. I
propose this patch for both trunk and 2.9.

Signed-off-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 15:32:29 -07:00
Steve Beattie
c1ae887576 tests: work around systemd mounting / shared in pivot_root tests
Merge from trunk revision 2923


The systemd init daemon mounts the / filesystem as shared [1], which
breaks pivot_root(2). The following patch adjusts the pivot_root
test script to remount / as private if it detects that its shared,
allowing the tests to run successfully, and then undoes it once the
tests are complete.

[1] http://cgit.freedesktop.org/systemd/systemd/commit/?id=b3ac5f8cb98757416d8660023d6564a7c411f0a0

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-24 17:12:18 -07:00
Steve Beattie
0ec6ce96d2 parser: fix compilation failure of deny link rules, expand equality tests
Merge from trunk commits 2909, 2910, 2911, and 2912

BugLink: http://bugs.launchpad.net/bugs/1433829

The apparmor_parser fails to compile deny rules with only link
permissions.

  Eg.
       deny /f l,
       deny l /f,
       deny link /f -> /d,

Will all fail to compile with the following assert

  apparmor_parser: aare_rules.cc:99: Node* convert_file_perms(int, uint32_t, uint32_t, bool): Assertion `perms != 0' failed.

NOTE: this is a minimal patch a bigger patch that cleans-up and separates
      and reorganizes file, link, exec, and change_profile rules is needed

parser: Expand Equality tests

This adds several new equality tests and turned up a couple of more
bugs
https://launchpad.net/bugs/1433829
https://launchpad.net/bugs/1434018

- add link/link subset tests
- add pix, Pix, cix, Cix, pux, Pux, cux, Cux and specified profile
  transitions (/f px -> b ...)
- test equality of leading and trailing permission file rules
  ie.   /foo rw, == rw /foo,
- test that specific x match overrides generic x rule. ie.
  /** ix, /foo px, is different than /** ix, /foo ix,
- test that deny removes permission
  /f[abc] r, deny /fb r,  is differnt than /f[abc] r,

In addition to adding the new tests, it changes the output of the
equality tests, so that if the $verbose variable is not set successful
tests only output a period, with failed tests outputing the full
info.  If verbose is set the full test info is output as before.

It also does:

- make the verbose output of equality.sh honor whether or not
  the environment variable VERBOSE is set
- thereby making the output verbose when 'make check V=1' or 'make
  check VERBOSE=1' is given from within the parser/ directory. This
  will make distribution packagers happy when diagnosing build
  failures caused by test failures.
- if verbose output is not emitted and the tests were successful, emit
  a newline before printing PASS.
- verify audit and audit allow is equal
- verify audit differs from deny and audit deny
- verify deny differs from audit deny
- make the verbose text a little more useful for some cases
- correct overlap exec tests to substitute in looped perms

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-23 12:43:57 -07:00
Christian Boltz
8c19eb5521 dovecot auth needs to read openssl.cnf
Darix' guess is that this is needed by libpq because he uses a postgresql
database with dovecot and has ssl enabled in postgresql.

Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9
2015-03-19 13:58:11 +01:00
Steve Beattie
21a41deabe parser: fix equality and valgrind test scripts to use features file
Merge from trunk commit revision 2907

This patch fixes the equality test script and the valgrind wrapper
script to make the parser under test use the features.all features file
from the features_files/ subdirectory. Otherwise, the equality tests
will fail on systems where the not all of the current language features
are supported. The equality fix does so in a way to make the script work
correctly regardless of the directory it is run from.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-19 04:37:25 -07:00
Steve Beattie
576e8fe33b parser: fix warning in net_find_af_name
Merge from trunk commit 2906

The fix to prevent the compiler from SEGV'ing when dumping network
rules in commit 2888 introduced the following compiler warning:

  network.c: In function ‘const char* net_find_af_name(unsigned int)’:
  network.c:331:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {

The problem is that the counter i is an int, but sizeof returns size_t
which is unsigned. The following patch fixes the issue by converting the
type of i to size_t.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-19 00:14:12 -07:00
Tyler Hicks
3c928c04e1 parser: Test the 'allow' modifier
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-18 12:34:49 -05:00
Tyler Hicks
37b872b155 parser: Test the 'audit allow' modifier
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:44 -05:00
Tyler Hicks
5ab8b7a483 parser: Verify policies change with the audit and deny modifiers
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:41 -05:00
Tyler Hicks
b813f4ba53 parser: Add ability to test the inequality of binary policies
Previously, we only had the ability to test that binary policy files
were equal. This patch allows for the testing of binary policy files
that are not equal.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:38 -05:00
John Johansen
05ab11fec4 Fix compilation of audit modifiers
cherry-pick: -r2901

This fixes the incorrect compilation of audit modifiers for exec and
pivot_root as detailed in

https://launchpad.net/bugs/1431717
https://launchpad.net/bugs/1432045

The permission accumulation routine on the backend was incorrectly setting
the audit mask based off of the exec type bits (info about the exec) and
not the actual exec permission.

This bug could have also caused permissions issues around overlapping exec
generic and exact match exec rules, except the encoding of EXEC_MODIFIERS
ensured that the
  exact_match_allow & AA_USER/OTHER_EXEC_TYPE
  test would never fail for a permission accumulation with the exec permission
  set.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-18 10:22:31 -07:00
Christian Boltz
2d7ba0871f Split off serialize_parse_profile_start_line() from
serialize_profile_from_old_profile() in aa.py, as a preparation to add
tests and then switch to the upcoming RE_PROFILE_START wrapper function.

Besides moving the code, I replaced write_prof_data[profile][hat]['profile']
and write_prof_data[profile][hat]['external'] with function parameters
to avoid that I have to pass around the full write_prof_data.

Note: The "lineno" parameter is technically superfluous - I kept it to
have the parameters as close to parse_profile_start() as possible and
hope that I can merge those functions later (when we have test coverage).


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-03-10 19:09:16 +01:00
Christian Boltz
c98b26069a tools.py: add functions to unload and reload profiles
and change the code to use them

Also add a comment to act() that it's only used by aa-cleanprof.

Note: The new functions add the --base parameter to the apparmor_parser
calls, which also means the disable directory inside the given profile
dir (and not always /etc/apparmor.d/disable) is now honored.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-03-07 20:32:11 +01:00
Christian Boltz
70dc81c4fd merge 'path' if conditions in logparser.py / add_event_to_tree()
logparser.py / add_event_to_tree() has 5 places to handle 'path' events.
This patch merges most if conditions to reduce that to 2 places.

It also makes the matching a bit more strict - instead of using 'in',
'xattr' has to be an exact match and 'file_' is matched with startswith().

Also, 'getattr' is added to the list of file events.


Acked-by: Steve Beattie <steve@nxnw.org> (also for 2.9)



---------- trunk only, unclear for 2.9 --------------
2015-03-07 20:26:32 +01:00
Christian Boltz
1b68baf7a3 let load_include raise an exception if an include file can't be found
instead of ignoring the error silently

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-03-07 13:28:41 +01:00
Christian Boltz
6af7faa2b7 add read_profiles() call to cmd_disable()
Without it, aa-disable
- didn't error out when hitting a broken profile directory
- didn't find a profile if it doesn't use the default naming scheme
  (for example /bin/true profile hiding in bin.false)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-03-07 13:27:57 +01:00
Steve Beattie
a1529a16bd profiles: add mir abstraction
Merge from trunk revision 2893

As mir has come into use in Ubuntu touch and is available for testing on
Ubuntu desktop, confined apps need access to a few mir specific things.
This patch adds a mir abstraction.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-05 11:51:16 -08:00
Steve Beattie
321a2c1dcb regression tests: fix gcc-5 inline confusion
Merge from trunk revision 2889

Parts of the regression tests that use the do_open() inline function
from changehat.h fail to build under gcc-5 like so:

  cc -g -O0 -Wall -Wstrict-prototypes    changeprofile.c  -lapparmor -o changeprofile /tmp/ccT6GE6k.o: In function `main':
    /home/ubuntu/bzr/apparmor/tests/regression/apparmor/changeprofile.c:43: undefined reference to `do_open'
    collect2: error: ld returned 1 exit status
    <builtin>: recipe for target 'changeprofile' failed

This patch converts the do_open function declaration to be static
inline, which apparently keeps gcc-5 from getting confused.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-03 23:32:26 -08:00
Alain BENEDETTI
735ef5d32b utils/aa-status: don't crash when non-ASCII mountpoints are in use
Merge from trunk revision 2892

aa-status was crashing when parsing through /proc/mounts looking
to see if and where the securityfs synthetic file system is mounted
if there was a mount point that contained characters outside of the
charset in use in the environment of aa-status. This patch fixes the
issue by converting the read of /proc/mounts into a binary read and
then uses decode on the elements.

Patch by Alain BENEDETTI.
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-03 22:25:32 -08:00
Tyler Hicks
9428498d90 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
Christian Boltz
3ea1e541c7 Add test for disconnected path
As a follow-up to the logparser.py change that converts disconnected
path events to an error, add a testcase to test-logparser.py.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-03-03 22:18:24 +01:00
Philip Withnall
29b0634f34 parser: net_find_af_name: do not assume that address families are consecutive,
remove unused net_find_af_val function, and network_families array
Merge from trunk commit 2888.

net_find_af_name: do not assume that address families are consecutive

The network_families array is automatically built from AF_NAMES, which is
extracted from the defines in <bits/socket.h>. The code assumes that
network_families is indexed by the AF defines. However, since the
defines are sparse, and the gaps in the array are not packed with
zeroes, the array is shorter than expected, and the indexing is wrong.

When this function was written, the network families that were
covered might well have been consecutive, but this is no longer true:
there's a gap between AF_LLC (26) and AF_CAN (29).

This assumption caused a crash in our testing while parsing the rule
"network raw".

Remove unused net_find_af_val function, and network_families array

Like net_find_af_name, this assumed that AF_* values were consecutive.

Patches from Philip Withnall and Simon McVittie.
2015-03-03 12:04:13 -08:00
Christian Boltz
586222c94e move strip_quotes() from aa.py to regex.py
The upcoming function parse_profile_start() (which is a wrapper around
the updated RE_PROFILE_START, and will live in regex.py) needs
strip_profile(), but importing it from aa.py fails with an import loop.
Therefore this patch moves strip_quotes() from aa.py to regex.py and
re-imports it into aa.py.

As a bonus, the patch also adds some tests for strip_quotes() ;-)


Also add TestStripQuotes to the test_suite list because it won't run
otherwise.

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9
2015-03-03 20:18:30 +01:00
Christian Boltz
232b51504c let logparser.py parse_event() change disconnected path events to 'ERROR'
This means that aa-logprof will ignore the event instead of crashing with
    AppArmorException: 'Unexpected rank input: var/run/nscd/passwd'

Note that I made the check as specific as possible to be sure it doesn't
hide other events.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=918787



Acked-by: Steve Beattie <steve@nxnw.org> for 2.9



(This is a backport of trunk r2877, but without the test-capability.py
adjustment because that file doesn't exist in 2.9)
2015-03-03 12:34:47 +01:00
Christian Boltz
df099620dd aa.py: split off parse_profile_start() from parse_profile_data() and add tests
Move the code for parsing the profile start ("/foo {") from aa.py
parse_profile_data() to a separate function parse_profile_start().

Most of the changes are just moving around code, with some small
exceptions:
- instead of handing over profile_data to parse_profile_start() to
  modify it, it sets two variables (pps_set_profile and
  pps_set_hat_external) as part of its return value, which are then
  used in parse_profile_data() to set the flags in profile_data.
- existing_profiles[profile] = file   is executed later, which means
  it used the strip_quotes() version of profile now
- whitespace / tab level changes

The patch also adds some tests for the parse_profile_start() function.



Acked-by: Steve Beattie <steve@nxnw.org> for 2.9 as well.
2015-03-02 21:46:45 +01:00
Christian Boltz
22d647ecb1 Add some tests for aa.py get_profile_flags().
Also adds a check to get_profile_flags() to catch an invalid syntax:
    /foo (  ) {
was accepted by get_profile_flags, while
    /foo () {
failed.

When testing with the parser, both result in a syntax error, therefore
the patch makes sure it also fails in get_profile_flags().


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-03-02 19:38:34 +01:00
Tyler Hicks
07b0886796 parser: Fix "PDEBUG" redefined warning
Only present when building with DEBUG=1.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-02 09:59:17 -06:00
Tyler Hicks
9da31bf281 parser: Fix -Wformat-extra-args warning
Only present when building with DEBUG=1.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 09:59:14 -06:00
Tyler Hicks
c5ff27a91b parser: Send PDEBUG() to stderr
PDEBUG() and PERROR() should both go to stderr.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-02 09:59:11 -06:00
Tyler Hicks
cf4afcb860 parser: Fix return value of dirat_for_each()
Seth pointed out that dirat_for_each() didn't correctly handle the
return value from readdir_r(). On error, it directly returns a positive
errno value. This would have resulted in that positive errno value being
returned, with an undefined errno value set, from dirat_for_each().
However, the dirat_for_each() documentation states that -1 is returned,
with errno set, on error.

This patch results in readdir_r()'s return value being handled
appropriately. In addition, it ensures that 0 is always returned on
success.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 09:54:57 -06:00
Cameron Norman
75a186fa9f profiles: add geary email client to ubuntu-email abstraction
Merge from trunk revision 2876

Merge from Cameron Norman <camerontnorman@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-27 23:28:05 -08:00
Felix Geyer
05bef291d7 profiles: allow aspell access to /usr/share/aspell/
Merge from trunk revision 2875

From: Felix Geyer <debfx@ubuntu.com>

At least Debian/Ubuntu started shipping some aspell files in
/usr/share/aspell/.
For example:
/usr/share/aspell/iso-8859-1.cmap
/usr/share/aspell/iso-8859-1.cset

The abstraction should allow read access to these files.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-27 23:16:32 -08:00
Steve Beattie
76f71f7d84 profiles: add support for /etc/pki/ in ssl certs abstraction
Merge from trunk revision 2874.

These appear to be related to the update-ca-trust tool.

Thanks to Gregor Dschung <dschung@cs.uni-kl.de>
2015-02-27 22:57:41 -08:00
Christian Boltz
34f2c1c6ea cleanup aa-disable handling in tools.py
Remove the check if the disable directory exists. If it's really
missing, it will be auto-created by create_symlink(), so we
automagically fix things instead of annoying the user with an
error message ;-)

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-02-28 00:25:45 +01:00
Christian Boltz
67dae2f1cf Fix the minitools (aa-audit, aa-complain, aa-enforce, aa-autodep)
to work with multiple profiles at once.

References: https://bugs.launchpad.net/apparmor/+bug/1378095

Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-02-27 14:21:05 +01:00
Seth Arnold
bbaaa00249 parser: fix dbus.cc issue when building with gcc 5
Merge from trunk revision 2868.

This should fix a gcc 5 build failure (untested) with os << .. << os

This build failure was discovered by doko's archive rebuild:
http://people.ubuntuwire.org/~wgrant/rebuild-ftbfs-test/test-rebuild-20150202-gcc5-vivid.html

Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-26 16:18:15 -08:00
Steve Beattie
9ed8789918 parser: fix more gcc 5 compilation problems
Merge from trunk revision 2871

Don't pass an ostream reference into another ostream via <<.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-02-26 15:20:19 -08:00
Christian Boltz
f45628d749 delete traces of program-chunks directory from apparmor.d(5)
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-02-26 18:45:41 +01:00
Christian Boltz
602decfbfc Update is_skippable_file() to match all extensions that are listed in
libapparmor _aa_is_blacklisted() - some extensions were missing in the
python code.

Also make the code more readable and add some testcases.

Notes:
- the original code additionally ignored *.swp. I didn't include that -
  *.swp looks like vim swap files which are also dot files
- the python code ignores README files, but the C code doesn't
  (do we need to add README in the C code?)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9 and trunk
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-04 13:18:47 +01:00
Christian Boltz
9aa1efd744 Fix aa-unconfined to work with profile names that don't start with / or null
Reported by u on the debian pkg-apparmor-team ML.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-02 20:53:29 +01:00
Jamie Strandboge
c51a68eaaf Description: Allow writes to /{,var}/run/systemd/journal/dev-log, the systemd
journal socket. On Debian and Ubuntu systems, /dev/log is a symlink to
 /run/systemd/journal/dev-log, so this access is now required in the base
 abstraction to maintain current behavior.
Bug: https://bugs.launchpad.net/apparmor/+bug/1413232

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-21 13:37:49 -06:00
Christian Boltz
49b739b184 Add some tests for logparser.py based on the log lines from
https://bugs.launchpad.net/apparmor/+bug/1399027

Also move some existing tests from aa_test.py to test-logparser.py and
adds checks for RE_LOG_v2_6_audit and RE_LOG_v2_6_syslog to them.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-01-18 14:57:10 +01:00
Christian Boltz
53d071adf5 update logparser.py to support the changed syslog format by adding
(audit:\s+)?   to RE_LOG_v2_6_syslog

References: https://bugs.launchpad.net/apparmor/+bug/1399027


Acked-by: Seth Arnold <seth.arnold@canonical.com> (for trunk)

Acked-by: Steve Beattie <steve@nxnw.org> for 2.9 as well
2015-01-17 14:35:38 +01:00
Christian Boltz
70cda06789 Fix the dnsmasq profile to allow executing bash to run the --dhcp-script
argument. Also fixed /usr/lib -> /usr/{lib,lib64} to get libvirt
leasehelper script to run even on x86_64.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=911001

Patch by "Cédric Bosdonnat" <cbosdonnat@suse.com>

Note: the original patch used {lib,lib64} - I changed it to lib{,64} to
match the style we typically use.

Acked-by: John Johansen <john.johansen@canonical.com>

(backport of trunk r2841)
2014-12-22 17:57:40 +01:00
Christian Boltz
e8ffc1c4e8 update and cleanup usr.sbin.dovecot profile
Add #include <abstractions/dovecot-common> to the usr.sbin.dovecot
profile. Effectively this adds "deny capability block_suspend," which
is the only missing part from
https://bugs.launchpad.net/apparmor/+bug/1296667/

Also remove "capability setgid," (covered by
abstractions/dovecot-common) and "@{PROC}/filesystems r," (part of
abstractions/base).

Acked-by: John Johansen <john.johansen@canonical.com>

(backport of trunk r2840)
2014-12-22 17:51:02 +01:00
Christian Boltz
09c93be47c Add some missing /run/dovecot/* to usr.lib.dovecot.imap{, -login}
Add the needed permissions as reported in
https://bugs.launchpad.net/apparmor/+bug/1296667/ comment #1
to the usr.lib.dovecot.imap and imap-login profiles.

Acked-by: John Johansen <john.johansen@canonical.com>

(backport of trunk r2839)
2014-12-22 17:43:54 +01:00
Christian Boltz
ac8d886645 update the mysqld profile in the extras directory to
something that works on my servers ;-)

Acked-by: John Johansen <john.johansen@canonical.com>

(backport of trunk r2838)
2014-12-22 17:39:29 +01:00
Christian Boltz
ec1dda24d0 fix network rule description in apparmor.d.pod
(backport from trunk r2837)

Acked-by: John Johansen <john.johansen@canonical.com> (for trunk)

Acked-by: Steve Beattie <steve@nxnw.org> (for 2.9)
2014-12-19 13:57:12 +01:00
Steve Beattie
e7e9053598 Update version in preparation for 2.9.2 development. 2014-12-16 13:37:58 -08:00
947 changed files with 4645 additions and 25654 deletions

View File

@@ -18,13 +18,13 @@ parser/*.8
parser/*.7.html
parser/*.5.html
parser/*.8.html
parser/common
parser/apparmor_parser
parser/libapparmor_re/regexp.cc
parser/techdoc.aux
parser/techdoc.log
parser/techdoc.pdf
parser/techdoc.toc
profiles/apparmor.d/local/*.*
libraries/libapparmor/Makefile
libraries/libapparmor/Makefile.in
libraries/libapparmor/aclocal.m4
@@ -41,32 +41,20 @@ libraries/libapparmor/install-sh
libraries/libapparmor/libtool
libraries/libapparmor/ltmain.sh
libraries/libapparmor/missing
libraries/libapparmor/test-driver
libraries/libapparmor/ylwrap
libraries/libapparmor/doc/Makefile
libraries/libapparmor/doc/Makefile.in
libraries/libapparmor/doc/*.2
libraries/libapparmor/doc/aa_*.3
libraries/libapparmor/include/Makefile
libraries/libapparmor/include/Makefile.in
libraries/libapparmor/include/sys/Makefile
libraries/libapparmor/include/sys/Makefile.in
libraries/libapparmor/src/.deps
libraries/libapparmor/src/.libs
libraries/libapparmor/src/Makefile
libraries/libapparmor/src/Makefile.in
libraries/libapparmor/src/af_protos.h
libraries/libapparmor/src/change_hat.lo
libraries/libapparmor/src/features.lo
libraries/libapparmor/src/grammar.lo
libraries/libapparmor/src/kernel.lo
libraries/libapparmor/src/kernel_interface.lo
libraries/libapparmor/src/libaalogparse.lo
libraries/libapparmor/src/libimmunix_warning.lo
libraries/libapparmor/src/policy_cache.lo
libraries/libapparmor/src/private.lo
libraries/libapparmor/src/scanner.lo
libraries/libapparmor/src/libapparmor.pc
libraries/libapparmor/src/libapparmor.la
libraries/libapparmor/src/libimmunix.la
libraries/libapparmor/src/grammar.c
@@ -82,20 +70,12 @@ libraries/libapparmor/swig/perl/Makefile
libraries/libapparmor/swig/perl/Makefile.PL
libraries/libapparmor/swig/perl/Makefile.in
libraries/libapparmor/swig/perl/Makefile.perl
libraries/libapparmor/swig/perl/Makefile.perle
libraries/libapparmor/swig/perl/MYMETA.json
libraries/libapparmor/swig/perl/MYMETA.yml
libraries/libapparmor/swig/perl/blib
libraries/libapparmor/swig/perl/libapparmor_wrap.c
libraries/libapparmor/swig/perl/pm_to_blib
libraries/libapparmor/swig/python/LibAppArmor.py
libraries/libapparmor/swig/python/build/
libraries/libapparmor/swig/python/libapparmor_wrap.c
libraries/libapparmor/swig/python/Makefile
libraries/libapparmor/swig/python/Makefile.in
libraries/libapparmor/swig/python/setup.py
libraries/libapparmor/swig/python/test/Makefile
libraries/libapparmor/swig/python/test/Makefile.in
libraries/libapparmor/swig/ruby/Makefile
libraries/libapparmor/swig/ruby/Makefile.in
libraries/libapparmor/testsuite/.deps
@@ -114,6 +94,10 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
libraries/libapparmor/testsuite/test_multi/out
changehat/mod_apparmor/.libs
changehat/mod_apparmor/common
changehat/pam_apparmor/common
changehat/tomcat_apparmor/common
utils/common
utils/*.8
utils/*.8.html
utils/*.5
@@ -181,5 +165,4 @@ tests/regression/apparmor/unix_fd_server
tests/regression/apparmor/unlink
tests/regression/apparmor/xattrs
tests/regression/apparmor/coredump
**/__pycache__/
*.orig
./utils/apparmor/__pycache__

View File

@@ -1,12 +1,8 @@
#
#
.PHONY: all
all:
@echo "*** See README for information how to build AppArmor ***"
exit 1
OVERRIDE_TARBALL=yes
COMMONDIR=common
include ${COMMONDIR}/Make.rules
include common/Make.rules
DIRS=parser \
profiles \
@@ -18,7 +14,7 @@ DIRS=parser \
#REPO_URL?=lp:apparmor
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.10
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.9
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"

View File

@@ -17,7 +17,13 @@ NAME:=apache2-mod_apparmor
all:
COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
TARGET:=mod_apparmor.so
MANPAGES=mod_apparmor.8
@@ -86,9 +92,9 @@ install: ${TARGET} ${MANPAGES}
make install_manpages DESTDIR=${DESTDIR}
.PHONY: clean
clean: pod_clean
clean: _clean
rm -rf .libs
rm -f *.la *.lo *.so *.o *.slo
rm -f *.la *.lo *.so *.o *.slo Make.rules
.PHONY: check
check: check_pod_files

View File

@@ -137,7 +137,7 @@ aa_enter_hat(request_rec *r)
ap_get_module_config(r->server->module_config, &apparmor_module);
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
int i = 0;
char *aa_label, *aa_mode, *aa_hat;
char *aa_con, *aa_mode, *aa_hat;
const char *vhost_uri;
debug_dump_uri(r);
@@ -201,14 +201,14 @@ aa_enter_hat(request_rec *r)
/* Check to see if a defined AAHatName or AADefaultHatName would
* apply, but wasn't the hat we landed up in; report a warning if
* that's the case. */
aa_ret = aa_getcon(&aa_label, &aa_mode);
aa_ret = aa_getcon(&aa_con, &aa_mode);
if (aa_ret < 0) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
} else {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"AA checks: aa_getcon result is '%s', mode '%s'", aa_label, aa_mode);
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
/* TODO: use libapparmor get hat_name fn here once it is implemented */
aa_hat = strstr(aa_label, "//");
aa_hat = strstr(aa_con, "//");
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
aa_hat += 2; /* skip "//" */
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
@@ -226,7 +226,7 @@ aa_enter_hat(request_rec *r)
scfg->hat_name);
}
}
free(aa_label);
free(aa_con);
}
return OK;

View File

@@ -65,7 +65,7 @@ provides the AAHatName and AADefaultHatName Apache configuration options.
AAHatName allows you to specify a hat to be used for a given Apache
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
E<lt>LocationMatchE<gt> directive (see the Apache documentation for more
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
details). Note that mod_apparmor behavior can become confused if
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
and it is recommended to use one type of directive. If the hat specified by

View File

@@ -16,8 +16,15 @@
NAME=pam_apparmor
all:
COMMONDIR=../../common/
MAKE_RULES=common/Make.rules
include $(COMMONDIR)/Make.rules
include ${MAKE_RULES}
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
ifdef USE_SYSTEM
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
@@ -53,7 +60,7 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
AA_LDLIBS = -lapparmor
endif
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
LIBS=-lpam $(AA_LDLIBS)
OBJECTS=${NAME}.o get_options.o
@@ -80,5 +87,7 @@ install: $(NAME).so
install -m 555 $(NAME).so $(SECDIR)/
.PHONY: clean
clean:
clean: ${MAKE_RULES}
rm -f core core.* *.so *.o *.s *.a *~
rm -f ${NAME}-*.tar.gz Make.rules

View File

@@ -111,7 +111,6 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
sizeof(magic_token));
if (retval < 0) {
pam_syslog(pamh, LOG_ERR, "Can't read from /dev/urandom\n");
close(fd);
return PAM_PERM_DENIED;
}
} while ((magic_token == 0) || (retval != sizeof(magic_token)));

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat5
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat55
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2010-2015 Canonical, Ltd.
# Copyright (C) 2010 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -15,21 +15,17 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ------------------------------------------------------------------
# Make.rules - common make targets and variables for building AppArmor
# Make.rules - common make targets and variables for building the SHASS
# product.
#
# NOTES:
# Before including this file in your Makefile, you should
# - define COMMONDIR (the location of the common/ directory)
# - define the default rule (usually 'all:'). (Note: you can redefine
# it later in your Makefile)
.PHONY: common_Make.rules_is_a_bad_target
common_Make.rules_is_a_bad_target:
@echo "*** default target in common/Make.rules hit - either you did something strange, or something is broken... ***"
exit 1
# - must define the package NAME before including this file.
# - After checking in to cvs, you'll need to delele the hardlinked
# Make.rules files that already exist in the individual application
# directories
DISTRIBUTION=AppArmor
VERSION=$(shell cat $(COMMONDIR)/Version)
VERSION=$(shell cat common/Version)
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
@@ -45,8 +41,106 @@ define nl
endef
# OVERRIDABLE variables
# Set these variables before including Make.rules to change its behavior
# SPECFILE - for packages that have a non-standard specfile name
# EXTERNAL_PACKAGE - for packages that have upstream versions that
# we're locally modifying (e.g. imnxcerttool/gnutls).
#
# use 'make BUILDIR=/some/where/else/' to override the /usr/src/redhat
# location -- it *should* pick out the right thing to do based on the
# .rpmmacros file, but you can still use BUILDDIR to override that.
TESTBUILDDIR=$(shell [ -f ${HOME}/.rpmmacros ] && awk '/^%_topdir/ {print $$2}' ${HOME}/.rpmmacros)
ifndef BUILDDIR
BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
echo ${TESTBUILDDIR} | sed "s^/$$^^" ; \
elif [ -d "/usr/src/redhat" ] ; then \
echo "/usr/src/redhat" ; \
elif [ -d "/usr/src/packages" ] ; then \
echo "/usr/src/packages" ; \
else \
echo "/tmp/${NAME}" ; \
fi ;)
endif
ifndef DISTRO
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
echo slackware ; \
elif [ -f /etc/debian_version ] ; then \
echo debian ;\
elif which rpm > /dev/null ; then \
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
echo suse ;\
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
echo rhel4 ;\
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
echo rhel4 ;\
else \
echo unknown ;\
fi ;\
else \
echo unknown ;\
fi)
endif
RPMARG=--define "_topdir $(BUILDDIR:/=)" \
--define "vendor NOVELL, Inc." \
--define "distribution ${DISTRIBUTION}" \
--define "debug_package %{nil}" \
--define "immunix_version ${VERSION}" \
$(shell [ -d ${BUILDDIR}/BUILDROOT ] && echo --define \"buildroot $(BUILDDIR:/=)/BUILDROOT\") \
$(shell [ -n "${DISTRO}" ] && echo --define \"distro ${DISTRO}\")
REPO_VERSION_CMD=([ -x /usr/bin/bzr ] && /usr/bin/bzr version-info . 2> /dev/null || awk '{ print "revno: "$2 }' common/.stamp_rev) | awk '/^revno:/ { print $2 }'
ifdef EXTERNAL_PACKAGE
RPMARG+=--define "_sourcedir $(shell pwd)"
endif
ifndef SPECFILE
SPECFILE = $(NAME).spec
endif
RELEASE_DIR = $(NAME)-$(VERSION)
TAR = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
LDCONFIG = /sbin/ldconfig
RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
ifdef EXTERNAL_PACKAGE
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
rpmbuild -ba ${RPMARG} ${SPECFILE}
else
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
__TARBALL=$(NAME)-$(VERSION)-$${__REPO_VERSION}.tar.gz ; \
make $${__TARBALL} ; \
cp $${__TARBALL} $(BUILDDIR)/SOURCES/
cp ${SPECFILE} $(BUILDDIR)/SPECS/
rpmbuild -ba ${RPMARG} ${SPECFILE}
.PHONY: ${SPECFILE}
${SPECFILE}: ${SPECFILE}.in
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
sed -e "s/@@immunix_version@@/${VERSION}/g" \
-e "s/@@repo_version@@/$${__REPO_VERSION}/g" $< > $@
%.tar.gz: clean ${SPECFILE}
-rm -rf $(RELEASE_DIR)
mkdir $(RELEASE_DIR)
$(TAR) --exclude $@ . | tar xz -C $(RELEASE_DIR)
$(TAR) --exclude $@ -f $@ $(RELEASE_DIR)
rm -rf $(RELEASE_DIR)
ifndef OVERRIDE_TARBALL
.PHONY: tarball
tarball: clean $(TARBALL)
endif
endif
ifndef PYTHON_VERSIONS
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
endif
@@ -61,18 +155,24 @@ pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
.PHONY: version
.SILENT: version
version:
echo $(VERSION)
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
.PHONY: repo_version
.SILENT: repo_version
repo_version:
$(value REPO_VERSION_CMD)
.PHONY: pod_clean
ifndef VERBOSE
.SILENT: pod_clean
endif
pod_clean:
.PHONY: build_dir
build_dir: $(BUILDRPMSUBDIRS)
$(BUILDRPMSUBDIRS):
mkdir -p $(BUILDRPMSUBDIRS)
.PHONY: _clean
.SILENT: _clean
_clean:
-[ -z "${NAME}" ] || rm -f ${NAME}-${VERSION}-*.tar.gz
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
# =====================
@@ -82,7 +182,7 @@ pod_clean:
# =====================
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | LC_ALL=C sort)
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | sort)
.PHONY: list_capabilities
list_capabilities: /usr/include/linux/capability.h
@@ -98,7 +198,7 @@ list_capabilities: /usr/include/linux/capability.h
# to mediate. We use PF_ here since that is what is required in
# bits/socket.h, but we will rewrite these as AF_.
FILTER_FAMILIES=PF_UNIX
FILTER_FAMILIES=PF_UNSPEC PF_UNIX
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')

View File

@@ -1 +1 @@
2.10.2
2.9.2

View File

@@ -24,7 +24,13 @@ NAME = apparmor-utils
all:
COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
MODDIR = Immunix
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
@@ -50,8 +56,9 @@ install:
ifndef VERBOSE
.SILENT: clean
endif
clean: pod_clean
clean: _clean
rm -f core core.* *.o *.s *.a *~
rm -f Make.rules
rm -rf staging/ build/
.PHONY: check

Binary file not shown.

View File

@@ -4,4 +4,22 @@ SRCDIR = src
SUBDIRS = doc src include swig testsuite
REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
fi)
REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
fi)
RELEASE_DIR = $(NAME)-$(VERSION)-${REPO_VERSION}
SVNTARBALL = $(NAME)-$(VERSION)-${REPO_VERSION}.tar.gz
SVNTAR = /bin/tar czvp -h --exclude .svn --exclude CVS --exclude .cvsignore --exclude ${SVNTARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
distball: clean
rm -rf $(RELEASE_DIR)
svn export -r $(REPO_VERSION) $(REPO_URL) $(RELEASE_DIR)
$(SVNTAR) -f $(SVNTARBALL) $(RELEASE_DIR)
rm -rf $(RELEASE_DIR)
EXTRA_DIST = AUTHORS ChangeLog COPYING.LGPL INSTALL NEWS README

View File

@@ -38,6 +38,6 @@ aclocal
echo "Running autoconf"
autoconf --force
echo "Running libtoolize"
libtoolize --automake -c --force
libtoolize --automake -c
echo "Running automake"
automake -ac

View File

@@ -14,14 +14,6 @@ PKG_PROG_PKG_CONFIG
AC_PATH_PROG([SWIG], [swig])
AC_MSG_CHECKING([whether the libapparmor debug output should be enabled])
AC_ARG_ENABLE([debug_output],
[AS_HELP_STRING([--enable-debug-output], [generate the libapparmor debug output [[default=no]]])],
[AC_MSG_RESULT([$enableval])],
[enable_debug_output=no]
[AC_MSG_RESULT([$enable_debug_output])])
AS_IF([test "$enable_debug_output" = "yes"], [AC_DEFINE([ENABLE_DEBUG_OUTPUT], [1], [debug output])])
AC_MSG_CHECKING([whether the libapparmor man pages should be generated])
AC_ARG_ENABLE(man_pages,
[AS_HELP_STRING([--enable-man-pages], [generate the libapparmor man pages [[default=yes]]])],
@@ -79,19 +71,14 @@ AM_CONDITIONAL(HAVE_PERL, test x$with_perl = xyes)
AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h stdint.h syslog.h)
AC_CHECK_HEADERS(unistd.h stdint.h)
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
AC_CHECK_FUNCS(asprintf)
AM_PROG_CC_C_O
AC_C_CONST
AM_PROG_LIBTOOL
AC_PROG_CC_C99
if test "$ac_cv_prog_cc_c99" = "no"; then
AC_MSG_ERROR([C99 mode is required to build libapparmor])
fi
AC_OUTPUT(
Makefile
doc/Makefile

View File

@@ -5,14 +5,14 @@ PODCHECKER = podchecker
if ENABLE_MAN_PAGES
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2
PODS = $(subst .2,.pod,$(man_MANS)) $(subst .3,.pod,$(man_MANS))
PODS = $(subst .2,.pod,$(man_MANS))
EXTRA_DIST = $(man_MANS) $(PODS)
## delete man pages at make clean
CLEANFILES = $(man_MANS)
## delete man pages at maintainer-clean
BUILT_SOURCES = $(man_MANS)
%.2: %.pod
$(PODCHECKER) -warnings -warnings $<
@@ -23,13 +23,4 @@ CLEANFILES = $(man_MANS)
--stderr \
$< > $@
%.3: %.pod
$(PODCHECKER) -warnings -warnings $<
$(POD2MAN) \
--section=3 \
--release="AppArmor $(VERSION)" \
--center="AppArmor" \
--stderr \
$< > $@
endif

View File

@@ -40,15 +40,16 @@ An AppArmor profile applies to an executable program; if a portion of
the program needs different access permissions than other portions,
the program can "change profile" to a different profile. To change into a
new profile, it can use the aa_change_profile() function to do so. It passes
in a pointer to the I<profile> to transition to. Confined programs wanting to
use aa_change_profile() need to have rules permitting changing to the named
profile. See apparmor.d(8) for details.
in a pointer to the I<profile> to transition to. Transitioning to another
profile via aa_change_profile() is permanent and the process is not
permitted to transition back to the original profile. Confined programs
wanting to use aa_change_profile() need to have rules permitting changing
to the named profile. See apparmor.d(8) for details.
If a program wants to return out of the current profile to the
original profile, it may use aa_change_hat(2). Otherwise, the two profiles must
have rules permitting changing between the two profiles.
original profile, it should use aa_change_hat(2) instead.
Open file descriptors may not be remediated after a call to aa_change_profile()
Open file descriptors are not remediated after a call to aa_change_profile()
so the calling program must close(2) open file descriptors to ensure they
are not available after calling aa_change_profile(). As aa_change_profile()
is typically used just before execve(2), you may want to use open(2) or
@@ -83,8 +84,8 @@ Insufficient kernel memory was available.
=item B<EPERM>
The calling application is confined by apparmor and the no_new_privs bit is
set.
The calling application is not confined by apparmor, or the no_new_privs
bit is set.
=item B<EACCES>

View File

@@ -1,148 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd.
# essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa_features - an opaque object representing a set of AppArmor kernel features
aa_features_new - create a new aa_features object based on a path
aa_features_new_from_string - create a new aa_features object based on a string
aa_features_new_from_kernel - create a new aa_features object based on the current kernel
aa_features_ref - increments the ref count of an aa_features object
aa_features_unref - decrements the ref count and frees the aa_features object when 0
aa_features_write_to_file - write a string representation of an aa_features object to a file
aa_features_is_equal - equality test for two aa_features objects
aa_features_supports - provides aa_features object support status
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_features aa_features;>
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
B<int aa_features_new_from_kernel(aa_features **features);>
B<aa_features *aa_features_ref(aa_features *features);>
B<void aa_features_unref(aa_features *features);>
B<int aa_features_write_to_file(aa_features *features, int dirfd, const char *path);>
B<bool aa_features_is_equal(aa_features *features1, aa_features *features2);>
B<bool aa_features_supports(aa_features *features, const char *str);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_features> object contains information about the AppArmor features
supported by a kernel. The feature support information is based upon the files
AppArmor represents in securityfs, which is typically found at
/sys/kernel/security/apparmor/features/. That information may be parsed and
turned into a string or flat file in order to represent a set of features of a
kernel that is not currently running.
The aa_features_new() function creates an I<aa_features> object based upon a
directory file descriptor and path. The I<path> can point to a file or
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. The
allocated I<features> object must be freed using aa_features_unref().
The aa_features_new_from_string() function is similar except that it accepts a
NUL-terminated string representation of the AppArmor features as the I<string>
argument. The length of the features string, not counting the NUL-terminator,
must be specified as the I<size> argument. The allocated I<features> object
must be freed using aa_features_unref().
The aa_features_new_from_kernel() function creates an I<aa_features> object
from the current running kernel. The allocated I<features> object must be freed
using aa_features_unref().
aa_features_ref() increments the reference count on the I<features> object.
aa_features_unref() decrements the reference count on the I<features> object
and releases all corresponding resources when the reference count reaches zero.
The aa_features_write_to_file() function writes a string representation of the
I<features> object to the file specified by the I<dirfd> and I<path>
combination.
aa_features_is_equal() can be used to detect if the I<features1> and
I<features2> objects are equal. The definition of equality is private to
libapparmor and may be changed in ways that do not break backward
compatibility.
The aa_features_supports() function can be used to query the I<features> object
to determine if a feature is supported. The I<str> argument should be equal to
the path, relative to the "apparmor/features/" directory of securityfs, of the
feature to query. For example, to test if policy version 6 is supported, I<str>
would be "policy/versions/v6".
=head1 RETURN VALUE
The aa_features_new() family of functions return 0 on success and I<*features>
will point to an I<aa_features> object that must be freed by
aa_features_unref(). -1 is returned on error, with errno set appropriately, and
I<*features> will be set to NULL.
aa_features_ref() returns the value of I<features>.
aa_features_write_to_file() returns 0 on success. -1 is returned on error, with
errno set appropriately.
aa_features_is_equal() returns true if I<features1> and I<features2> are equal
and false if they are not equal.
aa_features_supports() returns true if the feature represented by I<str> is
supported and false if it is not supported.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_features> family of functions that return -1 on error.
=head1 NOTES
All aa_features functions described above are present in libapparmor version
2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
openat(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -34,38 +34,27 @@ B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len, char **mode);>
B<int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);>
B<int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);>
B<int aa_gettaskcon(pid_t target, char **label, char **mode);>
B<int aa_gettaskcon(pid_t target, char **con, char **mode);>
B<int aa_getcon(char **label, char **mode);>
B<int aa_getcon(char **con, char **mode);>
B<int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);>
B<int aa_getpeercon(int fd, char **label, char **mode);>
B<int aa_getpeercon(int fd, char **con, char **mode);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_getcon function gets the current AppArmor confinement context for the
current task. The confinement context consists of a label and a mode. The label
is usually just the name of the AppArmor profile restricting the task, but it
may include the profile namespace or in some cases a set of profile names
(known as a stack of profiles). The mode is a string that describes how the
kernel is enforcing the policy defined in the profile. Profiles loaded in
"enforce" mode will result in enforcement of the policy defined in the profile
as well as reporting policy violation attempts. Profiles in "complain" mode
will not enforce policy but instead report policy violation attempts.
Some examples of possible returned *label strings are "unconfined", "/sbin/dhclient",
and "Firefox". The string can consist of any non-NUL characters but it will be
NUL-terminated. The *label string must be freed using free().
The possible *mode strings are "enforce" and "complain". Additionally, *mode may
be NULL when *label is "unconfined". B<The *mode string must not be freed>. The
*label and *mode strings come from a single buffer allocation and are separated
by a NUL character.
current task. The confinement context is usually just the name of the AppArmor
profile restricting the task, but it may include the profile namespace or in
some cases a set of profile names (known as a stack of profiles). The returned
string *con should be freed using free(), but the returned string *mode should
not be freed. The *con and *mode strings come from a single buffer allocation
and are separated by a NUL character.
The aa_gettaskcon function is like the aa_getcon function except it will work
for any arbitrary task in the system.
@@ -131,7 +120,7 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
aa_splitcon(3) and L<http://wiki.apparmor.net>.
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2) and
L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,162 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd.
# essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa_kernel_interface - an opaque object representing the AppArmor kernel interface for policy loading, replacing, and removing
aa_kernel_interface_new - create a new aa_kernel_interface object from an optional path
aa_kernel_interface_ref - increments the ref count of an aa_kernel_interface object
aa_kernel_interface_unref - decrements the ref count and frees the aa_kernel_interface object when 0
aa_kernel_interface_load_policy - load a policy from a buffer into the kernel
aa_kernel_interface_load_policy_from_file - load a policy from a file into the kernel
aa_kernel_interface_load_policy_from_fd - load a policy from a file descriptor into the kernel
aa_kernel_interface_replace_policy - replace a policy in the kernel with a policy from a buffer
aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel with a policy from a file
aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel with a policy from a file descriptor
aa_kernel_interface_remove_policy - remove a policy from the kernel
aa_kernel_interface_write_policy - write a policy to a file descriptor
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_kernel_interface aa_kernel_interface;>
B<int aa_kernel_interface_new(aa_kernel_interface **kernel_interface, aa_features *kernel_features, const char *apparmorfs);>
B<aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);>
B<void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);>
B<int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
B<int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
B<int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
B<int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
B<int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
B<int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
B<int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface, const char *fqname);>
B<int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_kernel_interface> object contains information about the AppArmor
kernel interface for policy loading, replacing, and removing.
The aa_kernel_interface_new() function creates an I<aa_kernel_interface> object
based on an optional I<aa_features> object and an optional path to the apparmor
directory of securityfs, which is typically found at
"/sys/kernel/security/apparmor/". If I<kernel_features> is NULL, then the
features of the current kernel are used. When specifying a valid
I<kernel_features> object, it must be compatible with the features of the
currently running kernel. If I<apparmorfs> is NULL, then the default location
is used. The allocated I<kernel_interface> object must be freed using
aa_kernel_interface_unref().
aa_kernel_interface_ref() increments the reference count on the
I<kernel_interface> object.
aa_kernel_interface_unref() decrements the reference count on the
I<kernel_interface> object and releases all corresponding resources when the
reference count reaches zero.
The aa_kernel_interface_load() family of functions load a policy into the
kernel. The operation will fail if a policy of the same name is already loaded.
Use the aa_kernel_interface_replace() family of functions if you wish to
replace a previously loaded policy with a new policy of the same name. The
aa_kernel_interface_replace() functions can also be used to load a policy that
does not correspond to a previously loaded policy.
When loading or replacing from a buffer, the I<buffer> will contain binary
data. The I<size> argument must specify the size of the I<buffer> argument.
When loading or replacing from a file, the I<dirfd> and I<path> combination are
used to specify the location of the file. See the openat(2) man page for
examples of I<dirfd> and I<path>.
It is also possible to load or replace from a file descriptor specified by the
I<fd> argument. The file must be open for reading and the file offset must be
set appropriately.
The aa_kernel_interface_remove_policy() function can be used to unload a
previously loaded policy. The fully qualified policy name must be specified
with the I<fqname> argument. The operation will fail if a policy matching
I<fqname> is not found.
The aa_kernel_interface_write_policy() function allows for a policy, which is
stored in I<buffer> and consists of I<size> bytes, to be written to a file
descriptor. The I<fd> must be open for writing and the file offset must be set
appropriately.
=head1 RETURN VALUE
The aa_kernel_interface_new() function returns 0 on success and
I<*kernel_interface> will point to an I<aa_kernel_interface> object that must
be freed by aa_kernel_interface_unref(). -1 is returned on error, with errno
set appropriately, and I<*kernel_interface> will be set to NULL.
aa_kernel_features_ref() returns the value of I<kernel_features>.
The aa_kernel_interface_load() family of functions, the
aa_kernel_interface_replace() family of functions,
aa_kernel_interface_remove(), and aa_kernel_interface_write_policy()
return 0 on success. -1 is returned on error, with errno set appropriately.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_kernel_interface> family of functions that return -1 on error.
=head1 NOTES
All aa_kernel_interface functions described above are present in libapparmor
version 2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_features(3), openat(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,125 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd.
# essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa_policy_cache - an opaque object representing an AppArmor policy cache
aa_policy_cache_new - create a new aa_policy_cache object from a path
aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
aa_policy_cache_remove - removes all policy cache files under a path
aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_policy_cache aa_policy_cache;>
B<int aa_policy_cache_new(aa_policy_cache **policy_cache, aa_features *kernel_features, int dirfd, const char *path, uint16_t max_caches);>
B<aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);>
B<void aa_policy_cache_unref(aa_policy_cache *policy_cache);>
B<int aa_policy_cache_remove(int dirfd, const char *path);>
B<int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_policy_cache> object contains information about a set of AppArmor
policy cache files. The policy cache files are the binary representation of a
human-readable AppArmor profile. The binary representation is the form that is
loaded into the kernel.
The aa_policy_cache_new() function creates an I<aa_policy_cache> object based
upon a directory file descriptor and path. The I<path> must point to a
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. If
I<kernel_features> is NULL, then the features of the current kernel are used.
When specifying a valid I<kernel_features> object, it must be the compatible
with the features of the kernel of interest. The value of I<max_caches> should
be equal to the number of caches that should be allowed before old caches are
automatically reaped. The definition of what is considered to be an old cache
is private to libapparmor. Specifying 0 means that no new caches should be
created and only existing, valid caches may be used. Specifying UINT16_MAX
means that a new cache may be created and that the reaping of old caches is
disabled. The allocated I<aa_policy_cache> object must be freed using
aa_policy_cache_unref().
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
object.
aa_policy_cache_unref() decrements the reference count on the I<policy_cache>
object and releases all corresponding resources when the reference count
reaches zero.
The aa_policy_cache_remove() function deletes all of the policy cache files
based upon a directory file descriptor and path. The I<path> must point to a
directory. See the openat(2) man page for examples of I<dirfd> and I<path>.
The aa_policy_cache_replace_all() function can be used to perform a policy
replacement of all of the cache policies in the cache directory represented by
the I<policy_cache> object. If I<kernel_interface> is NULL, then the current
kernel interface is used. When specifying a valid I<kernel_interface> object,
it must be the interface of the currently running kernel.
=head1 RETURN VALUE
The aa_policy_cache_new() function returns 0 on success and I<*policy_cache>
will point to an I<aa_policy_cache> object that must be freed by
aa_policy_cache_unref(). -1 is returned on error, with errno set appropriately,
and I<*policy_cache> will be set to NULL.
aa_policy_cache_ref() returns the value of I<policy_cache>.
aa_policy_cache_remove() and aa_policy_cache_replace_all() return 0 on success.
-1 is returned on error, with errno set appropriately.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_policy_cache> family of functions that return -1 on error.
=head1 NOTES
All aa_policy_cache functions described above are present in libapparmor
version 2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_features(3), aa_kernel_interface(3), openat(2) and
L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,137 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd.
# essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa_query_label - query access permission associated with a label
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_query_label((uint32_t mask, char *query, size_t size,
int *allowed, int *audited);>
B<int aa_query_file_path((uint32_t mask, const char *label, size_t label_len,
const char *path, int *allowed, int *audited);>
B<int aa_query_file_path_len((uint32_t mask, const char *label,
size_t label_len, const char *path, size_t path_len,
int *allowed, int *audited);>
B<int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);>
B<int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_query_label function fetches the current permissions granted by the
specified I<label> in the I<query> string.
The query is a raw binary formatted query, containing the label and
permission query to make. The returned I<allowed> and I<audited> values are
interpreted boolean values, simple stating whether the query is allowed and
if it is audited.
The mask of the query string is a bit mask of permissions to query and is
class type dependent (see AA_CLASS_xxx) entries in I<sys/apparmor.h>.
The format of the query string is also dependent on the B<AA_CLASS> and as
such the the aa_query_xxx helper functions should usually be used instead
of directly using I<aa_query_label>. If directly using the interface the
I<query> string is required to have a header of B<AA_QUERY_CMD_LABEL_SIZE>
that will be used by I<aa_query_label>.
The B<aa_query_file_path> and B<aa_query_file_path_len> functions are helper
function that assemble a properly formatted file path query for the
B<aa_query_label> function. The I<label> is a valid apparmor label as
returned by I<aa_splitcon> with I<label_len> being the length of the I<label>.
The I<path> is any valid filesystem path to query permissions for. For the
B<aa_query_file_path_len> variant the I<path_len> parameter specifies the
number of bytes in the I<path> to use as part of the query.
The B<aa_query_link_path> and B<aa_query_link_path_len> functions are helper
functions that assemble a properly formatted link path query for the
B<aa_query_label> function. The I<link_len> and I<target_len> parameters
specify the number of bytes in the I<link> and I<target> to use as part of
the query.
=head1 RETURN VALUE
On success 0 is returned, and the I<allowed> and I<audited> parameters
contain a boolean value of 0 not allowed/audited or 1 allowed/audited. On
error, -1 is returned, and errno(3) is set appropriately.
=head1 ERRORS
=over 4
=item B<EINVAL>
The requested I<mask> is empty.
The I<size> of the query is E<lt> the query B<AA_QUER?Y_CMD_LABEL_SIZE>
The apparmor kernel module is not loaded or the he kernel interface access
interface is not available
=item B<ENOMEM>
Insufficient memory was available.
=item B<EACCES>
Access to the specified I<label> or query interface was denied.
=item B<ENOENT>
The specified I<label> does not exist or is not visible.
=item B<ERANGE>
The confinement data is too large to fit in the supplied buffer.
=back
=head1 NOTES
The label permissions returned are only valid for the time of the
query and can change at any point in the future.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_getcon(2), aa_splitcon(3)
and L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,72 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd.
# essentially adhere to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa_splitcon - split the confinement context into a label and mode
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<char *aa_splitcon(char *con, char **mode);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_splitcon() function splits a confinement context into separate label
and mode strings. The @con string is modified so that the label portion is NUL
terminated. The enforcement mode is also NUL terminated and the parenthesis
surrounding the mode are removed. If @mode is non-NULL, it will point to the
first character in the enforcement mode string on success.
The Linux kernel's /proc/E<lt>PIDE<gt>/attr/current interface appends a
trailing newline character to AppArmor contexts that are read from that file.
If @con contains a single trailing newline character, it will be stripped by
aa_splitcon() prior to all other processing.
=head1 RETURN VALUE
Returns a pointer to the first character in the label string. NULL is returned
on error.
=head1 EXAMPLE
Context Label Mode
----------------------------- ------------------ -------
unconfined unconfined NULL
unconfined\n unconfined NULL
/bin/ping (enforce) /bin/ping enforce
/bin/ping (enforce)\n /bin/ping enforce
/usr/sbin/rsyslogd (complain) /usr/sbin/rsyslogd complain
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_getcon(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,3 +1,3 @@
apparmor_hdrdir = $(includedir)/sys
apparmor_hdr_HEADERS = apparmor.h apparmor_private.h
apparmor_hdr_HEADERS = apparmor.h

View File

@@ -18,7 +18,6 @@
#ifndef _SYS_APPARMOR_H
#define _SYS_APPARMOR_H 1
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -27,31 +26,10 @@ __BEGIN_DECLS
/*
* Class of public mediation types in the AppArmor policy db
*/
#define AA_CLASS_FILE 2
#define AA_CLASS_DBUS 32
/* Permission flags for the AA_CLASS_FILE mediation class */
#define AA_MAY_EXEC (1 << 0)
#define AA_MAY_WRITE (1 << 1)
#define AA_MAY_READ (1 << 2)
#define AA_MAY_APPEND (1 << 3)
#define AA_MAY_CREATE (1 << 4)
#define AA_MAY_DELETE (1 << 5)
#define AA_MAY_OPEN (1 << 6)
#define AA_MAY_RENAME (1 << 7)
#define AA_MAY_SETATTR (1 << 8)
#define AA_MAY_GETATTR (1 << 9)
#define AA_MAY_SETCRED (1 << 10)
#define AA_MAY_GETCRED (1 << 11)
#define AA_MAY_CHMOD (1 << 12)
#define AA_MAY_CHOWN (1 << 13)
#define AA_MAY_LOCK 0x8000
#define AA_EXEC_MMAP 0x10000
#define AA_MAY_LINK 0x40000
#define AA_MAY_ONEXEC 0x20000000
#define AA_MAY_CHANGE_PROFILE 0x40000000
/* Permission flags for the AA_CLASS_DBUS mediation class */
#define AA_DBUS_SEND (1 << 1)
#define AA_DBUS_RECEIVE (1 << 2)
@@ -79,18 +57,16 @@ extern int aa_change_onexec(const char *profile);
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
extern char *aa_splitcon(char *con, char **mode);
/* Protypes for introspecting task confinement
* Please see the aa_getcon(2) manpage for information
*/
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **label,
char **mode);
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
extern int aa_getcon(char **label, char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
extern int aa_getcon(char **con, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
extern int aa_getpeercon(int fd, char **label, char **mode);
extern int aa_getpeercon(int fd, char **con, char **mode);
/* A NUL character is used to separate the query command prefix string from the
* rest of the query string. The query command sizes intentionally include the
@@ -101,17 +77,6 @@ extern int aa_getpeercon(int fd, char **label, char **mode);
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
int *audit);
extern int aa_query_file_path_len(uint32_t mask, const char *label,
size_t label_len, const char *path,
size_t path_len, int *allowed, int *audited);
extern int aa_query_file_path(uint32_t mask, const char *label,
const char *path, int *allowed, int *audited);
extern int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);
extern int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);
#define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
#define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
@@ -137,58 +102,6 @@ extern int aa_query_link_path(const char *label, const char *target,
#define aa_change_hat_vargs(T, X...) \
(aa_change_hat_vargs)(T, __macroarg_counter(X), X)
typedef struct aa_features aa_features;
extern int aa_features_new(aa_features **features, int dirfd, const char *path);
extern int aa_features_new_from_string(aa_features **features,
const char *string, size_t size);
extern int aa_features_new_from_kernel(aa_features **features);
extern aa_features *aa_features_ref(aa_features *features);
extern void aa_features_unref(aa_features *features);
extern int aa_features_write_to_file(aa_features *features,
int dirfd, const char *path);
extern bool aa_features_is_equal(aa_features *features1,
aa_features *features2);
extern bool aa_features_supports(aa_features *features, const char *str);
typedef struct aa_kernel_interface aa_kernel_interface;
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
aa_features *kernel_features,
const char *apparmorfs);
extern aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);
extern void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);
extern int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
const char *buffer, size_t size);
extern int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
int dirfd,
const char *path);
extern int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface,
int fd);
extern int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
const char *buffer, size_t size);
extern int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
int dirfd,
const char *path);
extern int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface,
int fd);
extern int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
const char *fqname);
extern int aa_kernel_interface_write_policy(int fd, const char *buffer,
size_t size);
typedef struct aa_policy_cache aa_policy_cache;
extern int aa_policy_cache_new(aa_policy_cache **policy_cache,
aa_features *kernel_features,
int dirfd, const char *path,
uint16_t max_caches);
extern aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
extern void aa_policy_cache_unref(aa_policy_cache *policy_cache);
extern int aa_policy_cache_remove(int dirfd, const char *path);
extern int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
aa_kernel_interface *kernel_interface);
__END_DECLS
#endif /* sys/apparmor.h */

View File

@@ -1,38 +0,0 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SYS_APPARMOR_PRIVATE_H
#define _SYS_APPARMOR_PRIVATE_H 1
#include <stdio.h>
#include <sys/stat.h>
__BEGIN_DECLS
int _aa_is_blacklisted(const char *name);
void _aa_autofree(void *p);
void _aa_autoclose(int *fd);
void _aa_autofclose(FILE **f);
int _aa_asprintf(char **strp, const char *fmt, ...);
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
int (* cb)(int, const char *, struct stat *, void *));
__END_DECLS
#endif /* sys/apparmor_private.h */

View File

@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
# For more information, see:
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
#
AA_LIB_CURRENT = 4
AA_LIB_REVISION = 0
AA_LIB_AGE = 3
AA_LIB_CURRENT = 3
AA_LIB_REVISION = 1
AA_LIB_AGE = 2
SUFFIXES = .pc.in .pc
@@ -46,9 +46,9 @@ af_protos.h: /usr/include/netinet/in.h
LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" $< > $@
lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
@@ -63,15 +63,7 @@ CLEANFILES = libapparmor.pc
tst_aalogmisc_SOURCES = tst_aalogmisc.c
tst_aalogmisc_LDADD = .libs/libapparmor.a
tst_features_SOURCES = tst_features.c
tst_features_LDADD = .libs/libapparmor.a
tst_kernel_SOURCES = tst_kernel.c
tst_kernel_LDADD = .libs/libapparmor.a
tst_kernel_LDFLAGS = -pthread
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
check_PROGRAMS = tst_aalogmisc
TESTS = $(check_PROGRAMS)
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc

View File

@@ -1,561 +0,0 @@
/*
* Copyright (c) 2014
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/apparmor.h>
#include "private.h"
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
#define STRING_SIZE 8192
struct aa_features {
unsigned int ref_count;
char string[STRING_SIZE];
};
struct features_struct {
char *buffer;
int size;
char *pos;
};
struct component {
const char *str;
size_t len;
};
static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
{
va_list args;
int i, remaining = fst->size - (fst->pos - fst->buffer);
if (remaining < 0) {
errno = EINVAL;
PERROR("Invalid features buffer offset\n");
return -1;
}
va_start(args, fmt);
i = vsnprintf(fst->pos, remaining, fmt, args);
va_end(args);
if (i < 0) {
errno = EIO;
PERROR("Failed to write to features buffer\n");
return -1;
} else if (i >= remaining) {
errno = ENOBUFS;
PERROR("Feature buffer full.");
return -1;
}
fst->pos += i;
return 0;
}
/* load_features_file - opens and reads a file into @buffer and then NUL-terminates @buffer
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
* @path: name of the file
* @buffer: the buffer to read the features file into (will be NUL-terminated on success)
* @size: the size of @buffer
*
* Returns: The number of bytes copied into @buffer on success (not counting
* the NUL-terminator), else -1 and errno is set. Note that @size must be
* larger than the size of the file or -1 will be returned with errno set to
* ENOBUFS indicating that @buffer was not large enough to contain all of the
* file contents.
*/
static int load_features_file(int dirfd, const char *path,
char *buffer, size_t size)
{
autoclose int file = -1;
char *pos = buffer;
ssize_t len;
file = openat(dirfd, path, O_RDONLY);
if (file < 0) {
PDEBUG("Could not open '%s'\n", path);
return -1;
}
PDEBUG("Opened features \"%s\"\n", path);
if (!size) {
errno = ENOBUFS;
return -1;
}
/* Save room for a NUL-terminator at the end of @buffer */
size--;
do {
len = read(file, pos, size);
if (len > 0) {
size -= len;
pos += len;
}
} while (len > 0 && size);
/**
* Possible error conditions:
* - len == -1: read failed and errno is already set so return -1
* - len > 0: read() never returned 0 (EOF) meaning that @buffer was
* too small to contain all of the file contents so set
* errno to ENOBUFS and return -1
*/
if (len) {
if (len > 0)
errno = ENOBUFS;
PDEBUG("Error reading features file '%s': %m\n", path);
return -1;
}
/* NUL-terminate @buffer */
*pos = 0;
return pos - buffer;
}
static int features_dir_cb(int dirfd, const char *name, struct stat *st,
void *data)
{
struct features_struct *fst = (struct features_struct *) data;
/* skip dot files and files with no name */
if (*name == '.' || !strlen(name))
return 0;
if (features_snprintf(fst, "%s {", name) == -1)
return -1;
if (S_ISREG(st->st_mode)) {
int len;
int remaining = fst->size - (fst->pos - fst->buffer);
len = load_features_file(dirfd, name, fst->pos, remaining);
if (len < 0)
return -1;
fst->pos += len;
} else if (S_ISDIR(st->st_mode)) {
if (_aa_dirat_for_each(dirfd, name, fst, features_dir_cb))
return -1;
}
if (features_snprintf(fst, "}\n") == -1)
return -1;
return 0;
}
static int load_features_dir(int dirfd, const char *path,
char *buffer, int size)
{
struct features_struct fst = { buffer, size, buffer };
if (_aa_dirat_for_each(dirfd, path, &fst, features_dir_cb)) {
PDEBUG("Failed evaluating %s\n", path);
return -1;
}
return 0;
}
static bool islbrace(int c)
{
return c == '{';
}
static bool isrbrace(int c)
{
return c == '}';
}
static bool isnul(int c)
{
return c == '\0';
}
static bool isbrace(int c)
{
return islbrace(c) || isrbrace(c);
}
static bool isbrace_or_nul(int c)
{
return isbrace(c) || isnul(c);
}
static bool isbrace_space_or_nul(int c)
{
return isbrace(c) || isspace(c) || isnul(c);
}
static size_t tokenize_path_components(const char *str,
struct component *components,
size_t max_components)
{
size_t i = 0;
memset(components, 0, sizeof(*components) * max_components);
if (!str)
return 0;
while (*str && i < max_components) {
const char *fwdslash = strchrnul(str, '/');
/* Save the token if it is not "/" */
if (fwdslash != str) {
components[i].str = str;
components[i].len = fwdslash - str;
i++;
}
if (isnul(*fwdslash))
break;
str = fwdslash + 1;
}
return i;
}
/**
* walk_one - walk one component of a features string
* @str: a pointer to the current position in a features string
* @component: the component to walk
* @is_top_level: true if component is a top-level component
*
* Imagine a features string such as:
*
* "feat1 { subfeat1.1 subfeat1.2 } feat2 { subfeat2.1 { subfeat2.1.1 } }"
*
* You want to know if "feat2/subfeat2.1/subfeat2.8" is valid. It will take 3
* invocations of this function to determine if that string is valid. On the
* first call, *@str will point to the beginning of the features string,
* component->str will be "feat2", and is_top_level will be true since feat2 is
* a top level feature. The function will return true and *@str will now point
* at the the left brace after "feat2" in the features string. You can call
* this function again with component->str being equal to "subfeat2.1" and it
* will return true and *@str will now point at the left brace after
* "subfeat2.1" in the features string. A third call to the function, with
* component->str equal to "subfeat2.8", will return false and *@str will not
* be changed.
*
* Returns true if the walk was successful and false otherwise. If the walk was
* successful, *@str will point to the first encountered brace after the walk.
* If the walk was unsuccessful, *@str is not updated.
*/
static bool walk_one(const char **str, const struct component *component,
bool is_top_level)
{
const char *cur;
uint32_t brace_count = 0;
size_t i = 0;
/* NULL pointers and empty strings are not accepted */
if (!str || !*str || !component || !component->str || !component->len)
return false;
cur = *str;
/**
* If @component is not top-level, the first character in the string to
* search MUST be '{'
*/
if (!is_top_level) {
if (!islbrace(*cur))
return false;
cur++;
}
/**
* This loop tries to find the @component in *@str. When this loops
* completes, cur will either point one character past the end of the
* matched @component or to the NUL terminator of *@str.
*/
while(!isnul(*cur) && i < component->len) {
if (!isascii(*cur)) {
/* Only ASCII is expected */
return false;
} else if (islbrace(*cur)) {
/* There's a limit to the number of left braces */
if (brace_count == UINT32_MAX)
return false;
brace_count++;
} else if (isrbrace(*cur)) {
/* Check for unexpected right braces */
if (brace_count == 0)
return false;
brace_count--;
}
/**
* Move to the next character in @component if we're not inside
* of braces and we have a character match
*/
if (brace_count == 0 && *cur == component->str[i])
i++;
else
i = 0;
cur++;
}
/* Return false if a full match was not found */
if (i != component->len) {
return false;
} else if (!isbrace_space_or_nul(*cur))
return false;
/**
* This loop eats up valid (ASCII) characters until a brace or NUL
* character is found so that *@str is properly set to call back into
* this function
*/
while (!isbrace_or_nul(*cur)) {
if (!isascii(*cur))
return false;
cur++;
}
*str = cur;
return true;
}
/**
* aa_features_new - create a new aa_features object based on a path
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: path to a features file or directory
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new(aa_features **features, int dirfd, const char *path)
{
struct stat stat_file;
aa_features *f;
int retval;
*features = NULL;
if (fstatat(dirfd, path, &stat_file, 0) == -1)
return -1;
f = calloc(1, sizeof(*f));
if (!f) {
errno = ENOMEM;
return -1;
}
aa_features_ref(f);
retval = S_ISDIR(stat_file.st_mode) ?
load_features_dir(dirfd, path, f->string, STRING_SIZE) :
load_features_file(dirfd, path, f->string, STRING_SIZE);
if (retval == -1) {
int save = errno;
aa_features_unref(f);
errno = save;
return -1;
}
*features = f;
return 0;
}
/**
* aa_features_new_from_string - create a new aa_features object based on a string
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
* @string: a NUL-terminated string representation of features
* @size: the size of @string, not counting the NUL-terminator
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new_from_string(aa_features **features,
const char *string, size_t size)
{
aa_features *f;
*features = NULL;
/* Require size to be less than STRING_SIZE so there's room for a NUL */
if (size >= STRING_SIZE)
return ENOBUFS;
f = calloc(1, sizeof(*f));
if (!f) {
errno = ENOMEM;
return -1;
}
aa_features_ref(f);
memcpy(f->string, string, size);
f->string[size] = '\0';
*features = f;
return 0;
}
/**
* aa_features_new_from_kernel - create a new aa_features object based on the current kernel
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new_from_kernel(aa_features **features)
{
return aa_features_new(features, -1, FEATURES_FILE);
}
/**
* aa_features_ref - increments the ref count of an aa_features object
* @features: the features
*
* Returns: the features
*/
aa_features *aa_features_ref(aa_features *features)
{
atomic_inc(&features->ref_count);
return features;
}
/**
* aa_features_unref - decrements the ref count and frees the aa_features object when 0
* @features: the features (can be NULL)
*/
void aa_features_unref(aa_features *features)
{
if (features && atomic_dec_and_test(&features->ref_count))
free(features);
}
/**
* aa_features_write_to_file - write a string representation of an aa_features object to a file
* @features: the features
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: the path to write to
*
* Returns: 0 on success, -1 on error with errno set
*/
int aa_features_write_to_file(aa_features *features,
int dirfd, const char *path)
{
autoclose int fd = -1;
size_t size;
ssize_t retval;
char *string;
fd = openat(dirfd, path,
O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1)
return -1;
string = features->string;
size = strlen(string);
do {
retval = write(fd, string, size);
if (retval == -1)
return -1;
size -= retval;
string += retval;
} while (size);
return 0;
}
/**
* aa_features_is_equal - equality test for two aa_features objects
* @features1: the first features (can be NULL)
* @features2: the second features (can be NULL)
*
* Returns: true if they're equal, false if they're not or either are NULL
*/
bool aa_features_is_equal(aa_features *features1, aa_features *features2)
{
return features1 && features2 &&
strcmp(features1->string, features2->string) == 0;
}
/**
* aa_features_supports - provides aa_features object support status
* @features: the features
* @str: the string representation of a feature to check
*
* Example @str values are "dbus/mask/send", "caps/mask/audit_read", and
* "policy/versions/v7".
*
* Returns: a bool specifying the support status of @str feature
*/
bool aa_features_supports(aa_features *features, const char *str)
{
const char *features_string = features->string;
struct component components[32];
size_t i, num_components;
/* Empty strings are not accepted. Neither are leading '/' chars. */
if (!str || str[0] == '/')
return false;
/**
* Break @str into an array of components. For example,
* "mount/mask/mount" would turn into { "mount", 5 } as the first
* component, { "mask", 4 } as the second, and { "mount", 5 } as the
* third
*/
num_components = tokenize_path_components(str, components,
sizeof(components) / sizeof(*components));
/* At least one valid token is required */
if (!num_components)
return false;
/* Ensure that all components are valid and found */
for (i = 0; i < num_components; i++) {
if (!walk_one(&features_string, &components[i], i == 0))
return false;
}
return true;
}

View File

@@ -166,15 +166,9 @@ aa_record_event_type lookup_aa_event(unsigned int type)
%token TOK_SYSLOG_KERNEL
%token TOK_SYSLOG_USER
%destructor { free($$); } TOK_QUOTED_STRING TOK_ID TOK_MODE TOK_DMESG_STAMP
%destructor { free($$); } TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE TOK_TIME
%destructor { free($$); } TOK_HEXSTRING TOK_TYPE_OTHER TOK_MSG_REST
%destructor { free($$); } TOK_IP_ADDR
%%
log_message: audit_type
| dmesg_type
| syslog_type
| audit_dispatch
;
@@ -205,10 +199,6 @@ other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
}
;
dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
;
syslog_type:
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
@@ -428,7 +418,7 @@ _parse_yacc(char *str)
int parser_return;
ret_record = NULL;
ret_record = malloc(sizeof(aa_log_record));
ret_record = (aa_log_record *) malloc(sizeof(aa_log_record));
_init_log_record(ret_record);

View File

@@ -1,982 +0,0 @@
/*
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
* Copyright 2009-2010 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <mntent.h>
#include <inttypes.h>
#include <pthread.h>
#include <sys/apparmor.h>
#include "private.h"
/* some non-Linux systems do not define a static value */
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
#define symbol_version(real, name, version) \
__asm__ (".symver " #real "," #name "@" #version)
#define default_symbol_version(real, name, version) \
__asm__ (".symver " #real "," #name "@@" #version)
#define UNCONFINED "unconfined"
#define UNCONFINED_SIZE strlen(UNCONFINED)
/**
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
* @mnt: returns buffer with the mountpoint string
*
* Returns: 0 on success else -1 on error
*
* NOTE: this function only supports versions of apparmor using securityfs
*/
int aa_find_mountpoint(char **mnt)
{
struct stat statbuf;
struct mntent *mntpt;
FILE *mntfile;
int rc = -1;
if (!mnt) {
errno = EINVAL;
return -1;
}
mntfile = setmntent("/proc/mounts", "r");
if (!mntfile)
return -1;
while ((mntpt = getmntent(mntfile))) {
char *proposed = NULL;
if (strcmp(mntpt->mnt_type, "securityfs") != 0)
continue;
if (asprintf(&proposed, "%s/apparmor", mntpt->mnt_dir) < 0)
/* ENOMEM */
break;
if (stat(proposed, &statbuf) == 0) {
*mnt = proposed;
rc = 0;
break;
}
free(proposed);
}
endmntent(mntfile);
if (rc == -1)
errno = ENOENT;
return rc;
}
/**
* aa_is_enabled - determine if apparmor is enabled
*
* Returns: 1 if enabled else reason it is not, or 0 on error
*
* ENOSYS - no indication apparmor is present in the system
* ENOENT - enabled but interface could not be found
* ECANCELED - disabled at boot
* ENOMEM - out of memory
*/
int aa_is_enabled(void)
{
int serrno, fd, rc, size;
char buffer[2];
char *mnt;
/* if the interface mountpoint is available apparmor is enabled */
rc = aa_find_mountpoint(&mnt);
if (rc == 0) {
free(mnt);
return 1;
}
/* determine why the interface mountpoint isn't available */
fd = open("/sys/module/apparmor/parameters/enabled", O_RDONLY);
if (fd == -1) {
if (errno == ENOENT)
errno = ENOSYS;
return 0;
}
size = read(fd, &buffer, 2);
serrno = errno;
close(fd);
errno = serrno;
if (size > 0) {
if (buffer[0] == 'Y')
errno = ENOENT;
else
errno = ECANCELED;
}
return 0;
}
static inline pid_t aa_gettid(void)
{
#ifdef SYS_gettid
return syscall(SYS_gettid);
#else
return getpid();
#endif
}
static char *procattr_path(pid_t pid, const char *attr)
{
char *path = NULL;
if (asprintf(&path, "/proc/%d/attr/%s", pid, attr) > 0)
return path;
return NULL;
}
/**
* parse_unconfined - check for the unconfined label
* @con: the confinement context
* @size: size of the confinement context (not including the NUL terminator)
*
* Returns: True if the con is the unconfined label or false otherwise
*/
static bool parse_unconfined(char *con, int size)
{
return size == UNCONFINED_SIZE &&
strncmp(con, UNCONFINED, UNCONFINED_SIZE) == 0;
}
/**
* splitcon - split the confinement context into a label and mode
* @con: the confinement context
* @size: size of the confinement context (not including the NUL terminator)
* @strip_newline: true if a trailing newline character should be stripped
* @mode: if non-NULL and a mode is present, will point to mode string in @con
* on success
*
* Modifies the @con string to split it into separate label and mode strings.
* If @strip_newline is true and @con contains a single trailing newline, it
* will be stripped on success (it will not be stripped on error). The @mode
* argument is optional. If @mode is NULL, @con will still be split between the
* label and mode (if present) but @mode will not be set.
*
* Returns: a pointer to the label string or NULL on error
*/
static char *splitcon(char *con, int size, bool strip_newline, char **mode)
{
char *label = NULL;
char *mode_str = NULL;
char *newline = NULL;
if (size == 0)
goto out;
if (strip_newline && con[size - 1] == '\n') {
newline = &con[size - 1];
size--;
}
if (parse_unconfined(con, size)) {
label = con;
goto out;
}
if (size > 3 && con[size - 1] == ')') {
int pos = size - 2;
while (pos > 0 && !(con[pos] == ' ' && con[pos + 1] == '('))
pos--;
if (pos > 0) {
con[pos] = 0; /* overwrite ' ' */
con[size - 1] = 0; /* overwrite trailing ) */
mode_str = &con[pos + 2]; /* skip '(' */
label = con;
}
}
out:
if (label && strip_newline && newline)
*newline = 0; /* overwrite '\n', if requested, on success */
if (mode)
*mode = mode_str;
return label;
}
/**
* aa_splitcon - split the confinement context into a label and mode
* @con: the confinement context
* @mode: if non-NULL and a mode is present, will point to mode string in @con
* on success
*
* Modifies the @con string to split it into separate label and mode strings. A
* single trailing newline character will be stripped from @con, if found. The
* @mode argument is optional. If @mode is NULL, @con will still be split
* between the label and mode (if present) but @mode will not be set.
*
* Returns: a pointer to the label string or NULL on error
*/
char *aa_splitcon(char *con, char **mode)
{
return splitcon(con, strlen(con), true, mode);
}
/**
* aa_getprocattr_raw - get the contents of @attr for @tid into @buf
* @tid: tid of task to query
* @attr: which /proc/<tid>/attr/<attr> to query
* @buf: buffer to store the result in
* @len: size of the buffer
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
*
* Returns: size of data read or -1 on error, and sets errno
*/
int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode)
{
int rc = -1;
int fd, ret;
char *tmp = NULL;
int size = 0;
if (!buf || len <= 0) {
errno = EINVAL;
goto out;
}
tmp = procattr_path(tid, attr);
if (!tmp)
goto out;
fd = open(tmp, O_RDONLY);
free(tmp);
if (fd == -1) {
goto out;
}
tmp = buf;
do {
ret = read(fd, tmp, len);
if (ret <= 0)
break;
tmp += ret;
size += ret;
len -= ret;
if (len < 0) {
errno = ERANGE;
goto out2;
}
} while (ret > 0);
if (ret < 0) {
int saved;
if (ret != -1) {
errno = EPROTO;
}
saved = errno;
(void)close(fd);
errno = saved;
goto out;
} else if (size > 0 && buf[size - 1] != 0) {
/* check for null termination */
if (buf[size - 1] != '\n') {
if (len == 0) {
errno = ERANGE;
goto out2;
} else {
buf[size] = 0;
size++;
}
}
if (splitcon(buf, size, true, mode) != buf) {
errno = EINVAL;
goto out2;
}
}
rc = size;
out2:
(void)close(fd);
out:
return rc;
}
#define INITIAL_GUESS_SIZE 128
/**
* aa_getprocattr - get the contents of @attr for @tid into @label and @mode
* @tid: tid of task to query
* @attr: which /proc/<tid>/attr/<attr> to query
* @label: allocated buffer the label is stored in
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: size of data read or -1 on error, and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode)
{
int rc, size = INITIAL_GUESS_SIZE/2;
char *buffer = NULL;
if (!label) {
errno = EINVAL;
return -1;
}
do {
char *tmp;
size <<= 1;
tmp = realloc(buffer, size);
if (!tmp) {
free(buffer);
return -1;
}
buffer = tmp;
memset(buffer, 0, size);
rc = aa_getprocattr_raw(tid, attr, buffer, size, mode);
} while (rc == -1 && errno == ERANGE);
if (rc == -1) {
free(buffer);
*label = NULL;
if (mode)
*mode = NULL;
} else
*label = buffer;
return rc;
}
static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
{
int rc = -1;
int fd, ret;
char *ctl = NULL;
if (!buf) {
errno = EINVAL;
goto out;
}
ctl = procattr_path(tid, attr);
if (!ctl)
goto out;
fd = open(ctl, O_WRONLY);
if (fd == -1) {
goto out;
}
ret = write(fd, buf, len);
if (ret != len) {
int saved;
if (ret != -1) {
errno = EPROTO;
}
saved = errno;
(void)close(fd);
errno = saved;
goto out;
}
rc = 0;
(void)close(fd);
out:
if (ctl) {
free(ctl);
}
return rc;
}
int aa_change_hat(const char *subprofile, unsigned long token)
{
int rc = -1;
int len = 0;
char *buf = NULL;
const char *fmt = "changehat %016lx^%s";
/* both may not be null */
if (!(token || subprofile)) {
errno = EINVAL;
goto out;
}
if (subprofile && strnlen(subprofile, PATH_MAX + 1) > PATH_MAX) {
errno = EPROTO;
goto out;
}
len = asprintf(&buf, fmt, token, subprofile ? subprofile : "");
if (len < 0) {
goto out;
}
rc = setprocattr(aa_gettid(), "current", buf, len);
out:
if (buf) {
/* clear local copy of magic token before freeing */
memset(buf, '\0', len);
free(buf);
}
return rc;
}
/* original change_hat interface */
int __change_hat(char *subprofile, unsigned int token)
{
return aa_change_hat(subprofile, (unsigned long) token);
}
int aa_change_profile(const char *profile)
{
char *buf = NULL;
int len;
int rc;
if (!profile) {
errno = EINVAL;
return -1;
}
len = asprintf(&buf, "changeprofile %s", profile);
if (len < 0)
return -1;
rc = setprocattr(aa_gettid(), "current", buf, len);
free(buf);
return rc;
}
int aa_change_onexec(const char *profile)
{
char *buf = NULL;
int len;
int rc;
if (!profile) {
errno = EINVAL;
return -1;
}
len = asprintf(&buf, "exec %s", profile);
if (len < 0)
return -1;
rc = setprocattr(aa_gettid(), "exec", buf, len);
free(buf);
return rc;
}
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
int aa_change_hatv(const char *subprofiles[], unsigned long token)
{
int size, totallen = 0, hatcount = 0;
int rc = -1;
const char **hats;
char *pos, *buf = NULL;
const char *cmd = "changehat";
/* both may not be null */
if (!token && !(subprofiles && *subprofiles)) {
errno = EINVAL;
goto out;
}
/* validate hat lengths and while we are at it count how many and
* mem required */
if (subprofiles) {
for (hats = subprofiles; *hats; hats++) {
int len = strnlen(*hats, PATH_MAX + 1);
if (len > PATH_MAX) {
errno = EPROTO;
goto out;
}
totallen += len + 1;
hatcount++;
}
}
/* allocate size of cmd + space + token + ^ + vector of hats */
size = strlen(cmd) + 18 + totallen + 1;
buf = malloc(size);
if (!buf) {
goto out;
}
/* setup command string which is of the form
* changehat <token>^hat1\0hat2\0hat3\0..\0
*/
sprintf(buf, "%s %016lx^", cmd, token);
pos = buf + strlen(buf);
if (subprofiles) {
for (hats = subprofiles; *hats; hats++) {
strcpy(pos, *hats);
pos += strlen(*hats) + 1;
}
} else
/* step pos past trailing \0 */
pos++;
rc = setprocattr(aa_gettid(), "current", buf, pos - buf);
out:
if (buf) {
/* clear local copy of magic token before freeing */
memset(buf, '\0', size);
free(buf);
}
return rc;
}
/**
* change_hat_vargs - change_hatv but passing the hats as fn arguments
* @token: the magic token
* @nhat: the number of hats being passed in the arguments
* ...: a argument list of const char * being passed
*
* change_hat_vargs can be called directly but it is meant to be called
* through its macro wrapper of the same name. Which automatically
* fills in the nhats arguments based on the number of parameters
* passed.
* to call change_hat_vargs direction do
* (change_hat_vargs)(token, nhats, hat1, hat2...)
*/
int (aa_change_hat_vargs)(unsigned long token, int nhats, ...)
{
va_list ap;
const char *argv[nhats+1];
int i;
va_start(ap, nhats);
for (i = 0; i < nhats ; i++) {
argv[i] = va_arg(ap, char *);
}
argv[nhats] = NULL;
va_end(ap);
return aa_change_hatv(argv, token);
}
/**
* aa_gettaskcon - get the confinement context for task @target in an allocated buffer
* @target: task to query
* @label: pointer to returned buffer with the label
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context or -1 on error and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_gettaskcon(pid_t target, char **label, char **mode)
{
return aa_getprocattr(target, "current", label, mode);
}
/**
* aa_getcon - get the confinement context for current task in an allocated buffer
* @label: pointer to return buffer with the label if successful
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context or -1 on error and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and may > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getcon(char **label, char **mode)
{
return aa_gettaskcon(aa_gettid(), label, mode);
}
#ifndef SO_PEERSEC
#define SO_PEERSEC 31
#endif
/**
* aa_getpeercon_raw - get the confinement context of the socket's peer (other end)
* @fd: socket to get peer confinement context for
* @buf: buffer to store the result in
* @len: initially contains size of the buffer, returns size of data read
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
*
* Returns: length of confinement context including null termination or -1 on
* error if errno == ERANGE then @len will hold the size needed
*/
int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode)
{
socklen_t optlen = *len;
int rc;
if (optlen <= 0 || buf == NULL) {
errno = EINVAL;
return -1;
}
rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &optlen);
if (rc == -1 || optlen <= 0)
goto out;
/* check for null termination */
if (buf[optlen - 1] != 0) {
if (optlen < *len) {
buf[optlen] = 0;
optlen++;
} else {
/* buf needs to be bigger by 1 */
rc = -1;
errno = ERANGE;
optlen++;
goto out;
}
}
if (splitcon(buf, optlen - 1, false, mode) != buf) {
rc = -1;
errno = EINVAL;
goto out;
}
rc = optlen;
out:
*len = optlen;
return rc;
}
/**
* aa_getpeercon - get the confinement context of the socket's peer (other end)
* @fd: socket to get peer confinement context for
* @label: pointer to allocated buffer with the label
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context including null termination or -1 on error
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getpeercon(int fd, char **label, char **mode)
{
int rc, last_size, size = INITIAL_GUESS_SIZE;
char *buffer = NULL;
if (!label) {
errno = EINVAL;
return -1;
}
do {
char *tmp;
last_size = size;
tmp = realloc(buffer, size);
if (!tmp) {
free(buffer);
return -1;
}
buffer = tmp;
memset(buffer, 0, size);
rc = aa_getpeercon_raw(fd, buffer, &size, mode);
/* size should contain actual size needed if errno == ERANGE */
} while (rc == -1 && errno == ERANGE && size > last_size);
if (rc == -1) {
free(buffer);
*label = NULL;
if (mode)
*mode = NULL;
size = -1;
} else
*label = buffer;
return size;
}
static pthread_once_t aafs_access_control = PTHREAD_ONCE_INIT;
static char *aafs_access = NULL;
static void aafs_access_init_once(void)
{
char *aafs;
int ret;
ret = aa_find_mountpoint(&aafs);
if (ret < 0)
return;
ret = asprintf(&aafs_access, "%s/.access", aafs);
if (ret < 0)
aafs_access = NULL;
free(aafs);
}
/* "allow 0x00000000\ndeny 0x00000000\naudit 0x00000000\nquiet 0x00000000\n" */
#define QUERY_LABEL_REPLY_LEN 67
/**
* aa_query_label - query the access(es) of a label
* @mask: permission bits to query
* @query: binary query string, must be offset by AA_QUERY_CMD_LABEL_SIZE
* @size: size of the query string must include AA_QUERY_CMD_LABEL_SIZE
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int query_label(uint32_t mask, char *query, size_t size, int *allowed,
int *audited)
{
char buf[QUERY_LABEL_REPLY_LEN];
uint32_t allow, deny, audit, quiet;
int fd, ret, saved;
if (!mask || size <= AA_QUERY_CMD_LABEL_SIZE) {
errno = EINVAL;
return -1;
}
ret = pthread_once(&aafs_access_control, aafs_access_init_once);
if (ret) {
errno = EINVAL;
return -1;
} else if (!aafs_access) {
errno = ENOMEM;
return -1;
}
fd = open(aafs_access, O_RDWR);
if (fd == -1) {
if (errno == ENOENT)
errno = EPROTONOSUPPORT;
return -1;
}
memcpy(query, AA_QUERY_CMD_LABEL, AA_QUERY_CMD_LABEL_SIZE);
errno = 0;
ret = write(fd, query, size);
if (ret != size) {
if (ret >= 0)
errno = EPROTO;
/* IMPORTANT: This is the only valid error path that can have
* errno set to ENOENT. It indicates that the subject label
* could not be found by the kernel.
*/
(void)close(fd);
return -1;
}
ret = read(fd, buf, QUERY_LABEL_REPLY_LEN);
saved = errno;
(void)close(fd);
errno = saved;
if (ret != QUERY_LABEL_REPLY_LEN) {
errno = EPROTO;
return -1;
}
ret = sscanf(buf, "allow 0x%8" SCNx32 "\n"
"deny 0x%8" SCNx32 "\n"
"audit 0x%8" SCNx32 "\n"
"quiet 0x%8" SCNx32 "\n",
&allow, &deny, &audit, &quiet);
if (ret != 4) {
errno = EPROTONOSUPPORT;
return -1;
}
*allowed = mask & ~(allow & ~deny) ? 0 : 1;
if (!(*allowed))
audit = 0xFFFFFFFF;
*audited = mask & ~(audit & ~quiet) ? 0 : 1;
return 0;
}
/* export multiple aa_query_label symbols to compensate for downstream
* releases with differing symbol versions. */
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
/**
* aa_query_file_path_len - query access permissions for a file @path
* @mask: permission bits to query
* @label: apparmor label
* @label_len: length of @label (does not include any terminating nul byte)
* @path: file path to query permissions for
* @path_len: length of @path (does not include any terminating nul byte)
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_file_path_len(uint32_t mask, const char *label, size_t label_len,
const char *path, size_t path_len, int *allowed,
int *audited)
{
autofree char *query = NULL;
/* + 1 for null separator */
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + path_len;
query = malloc(size + 1);
if (!query)
return -1;
memcpy(query + AA_QUERY_CMD_LABEL_SIZE, label, label_len);
/* null separator */
query[AA_QUERY_CMD_LABEL_SIZE + label_len] = 0;
query[AA_QUERY_CMD_LABEL_SIZE + label_len + 1] = AA_CLASS_FILE;
memcpy(query + AA_QUERY_CMD_LABEL_SIZE + label_len + 2, path, path_len);
return aa_query_label(mask, query, size , allowed, audited);
}
/**
* aa_query_file_path - query access permissions for a file @path
* @mask: permission bits to query
* @label: apparmor label
* @path: file path to query permissions for
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_file_path(uint32_t mask, const char *label, const char *path,
int *allowed, int *audited)
{
return aa_query_file_path_len(mask, label, strlen(label), path,
strlen(path), allowed, audited);
}
/**
* aa_query_link_path_len - query access permissions for a hard link @link
* @label: apparmor label
* @label_len: length of @label (does not include any terminating nul byte)
* @target: file path that hard link will point to
* @target_len: length of @target (does not include any terminating nul byte)
* @link: file path of hard link
* @link_len: length of @link (does not include any terminating nul byte)
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited)
{
autofree char *query = NULL;
int rc;
/* + 1 for null separators */
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + target_len +
1 + link_len;
size_t pos = AA_QUERY_CMD_LABEL_SIZE;
query = malloc(size);
if (!query)
return -1;
memcpy(query + pos, label, label_len);
/* null separator */
pos += label_len;
query[pos] = 0;
query[++pos] = AA_CLASS_FILE;
memcpy(query + pos + 1, link, link_len);
/* The kernel does the query in two parts we could similate this
* doing the following, however as long as policy is compiled
* correctly this isn't requied, and it requires and extra round
* trip to the kernel and adds a race on policy replacement between
* the two queries.
*
rc = aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
if (rc || !*allowed)
return rc;
*/
pos += 1 + link_len;
query[pos] = 0;
memcpy(query + pos + 1, target, target_len);
return aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
}
/**
* aa_query_link_path - query access permissions for a hard link @link
* @label: apparmor label
* @target: file path that hard link will point to
* @link: file path of hard link
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_link_path(const char *label, const char *target, const char *link,
int *allowed, int *audited)
{
return aa_query_link_path_len(label, strlen(label), target,
strlen(target), link, strlen(link),
allowed, audited);
}

File diff suppressed because it is too large Load Diff

View File

@@ -51,49 +51,3 @@ APPARMOR_2.9 {
local:
*;
} APPARMOR_1.1;
APPARMOR_2.10 {
global:
aa_query_file_path;
aa_query_file_path_len;
aa_query_link_path;
aa_query_link_path_len;
aa_features_new;
aa_features_new_from_string;
aa_features_new_from_kernel;
aa_features_ref;
aa_features_unref;
aa_features_write_to_file;
aa_features_is_equal;
aa_features_supports;
aa_kernel_interface_new;
aa_kernel_interface_ref;
aa_kernel_interface_unref;
aa_kernel_interface_load_policy;
aa_kernel_interface_load_policy_from_file;
aa_kernel_interface_load_policy_from_fd;
aa_kernel_interface_replace_policy;
aa_kernel_interface_replace_policy_from_file;
aa_kernel_interface_replace_policy_from_fd;
aa_kernel_interface_remove_policy;
aa_kernel_interface_write_policy;
aa_policy_cache_new;
aa_policy_cache_ref;
aa_policy_cache_unref;
aa_policy_cache_remove;
aa_policy_cache_replace_all;
aa_splitcon;
local:
*;
} APPARMOR_2.9;
PRIVATE {
global:
_aa_is_blacklisted;
_aa_autofree;
_aa_autoclose;
_aa_autofclose;
_aa_dirat_for_each;
local:
*;
};

View File

@@ -1,277 +0,0 @@
/*
* Copyright (c) 2014
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/apparmor.h>
#include "private.h"
#define CACHE_FEATURES_FILE ".features"
struct aa_policy_cache {
unsigned int ref_count;
aa_features *features;
aa_features *kernel_features;
int dirfd;
};
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
void *data unused)
{
/* remove regular files */
if (S_ISREG(st->st_mode))
return unlinkat(dirfd, path, 0);
/* do nothing with other file types */
return 0;
}
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
{
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
return -1;
if (aa_features_write_to_file(features, policy_cache->dirfd,
CACHE_FEATURES_FILE) == -1)
return -1;
aa_features_unref(policy_cache->features);
policy_cache->features = aa_features_ref(features);
return 0;
}
static int init_cache_features(aa_policy_cache *policy_cache,
aa_features *kernel_features, bool create)
{
bool call_create_cache = false;
if (aa_features_new(&policy_cache->features, policy_cache->dirfd,
CACHE_FEATURES_FILE)) {
policy_cache->features = NULL;
if (!create || errno != ENOENT)
return -1;
/* The cache directory needs to be created */
call_create_cache = true;
} else if (!aa_features_is_equal(policy_cache->features,
kernel_features)) {
if (!create) {
errno = EEXIST;
return -1;
}
/* The cache directory needs to be refreshed */
call_create_cache = true;
}
return call_create_cache ?
create_cache(policy_cache, kernel_features) : 0;
}
struct replace_all_cb_data {
aa_policy_cache *policy_cache;
aa_kernel_interface *kernel_interface;
};
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
void *cb_data)
{
int retval = 0;
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
struct replace_all_cb_data *data;
data = (struct replace_all_cb_data *) cb_data;
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
data->policy_cache->dirfd,
name);
}
return retval;
}
/**
* aa_policy_cache_new - create a new aa_policy_cache object from a path
* @policy_cache: will point to the address of an allocated and initialized
* aa_policy_cache_new object upon success
* @kernel_features: features representing a kernel (may be NULL if you want to
* use the features of the currently running kernel)
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: path to the policy cache
* @max_caches: The maximum number of policy caches, one for each unique set of
* kernel features, before older caches are auto-reaped. 0 means
* that no new caches should be created (existing, valid caches
* will be used) and auto-reaping is disabled. UINT16_MAX means
* that a cache can be created and auto-reaping is disabled.
*
* Returns: 0 on success, -1 on error with errno set and *@policy_cache
* pointing to NULL
*/
int aa_policy_cache_new(aa_policy_cache **policy_cache,
aa_features *kernel_features,
int dirfd, const char *path, uint16_t max_caches)
{
aa_policy_cache *pc;
bool create = max_caches > 0;
*policy_cache = NULL;
if (!path) {
errno = EINVAL;
return -1;
}
if (max_caches > 1) {
errno = ENOTSUP;
return -1;
}
pc = calloc(1, sizeof(*pc));
if (!pc) {
errno = ENOMEM;
return -1;
}
pc->dirfd = -1;
aa_policy_cache_ref(pc);
open:
pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (pc->dirfd < 0) {
int save;
/* does the dir exist? */
if (create && errno == ENOENT) {
if (mkdirat(dirfd, path, 0700) == 0)
goto open;
PERROR("Can't create cache directory '%s': %m\n", path);
} else if (create) {
PERROR("Can't update cache directory '%s': %m\n", path);
} else {
PDEBUG("Cache directory '%s' does not exist\n", path);
}
save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
if (kernel_features) {
aa_features_ref(kernel_features);
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
int save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
pc->kernel_features = kernel_features;
if (init_cache_features(pc, kernel_features, create)) {
int save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
*policy_cache = pc;
return 0;
}
/**
* aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
* @policy_cache: the policy_cache
*
* Returns: the policy_cache
*/
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
{
atomic_inc(&policy_cache->ref_count);
return policy_cache;
}
/**
* aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
* @policy_cache: the policy_cache (can be NULL)
*/
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
{
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
aa_features_unref(policy_cache->features);
aa_features_unref(policy_cache->kernel_features);
if (policy_cache->dirfd != -1)
close(policy_cache->dirfd);
free(policy_cache);
}
}
/**
* aa_policy_cache_remove - removes all policy cache files under a path
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: the path to a policy cache directory
*
* Returns: 0 on success, -1 on error with errno set
*/
int aa_policy_cache_remove(int dirfd, const char *path)
{
return _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb);
}
/**
* aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
* @policy_cache: the policy_cache
* @kernel_interface: the kernel interface to use when doing the replacement
* (may be NULL if the currently running kernel features
* were used when calling aa_policy_cache_new())
*
* Returns: 0 on success, -1 on error with errno set and features pointing to
* NULL
*/
int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
aa_kernel_interface *kernel_interface)
{
struct replace_all_cb_data cb_data;
int retval;
if (kernel_interface) {
aa_kernel_interface_ref(kernel_interface);
} else if (aa_kernel_interface_new(&kernel_interface,
policy_cache->kernel_features,
NULL) == -1) {
kernel_interface = NULL;
return -1;
}
cb_data.policy_cache = policy_cache;
cb_data.kernel_interface = kernel_interface;
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data,
replace_all_cb);
aa_kernel_interface_unref(kernel_interface);
return retval;
}

View File

@@ -1,252 +0,0 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "private.h"
/**
* Allow libapparmor to build on older systems where secure_getenv() is still
* named __secure_getenv(). This snippet was taken from the glibc wiki
* (https://sourceware.org/glibc/wiki/Tips_and_Tricks/secure_getenv).
*/
#ifndef HAVE_SECURE_GETENV
#ifdef HAVE___SECURE_GETENV
#define secure_getenv __secure_getenv
#else
#error neither secure_getenv nor __secure_getenv is available
#endif
#endif
struct ignored_suffix_t {
const char * text;
int len;
int silent;
};
static struct ignored_suffix_t ignored_suffixes[] = {
/* Debian packging files, which are in flux during install
should be silently ignored. */
{ ".dpkg-new", 9, 1 },
{ ".dpkg-old", 9, 1 },
{ ".dpkg-dist", 10, 1 },
{ ".dpkg-bak", 9, 1 },
/* RPM packaging files have traditionally not been silently
ignored */
{ ".rpmnew", 7, 0 },
{ ".rpmsave", 8, 0 },
/* patch file backups/conflicts */
{ ".orig", 5, 0 },
{ ".rej", 4, 0 },
/* Backup files should be mentioned */
{ "~", 1, 0 },
{ NULL, 0, 0 }
};
#define DEBUG_ENV_VAR "LIBAPPARMOR_DEBUG"
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...)
{
va_list args;
int openlog_options = 0;
if (honor_env_var && secure_getenv(DEBUG_ENV_VAR))
openlog_options |= LOG_PERROR;
openlog(ident, openlog_options, LOG_ERR);
va_start(args, fmt);
vsyslog(LOG_ERR, fmt, args);
va_end(args);
closelog();
}
void print_debug(const char *fmt, ...)
{
va_list args;
if (!secure_getenv(DEBUG_ENV_VAR))
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
void atomic_inc(unsigned int *v)
{
__sync_add_and_fetch(v, 1);
}
bool atomic_dec_and_test(unsigned int *v)
{
return __sync_sub_and_fetch(v, 1) == 0;
}
int _aa_is_blacklisted(const char *name)
{
size_t name_len = strlen(name);
struct ignored_suffix_t *suffix;
/* skip dot files and files with no name */
if (!name_len || *name == '.' || !strcmp(name, "README"))
return 1;
/* skip blacklisted suffixes */
for (suffix = ignored_suffixes; suffix->text; suffix++) {
char *found;
if ( (found = strstr((char *) name, suffix->text)) &&
found - name + suffix->len == name_len ) {
if (!suffix->silent)
return -1;
return 1;
}
}
return 0;
}
/* automaticly free allocated variables tagged with autofree on fn exit */
void _aa_autofree(void *p)
{
void **_p = (void**)p;
free(*_p);
}
void _aa_autoclose(int *fd)
{
if (*fd != -1) {
/* if close was interrupted retry */
while(close(*fd) == -1 && errno == EINTR);
*fd = -1;
}
}
void _aa_autofclose(FILE **f)
{
if (*f) {
fclose(*f);
*f = NULL;
}
}
int _aa_asprintf(char **strp, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vasprintf(strp, fmt, args);
va_end(args);
if (rc == -1)
*strp = NULL;
return rc;
}
static int dot_or_dot_dot_filter(const struct dirent *ent)
{
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
return 0;
return 1;
}
/**
* _aa_dirat_for_each: iterate over a directory calling cb for each entry
* @dirfd: already opened directory
* @name: name of the directory (NOT NULL)
* @data: data pointer to pass to the callback fn (MAY BE NULL)
* @cb: the callback to pass entry too (NOT NULL)
*
* Iterate over the entries in a directory calling cb for each entry.
* The directory to iterate is determined by a combination of @dirfd and
* @name.
*
* See the openat section of the open(2) man page for details on valid @dirfd
* and @name combinations. This function does accept AT_FDCWD as @dirfd if
* @name should be considered relative to the current working directory.
*
* Pass "." for @name if @dirfd is the directory to iterate over.
*
* The cb function is called with the DIR in use and the name of the
* file in that directory. If the file is to be opened it should
* use the openat, fstatat, and related fns.
*
* Returns: 0 on success, else -1 and errno is set to the error code
*/
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
int (* cb)(int, const char *, struct stat *, void *))
{
autofree struct dirent **namelist = NULL;
autoclose int cb_dirfd = -1;
int i, num_dirs, rc;
if (!cb || !name) {
errno = EINVAL;
return -1;
}
cb_dirfd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (cb_dirfd == -1) {
PDEBUG("could not open directory '%s': %m\n", name);
return -1;
}
num_dirs = scandirat(cb_dirfd, ".", &namelist,
dot_or_dot_dot_filter, NULL);
if (num_dirs == -1) {
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
return -1;
}
for (rc = 0, i = 0; i < num_dirs; i++) {
/* Must cycle through all dirs so that each one is autofreed */
autofree struct dirent *dir = namelist[i];
struct stat my_stat;
if (rc)
continue;
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
rc = -1;
continue;
}
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
PDEBUG("dir_for_each callback failed for '%s'\n",
dir->d_name);
rc = -1;
continue;
}
}
return rc;
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AA_PRIVATE_H
#define _AA_PRIVATE_H 1
#include <stdbool.h>
#include <sys/apparmor_private.h>
#define autofree __attribute((cleanup(_aa_autofree)))
#define autoclose __attribute((cleanup(_aa_autoclose)))
#define autofclose __attribute((cleanup(_aa_autofclose)))
#define unused __attribute__ ((unused))
#define asprintf _aa_asprintf
#if ENABLE_DEBUG_OUTPUT
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
#define PDEBUG(fmt, args...) print_debug("libapparmor: " fmt, ## args)
#else /* ENABLE_DEBUG_OUTPUT */
#define PERROR(fmt, args...) print_error(false, "libapparmor", fmt, ## args)
#define PDEBUG(fmt, args...) /* do nothing */
#endif /* ENABLE_DEBUG_OUTPUT */
#define MY_TEST(statement, error) \
if (!(statement)) { \
fprintf(stderr, "FAIL: %s\n", error); \
rc = 1; \
}
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...);
void print_debug(const char *fmt, ...);
void atomic_inc(unsigned int *v);
bool atomic_dec_and_test(unsigned int *v);
#endif /* _AA_PRIVATE_H */

View File

@@ -178,7 +178,7 @@ syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(
hhmmss {digit}{2}{colon}{digit}{2}{colon}{digit}{2}
timezone ({plus}|{minus}){digit}{2}{colon}{digit}{2}
syslog_time {hhmmss}({period}{digits})?{timezone}?
syslog_hostname [[:alnum:]._-]+
syslog_hostname [[:alnum:]_-]+
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
%x single_quoted_string
@@ -355,7 +355,6 @@ yy_flex_debug = 0;
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_TIME); }
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
{dmesg_timestamp} { yylval->t_str = strdup(yytext); return(TOK_DMESG_STAMP); }
. { /* ignore any non-matched input */ BEGIN(unknown_message); yyless(0); }

View File

@@ -20,7 +20,13 @@
#include <stdio.h>
#include <aalogparse.h>
#include "parser.h"
#include "private.h"
#define MY_TEST(statement, error) \
if (!(statement)) { \
fprintf(stderr, "FAIL: %s\n", error); \
rc = 1; \
}
int main(void)
{
@@ -34,25 +40,19 @@ int main(void)
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
MY_TEST(retstr, "basic allocation");
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
free(retstr);
retstr = hex_to_string("61");
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
free(retstr);
retstr = hex_to_string("");
MY_TEST(strcmp(retstr, "") == 0, "empty string");
free(retstr);
/* ipproto_to_string() tests */
retstr = ipproto_to_string((unsigned) 99999);
MY_TEST(strcmp(retstr, "unknown(99999)") == 0, "invalid protocol test");
free(retstr);
retstr = ipproto_to_string((unsigned) 6);
MY_TEST(strcmp(retstr, "tcp") == 0, "protocol=tcp");
free(retstr);
return rc;
}

View File

@@ -1,247 +0,0 @@
/*
* Copyright (c) 2015
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <stdio.h>
#include <string.h>
#include "private.h"
#include "features.c"
static int test_tokenize_path_components(void)
{
struct component components[32];
size_t max = sizeof(components) / sizeof(*components);
size_t num;
int rc = 0;
num = tokenize_path_components(NULL, components, max);
MY_TEST(num == 0, "basic NULL test");
num = tokenize_path_components("", components, max);
MY_TEST(num == 0, "basic empty string test");
num = tokenize_path_components("a", components, 0);
MY_TEST(num == 0, "basic empty array test");
num = tokenize_path_components("a", components, 1);
MY_TEST(num == 1, "one component full test (num)");
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
"one component full test (components[0])");
num = tokenize_path_components("a/b", components, 2);
MY_TEST(num == 2, "two component full test (num)");
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
"two component full test (components[0])");
MY_TEST(!strncmp(components[1].str, "b", components[0].len),
"two component full test (components[1])");
num = tokenize_path_components("a/b/c", components, 1);
MY_TEST(num == 1, "not enough components full test (num)");
MY_TEST(!strncmp(components[0].str, "a/b/c", components[0].len),
"not enough components full test (components[0])");
num = tokenize_path_components("/", components, max);
MY_TEST(num == 0, "no valid components #1 (num)");
num = tokenize_path_components("////////", components, max);
MY_TEST(num == 0, "no valid components #2 (num)");
num = tokenize_path_components("////////////foo////", components, max);
MY_TEST(num == 1, "many invalid components (num)");
MY_TEST(!strncmp(components[0].str, "foo", components[0].len),
"many invalid components (components[0])");
num = tokenize_path_components("file", components, max);
MY_TEST(num == 1, "file (num)");
MY_TEST(!strncmp(components[0].str, "file", components[0].len),
"file (components[0])");
num = tokenize_path_components("/policy///versions//v7/", components, max);
MY_TEST(num == 3, "v7 (num)");
MY_TEST(!strncmp(components[0].str, "policy", components[0].len),
"v7 (components[0])");
MY_TEST(!strncmp(components[1].str, "versions", components[1].len),
"v7 (components[1])");
MY_TEST(!strncmp(components[2].str, "v7", components[2].len),
"v7 (components[2])");
num = tokenize_path_components("dbus/mask/send", components, max);
MY_TEST(num == 3, "dbus send (num)");
MY_TEST(!strncmp(components[0].str, "dbus", components[0].len),
"dbus send (components[0])");
MY_TEST(!strncmp(components[1].str, "mask", components[1].len),
"dbus send (components[1])");
MY_TEST(!strncmp(components[2].str, "send", components[2].len),
"dbus send (components[2])");
return rc;
}
static int do_test_walk_one(const char **str, const struct component *component,
bool is_top_level, bool expect_walk, const char *e1,
const char *e2, const char *e3)
{
const char *save = str ? *str : NULL;
bool walked = walk_one(str, component, is_top_level);
int rc = 0;
/* Check if the result of the walk matches the expected result*/
MY_TEST(expect_walk == walked, e1);
if (save) {
/**
* If a walk was expected, @*str should have changed. It
* shouldn't change if a walk was unexpected.
*/
if (expect_walk) {
MY_TEST(*str != save, e2);
} else {
MY_TEST(*str == save, e3);
}
}
return rc;
}
#define MY_WALK_TEST(str, component, is_top_level, expect_walk, error) \
if (do_test_walk_one(str, component, is_top_level, \
expect_walk, \
error " (walk check)", \
error " (str didn't change)", \
error " (str changed)")) { \
rc = 1; \
}
#define MY_GOOD_WALK_TEST(str, component, is_top_level, error) \
MY_WALK_TEST(str, component, is_top_level, true, error)
#define MY_BAD_WALK_TEST(str, component, is_top_level, error) \
MY_WALK_TEST(str, component, is_top_level, false, error)
static int test_walk_one(void)
{
struct component c;
const char *str;
int rc = 0;
MY_BAD_WALK_TEST(NULL, &c, true, "basic NULL str test");
str = NULL;
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL *str test");
str = "test { a b }";
MY_BAD_WALK_TEST(&str, NULL, true, "basic NULL component test");
str = "test { a b }";
c = (struct component) { NULL, 8 };
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL c.str test");
str = "test { a b }";
c = (struct component) { "", 0 };
MY_BAD_WALK_TEST(&str, &c, true, "basic empty c.str test");
str = "test";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component");
str = "testX";
c = (struct component) { "test", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "single component bad str");
str = "test";
c = (struct component) { "testX", 5 };
MY_BAD_WALK_TEST(&str, &c, true, "single component bad c.str");
str = "test { }";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #1");
str = "test {\n\t}";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #2");
str = "test{}";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #3");
str = "test\t{}\n ";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #4");
str = "test {}";
c = (struct component) { "test", 4 };
MY_BAD_WALK_TEST(&str, &c, false, "single component bad is_top_level");
str = "front{back";
c = (struct component) { "frontback", 9};
MY_BAD_WALK_TEST(&str, &c, true, "brace in the middle #1");
MY_BAD_WALK_TEST(&str, &c, false, "brace in the middle #2");
str = "ardvark { bear cat { deer } }";
c = (struct component) { "ardvark", 7 };
MY_GOOD_WALK_TEST(&str, &c, true, "animal walk good ardvark");
c = (struct component) { "deer", 4 };
MY_BAD_WALK_TEST(&str, &c, false, "animal walk bad deer");
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad top-level deer");
c = (struct component) { "bear", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad bear");
c = (struct component) { "cat", 3 };
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good cat");
c = (struct component) { "ardvark", 7 };
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad ardvark");
c = (struct component) { "deer", 4 };
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good deer");
str = "dbus {mask {acquire send receive\n}\n}\nsignal {mask {hup int\n}\n}";
c = (struct component) { "hup", 3 };
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad hup #1");
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad hup #2");
c = (struct component) { "signal", 6 };
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad signal");
MY_GOOD_WALK_TEST(&str, &c, true, "dbus/signal good signal");
c = (struct component) { "mask", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad mask");
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good mask");
c = (struct component) { "hup", 3 };
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good hup");
str = "policy {set_load {yes\n}\nversions {v7 {yes\n}\nv6 {yes\n}";
c = (struct component) { "policy", 6 };
MY_GOOD_WALK_TEST(&str, &c, true, "policy good");
c = (struct component) { "versions", 8 };
MY_GOOD_WALK_TEST(&str, &c, false, "versions good");
c = (struct component) { "v7", 2 };
MY_GOOD_WALK_TEST(&str, &c, false, "v7 good");
return rc;
}
int main(void)
{
int retval, rc = 0;
retval = test_tokenize_path_components();
if (retval)
rc = retval;
retval = test_walk_one();
if (retval)
rc = retval;
return rc;
}

View File

@@ -1,228 +0,0 @@
/*
* Copyright (c) 2015
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <stdio.h>
#include <string.h>
#include "kernel.c"
static int nullcmp_and_strcmp(const void *s1, const void *s2)
{
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
if (!s1 || !s2)
return s1 != s2;
return strcmp(s1, s2);
}
static int do_test_splitcon(char *con, int size, bool strip_nl, char **mode,
const char *expected_label,
const char *expected_mode, const char *error)
{
char *label;
int rc = 0;
label = splitcon(con, size, strip_nl, mode);
if (nullcmp_and_strcmp(label, expected_label)) {
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
error, label, expected_label);
rc = 1;
}
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
error, *mode, expected_mode);
rc = 1;
}
return rc;
}
static int do_test_aa_splitcon(char *con, char **mode,
const char *expected_label,
const char *expected_mode, const char *error)
{
char *label;
int rc = 0;
label = aa_splitcon(con, mode);
if (nullcmp_and_strcmp(label, expected_label)) {
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
error, label, expected_label);
rc = 1;
}
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
error, *mode, expected_mode);
rc = 1;
}
return rc;
}
#define TEST_SPLITCON(con, size, strip_nl, expected_label, \
expected_mode, error) \
do { \
char c1[] = con; \
char c2[] = con; \
size_t sz = size < 0 ? strlen(con) : size; \
char *mode; \
\
if (do_test_splitcon(c1, sz, strip_nl, &mode, \
expected_label, expected_mode, \
"splitcon: " error)) { \
rc = 1; \
} else if (do_test_splitcon(c2, sz, strip_nl, NULL, \
expected_label, NULL, \
"splitcon: " error " (NULL mode)")) { \
rc = 1; \
} \
} while (0)
#define TEST_AA_SPLITCON(con, expected_label, expected_mode, error) \
do { \
char c1[] = con; \
char c2[] = con; \
char c3[] = con "\n"; \
char *mode; \
\
if (do_test_aa_splitcon(c1, &mode, expected_label, \
expected_mode, "aa_splitcon: " error)) {\
rc = 1; \
} else if (do_test_aa_splitcon(c2, NULL, expected_label,\
NULL, \
"aa_splitcon: " error " (NULL mode)")) {\
rc = 1; \
} else if (do_test_aa_splitcon(c3, &mode, \
expected_label, expected_mode, \
"aa_splitcon: " error " (newline)")) { \
rc = 1; \
} \
} while (0)
static int test_splitcon(void)
{
int rc = 0;
/**
* NOTE: the TEST_SPLITCON() macro automatically generates
* corresponding tests with a NULL mode pointer.
*/
TEST_SPLITCON("", 0, true, NULL, NULL, "empty string test #1");
TEST_SPLITCON("", 0, false, NULL, NULL, "empty string test #2");
TEST_SPLITCON("unconfined", -1, true, "unconfined", NULL,
"unconfined #1");
TEST_SPLITCON("unconfined", -1, false, "unconfined", NULL,
"unconfined #2");
TEST_SPLITCON("unconfined\n", -1, true, "unconfined", NULL,
"unconfined #3");
TEST_SPLITCON("unconfined\n", -1, false, NULL, NULL,
"unconfined #4");
TEST_SPLITCON("label (mode)", -1, true, "label", "mode",
"basic split #1");
TEST_SPLITCON("label (mode)", -1, false, "label", "mode",
"basic split #2");
TEST_SPLITCON("label (mode)\n", -1, true, "label", "mode",
"basic split #3");
TEST_SPLITCON("label (mode)\n", -1, false, NULL, NULL,
"basic split #4");
TEST_SPLITCON("/a/b/c (enforce)", -1, true, "/a/b/c", "enforce",
"path enforce split #1");
TEST_SPLITCON("/a/b/c (enforce)", -1, false, "/a/b/c", "enforce",
"path enforce split #2");
TEST_SPLITCON("/a/b/c (enforce)\n", -1, true, "/a/b/c", "enforce",
"path enforce split #3");
TEST_SPLITCON("/a/b/c (enforce)\n", -1, false, NULL, NULL,
"path enforce split #4");
return rc;
}
static int test_aa_splitcon(void)
{
int rc = 0;
/**
* NOTE: the TEST_AA_SPLITCON() macro automatically generates
* corresponding tests with a NULL mode pointer and contexts with
* trailing newline characters.
*/
TEST_AA_SPLITCON("label (mode)", "label", "mode", "basic split");
TEST_AA_SPLITCON("/a/b/c (enforce)", "/a/b/c", "enforce",
"path enforce split");
TEST_AA_SPLITCON("/a/b/c (complain)", "/a/b/c", "complain",
"path complain split");
TEST_AA_SPLITCON("profile_name (enforce)", "profile_name", "enforce",
"name enforce split");
TEST_AA_SPLITCON("profile_name (complain)", "profile_name", "complain",
"name complain split");
TEST_AA_SPLITCON("unconfined", "unconfined", NULL, "unconfined");
TEST_AA_SPLITCON("(odd) (enforce)", "(odd)", "enforce",
"parenthesized label #1");
TEST_AA_SPLITCON("(odd) (enforce) (enforce)", "(odd) (enforce)",
"enforce", "parenthesized label #2");
TEST_AA_SPLITCON("/usr/bin/😺 (enforce)", "/usr/bin/😺", "enforce",
"non-ASCII path");
TEST_AA_SPLITCON("👍 (enforce)", "👍", "enforce",
"non-ASCII profile name");
/* Negative tests */
TEST_AA_SPLITCON("", NULL, NULL, "empty string test");
TEST_AA_SPLITCON("profile\t(enforce)", NULL, NULL,
"invalid tab separator");
TEST_AA_SPLITCON("profile(enforce)", NULL, NULL,
"invalid missing separator");
return rc;
}
int main(void)
{
int retval, rc = 0;
retval = test_splitcon();
if (retval)
rc = retval;
retval = test_aa_splitcon();
if (retval)
rc = retval;
return rc;
}

View File

@@ -3,30 +3,12 @@
%{
#include <aalogparse.h>
#include <sys/apparmor.h>
#include <sys/apparmor_private.h>
%}
%include "typemaps.i"
%include <aalogparse.h>
/**
* swig doesn't like the macro magic we do in apparmor.h and apparmor_private.h
* so the function prototypes must be manually inserted.
*
* Functions that return a negative int and set errno upon error use a special
* %exception directive and must be listed after the %exception below. All
* other functions go here.
*/
/* apparmor.h */
extern char *aa_splitcon(char *con, char **mode);
/* apparmor_private.h */
extern int _aa_is_blacklisted(const char *name);
#ifdef SWIGPYTHON
%exception {
$action
@@ -37,9 +19,9 @@ extern int _aa_is_blacklisted(const char *name);
}
#endif
/* Functions that return a negative int and set errno upon error go here. */
/* apparmor.h */
/* swig doesn't like the macro magic we do in apparmor.h so the fn prototypes
* are manually inserted here
*/
extern int aa_is_enabled(void);
extern int aa_find_mountpoint(char **mnt);
@@ -51,22 +33,11 @@ extern int aa_change_hat_vargs(unsigned long token, int count, ...);
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
extern int aa_getcon(char **label, char **mode);
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
extern int aa_getcon(char **con, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
extern int aa_getpeercon(int fd, char **label, char **mode);
extern int aa_getpeercon(int fd, char **con, char **mode);
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
int *audit);
extern int aa_query_file_path_len(uint32_t mask, const char *label,
size_t label_len, const char *path,
size_t path_len, int *allowed, int *audited);
extern int aa_query_file_path(uint32_t mask, const char *label,
const char *path, int *allowed, int *audited);
extern int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);
extern int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);
%exception;

View File

@@ -6,8 +6,9 @@ SUBDIRS = test
libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
$(SWIG) -python -I$(srcdir)/../../include -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
mv LibAppArmor.py __init__.py
MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
MOSTLYCLEANFILES=libapparmor_wrap.c __init__.py
all-local: libapparmor_wrap.c setup.py
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi

View File

@@ -1,6 +0,0 @@
import sys
if sys.version_info[0] >= 3:
from LibAppArmor.LibAppArmor import *
else:
from .LibAppArmor import *

View File

@@ -1 +0,0 @@
[103975.623545] audit: type=1400 audit(1481284511.494:2807): apparmor="DENIED" operation="change_onexec" info="no new privs" error=-1 namespace="root//lxd-tor_<var-lib-lxd>" profile="unconfined" name="system_tor" pid=18593 comm="(tor)" target="system_tor"

View File

@@ -1,15 +0,0 @@
START
File: change_onexec_lp1648143.in
Event type: AA_RECORD_DENIED
Audit ID: 1481284511.494:2807
Operation: change_onexec
Profile: unconfined
Name: system_tor
Command: (tor)
Name2: system_tor
Namespace: root//lxd-tor_<var-lib-lxd>
Info: no new privs
ErrorCode: 1
PID: 18593
Epoch: 1481284511
Audit subid: 2807

View File

@@ -1 +0,0 @@
type=AVC msg=audit(1465133533.431:728): apparmor="DENIED" operation="chown" profile="/usr/sbin/cupsd" name="/run/cups/certs/" pid=8515 comm="cupsd" requested_mask="w" denied_mask="w" fsuid=0 ouid=4

View File

@@ -1,15 +0,0 @@
START
File: file_chown.in
Event type: AA_RECORD_DENIED
Audit ID: 1465133533.431:728
Operation: chown
Mask: w
Denied Mask: w
fsuid: 0
ouid: 4
Profile: /usr/sbin/cupsd
Name: /run/cups/certs/
Command: cupsd
PID: 8515
Epoch: 1465133533
Audit subid: 728

View File

@@ -1 +0,0 @@
Oct 22 15:57:38 NR021AA kernel: [ 69.827705] audit: type=1400 audit(1445522258.769:1054): apparmor="DENIED" operation="file_inherit" profile="/usr/lib/NetworkManager/nm-dhcp-client.action" pid=2407 comm="nm-dhcp-client." lport=10580 family="inet6" sock_type="dgram" protocol=17

View File

@@ -1,14 +0,0 @@
START
File: file_inherit_network_lp1509030.in
Event type: AA_RECORD_DENIED
Audit ID: 1445522258.769:1054
Operation: file_inherit
Profile: /usr/lib/NetworkManager/nm-dhcp-client.action
Command: nm-dhcp-client.
PID: 2407
Network family: inet6
Socket type: dgram
Protocol: udp
Local port: 10580
Epoch: 1445522258
Audit subid: 1054

View File

@@ -1 +0,0 @@
Jun 19 12:00:55 piorun kernel: [4475115.459952] audit: type=1400 audit(1434708055.676:19629): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2" pid=3512 comm="apache2" laddr=::ffff:192.168.236.159 lport=80 faddr=::ffff:192.168.103.80 fport=61985 family="inet6" sock_type="stream" protocol=6

View File

@@ -1,17 +0,0 @@
START
File: file_perm_network_lp1466812.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1434708055.676:19629
Operation: file_perm
Profile: /usr/sbin/apache2
Command: apache2
PID: 3512
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:192.168.236.159
Foreign addr: ::ffff:192.168.103.80
Local port: 80
Foreign port: 61985
Epoch: 1434708055
Audit subid: 19629

View File

@@ -1 +0,0 @@
type=AVC msg=audit(1463403689.381:267599): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2//www.xxxxxxxxxx.co.uk" pid=13215 comm="apache2" laddr=::ffff:192.168.1.100 lport=80 faddr=::ffff:192.168.1.100 fport=45658 family="inet6" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"

View File

@@ -1,19 +0,0 @@
START
File: file_perm_network_receive_lp1577051.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1463403689.381:267599
Operation: file_perm
Mask: send
Denied Mask: send
Profile: /usr/sbin/apache2//www.xxxxxxxxxx.co.uk
Command: apache2
PID: 13215
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:192.168.1.100
Foreign addr: ::ffff:192.168.1.100
Local port: 80
Foreign port: 45658
Epoch: 1463403689
Audit subid: 267599

View File

@@ -1 +0,0 @@
Apr 30 21:53:05 nova kernel: [24668.960760] audit: type=1400 audit(1462045985.636:2154): apparmor="ALLOWED" operation="file_perm" profile="/usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java" pid=12529 comm="java" laddr=::ffff:127.0.0.1 lport=8080 faddr=::ffff:127.0.0.1 fport=52308 family="inet6" sock_type="stream" protocol=6 requested_mask="receive" denied_mask="receive"

View File

@@ -1,19 +0,0 @@
START
File: file_perm_network_receive_lp1582374.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1462045985.636:2154
Operation: file_perm
Mask: receive
Denied Mask: receive
Profile: /usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java
Command: java
PID: 12529
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:127.0.0.1
Foreign addr: ::ffff:127.0.0.1
Local port: 8080
Foreign port: 52308
Epoch: 1462045985
Audit subid: 2154

View File

@@ -1 +0,0 @@
Sep 14 18:49:13 mfa-mia-74-app-rabbitmq-1.mia.ix.int kernel: [964718.247816] type=1400 audit(1442256553.643:40143): apparmor="ALLOWED" operation="open" profile="/opt/evoke/venv/bin/gunicorn" name="/opt/evoke/venv/lib/python2.7/warnings.pyc" pid=28943 comm="gunicorn" requested_mask="r" denied_mask="r" fsuid=1000 ouid=110

View File

@@ -1,15 +0,0 @@
START
File: syslog_hostname_with_dot.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1442256553.643:40143
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 110
Profile: /opt/evoke/venv/bin/gunicorn
Name: /opt/evoke/venv/lib/python2.7/warnings.pyc
Command: gunicorn
PID: 28943
Epoch: 1442256553
Audit subid: 40143

View File

@@ -1 +0,0 @@
type=AVC msg=audit(1449442292.901:961): apparmor="ALLOWED" operation="change_hat" profile="/usr/sbin/httpd{,2}-prefork" pid=8527 comm="httpd-prefork" target="/usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT"

View File

@@ -1,11 +0,0 @@
START
File: testcase_changehat_01.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1449442292.901:961
Operation: change_hat
Profile: /usr/sbin/httpd{,2}-prefork
Command: httpd-prefork
Name2: /usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT
PID: 8527
Epoch: 1449442292
Audit subid: 961

View File

@@ -1 +0,0 @@
Sep 9 12:51:36 ubuntu-desktop kernel: [ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"

View File

@@ -1,11 +0,0 @@
START
File: testcase_changeprofile_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1431116353.523:77
Operation: change_profile
Profile: /tests/regression/apparmor/changeprofile
Command: changeprofile
Name2: /tests/regression/apparmor/rename
PID: 3459
Epoch: 1431116353
Audit subid: 77

View File

@@ -1 +0,0 @@
[ 1612.746129] audit: type=1400 audit(1284061910.975:672): apparmor="DENIED" operation="capable" parent=2663 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority" pid=7292 comm="syscall_setprio" capability=23 capname="sys_nice"

View File

@@ -1,12 +0,0 @@
START
File: testcase_dmesg_capability.in
Event type: AA_RECORD_DENIED
Audit ID: 1284061910.975:672
Operation: capable
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority
Name: sys_nice
Command: syscall_setprio
Parent: 2663
PID: 7292
Epoch: 1284061910
Audit subid: 672

View File

@@ -1 +0,0 @@
[ 1597.774866] audit: type=1400 audit(1284061896.005:28): apparmor="DENIED" operation="change_hat" info="unconfined" error=-1 pid=2698 comm="syscall_ptrace"

View File

@@ -1,11 +0,0 @@
START
File: testcase_dmesg_changehat_negative_error.in
Event type: AA_RECORD_DENIED
Audit ID: 1284061896.005:28
Operation: change_hat
Command: syscall_ptrace
Info: unconfined
ErrorCode: 1
PID: 2698
Epoch: 1284061896
Audit subid: 28

View File

@@ -1 +0,0 @@
[ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"

View File

@@ -1,11 +0,0 @@
START
File: testcase_dmesg_changeprofile_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1431116353.523:77
Operation: change_profile
Profile: /tests/regression/apparmor/changeprofile
Command: changeprofile
Name2: /tests/regression/apparmor/rename
PID: 3459
Epoch: 1431116353
Audit subid: 77

View File

@@ -1 +0,0 @@
[ 2010.738449] audit: type=1400 audit(1284062308.965:276251): apparmor="DENIED" operation="link" parent=19088 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/link" name="/tmp/sdtest.19088-12382-HWH57d/linkfile" pid=19142 comm="link" requested_mask="l" denied_mask="l" fsuid=0 ouid=0 target="/tmp/sdtest.19088-12382-HWH57d/target"

View File

@@ -1,17 +0,0 @@
START
File: testcase_dmesg_link_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1284062308.965:276251
Operation: link
Mask: l
Denied Mask: l
fsuid: 0
ouid: 0
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/link
Name: /tmp/sdtest.19088-12382-HWH57d/linkfile
Command: link
Name2: /tmp/sdtest.19088-12382-HWH57d/target
Parent: 19088
PID: 19142
Epoch: 1284062308
Audit subid: 276251

View File

@@ -1 +0,0 @@
[45334.755142] audit: type=1503 audit(1282671283.411:2199): operation="mkdir" pid=4786 parent=4708 profile="/usr/sbin/sshd//ubuntu" requested_mask="c::" denied_mask="c::" fsuid=1000 ouid=1000 name="/tmp/ssh-gRozJw4786/"

View File

@@ -1,15 +0,0 @@
START
File: testcase_dmesg_mkdir.in
Event type: AA_RECORD_DENIED
Audit ID: 1282671283.411:2199
Operation: mkdir
Mask: c::
Denied Mask: c::
fsuid: 1000
ouid: 1000
Profile: /usr/sbin/sshd//ubuntu
Name: /tmp/ssh-gRozJw4786/
Parent: 4708
PID: 4786
Epoch: 1282671283
Audit subid: 2199

View File

@@ -1 +0,0 @@
[ 878.663418] audit: type=1502 audit(1282626827.320:413): operation="rename_dest" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="wc::" denied_mask="wc::" fsuid=0 ouid=0 name="/var/run/motd"

View File

@@ -1,15 +0,0 @@
START
File: testcase_dmesg_rename_dest.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1282626827.320:413
Operation: rename_dest
Mask: wc::
Denied Mask: wc::
fsuid: 0
ouid: 0
Profile: /usr/sbin/sshd
Name: /var/run/motd
Parent: 650
PID: 1881
Epoch: 1282626827
Audit subid: 413

View File

@@ -1 +0,0 @@
[ 878.663410] audit: type=1502 audit(1282626827.320:412): operation="rename_src" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="r::" denied_mask="r::" fsuid=0 ouid=0 name="/var/run/motd.new"

View File

@@ -1,15 +0,0 @@
START
File: testcase_dmesg_rename_src.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1282626827.320:412
Operation: rename_src
Mask: r::
Denied Mask: r::
fsuid: 0
ouid: 0
Profile: /usr/sbin/sshd
Name: /var/run/motd.new
Parent: 650
PID: 1881
Epoch: 1282626827
Audit subid: 412

View File

@@ -1 +0,0 @@
[ 2143.902340] audit: type=1400 audit(1283989336.064:272335): apparmor="STATUS" info="failed to unpack profile" error=-71 pid=4958 comm="apparmor_parser" name="/home/jj/master/tests/regression/apparmor/net_raw" offset=159

View File

@@ -1,11 +0,0 @@
START
File: testcase_dmesg_status_offset.in
Event type: AA_RECORD_STATUS
Audit ID: 1283989336.064:272335
Name: /home/jj/master/tests/regression/apparmor/net_raw
Command: apparmor_parser
Info: failed to unpack profile
ErrorCode: 71
PID: 4958
Epoch: 1283989336
Audit subid: 272335

View File

@@ -1 +0,0 @@
[ 878.662172] audit: type=1503 audit(1282626827.320:411): operation="truncate" pid=1957 parent=1 profile="/etc/update-motd.d/91-release-upgrade" requested_mask="w::" denied_mask="w::" fsuid=0 ouid=0 name="/var/lib/update-notifier/release-upgrade-available"

View File

@@ -1,15 +0,0 @@
START
File: testcase_dmesg_truncate.in
Event type: AA_RECORD_DENIED
Audit ID: 1282626827.320:411
Operation: truncate
Mask: w::
Denied Mask: w::
fsuid: 0
ouid: 0
Profile: /etc/update-motd.d/91-release-upgrade
Name: /var/lib/update-notifier/release-upgrade-available
Parent: 1
PID: 1957
Epoch: 1282626827
Audit subid: 411

View File

@@ -1 +0,0 @@
Jul 29 11:42:05 files kernel: [483212.877816] audit: type=1400 audit(1469785325.122:21021): apparmor="ALLOWED" operation="file_inherit" profile="/usr/bin/nginx-amplify-agent.py//null-/bin/dash" pid=18239 comm="sh" laddr=192.168.10.3 lport=50758 faddr=54.153.70.241 fport=443 family="inet" sock_type="stream" protocol=6 requested_mask="send receive" denied_mask="send receive"

View File

@@ -1,19 +0,0 @@
START
File: testcase_network_send_receive.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1469785325.122:21021
Operation: file_inherit
Mask: send receive
Denied Mask: send receive
Profile: /usr/bin/nginx-amplify-agent.py//null-/bin/dash
Command: sh
PID: 18239
Network family: inet
Socket type: stream
Protocol: tcp
Local addr: 192.168.10.3
Foreign addr: 54.153.70.241
Local port: 50758
Foreign port: 443
Epoch: 1469785325
Audit subid: 21021

Some files were not shown because too many files have changed in this diff Show More