Commit graph

1020 commits

Author SHA1 Message Date
Christian Boltz
6a6f63a595 Map c (create) log events to w instead of a
Creating a file is in theory covered by the 'a' permission, however
discussion on IRC brought up that depending on the open flags it might
not be enough (real-world example: creating the apache pid file).

Therefore change the mapping to 'w' permissions. That might allow more
than needed in some cases, but makes sure the profile always works.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9, 2.10 and trunk
2015-11-19 21:23:02 +01:00
Christian Boltz
00cd706086 Also add python 3.5 to logprof.conf
Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9, 2.10 and trunk
2015-11-19 20:22:40 +01:00
Christian Boltz
801f3d596b Add debug info to profile_storage()
For debugging, it's helpful to know which part of the code initialized a
profile_storage and for which profile and hat this was done.

This patch adds an 'info' array with that information, adds the
corresponding parameters to profile_storage() and changes the callers to
deliver some useful content.


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.10
2015-11-18 22:01:19 +01:00
Christian Boltz
28d46e96ab Fix parsing/storing bare file rules
We replaced parse_audit_allow() with parse_modifiers() in r2833, but
overlooked that parse_modifiers() returns allow/deny as boolean. This
resulted in storing bare file rules in aa[profile][hat]['path'][False]
instead of aa[profile][hat]['path']['allow'] (or True instead of 'deny'
for 'deny file,' rules), with the user-visible result of loosing bare
file rules when saving the profile.

This patch converts the boolean value from parse_modifiers back to a
string.

Note: 2.9 is not affected because the old parse_audit_allow() returns
'allow' or 'deny' as string, not as boolean.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.10
2015-11-18 21:31:14 +01:00
Christian Boltz
98841b102a update PYMODULES in tools/Makefile
PYMODULES is used for generating *.pod, so it should include rule/*.PYMODULES


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.10
2015-11-18 21:28:53 +01:00
Christian Boltz
5e40adea06 utils/test/Makefile: add libapparmor to PYTHONPATH
The last utils/test/Makefile change switched to using the in-tree
libapparmor by default (unless USE_SYSTEM=1 is given). However, I missed
to add the swig/python parts of libapparmor to PYTHONPATH, so the
system-wide LibAppArmor/__init__.py was always used.

This patch adds the in-tree libapparmor python module to PYTHONPATH.

I'm sorry for the interesting[tm] way to find out that path, but
a) I don't know a better / less ugly way and
b) a similar monster already works in libapparmor/swig/python/test/ ;-)


Acked-by: John Johansen <john.johansen@canonical.com> for 2.9 and trunk
(that also implies 2.10 ;-)
2015-11-18 13:44:45 +01:00
Christian Boltz
b7c2ee19b7 Add python to the "no Px rule" list in logprof.conf
To make things more interesting, /usr/bin/python and /usr/bin/python[23]
are symlinks to /usr/bin/python[23].[0-9], so we have to explicitely
list several versions.


Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10 and trunk
2015-11-18 13:39:07 +01:00
Christian Boltz
37ab41bb13 Add __repr__() functions to BaseRule and BaseRuleset
This makes print()ing a class object much more helpful - instead of
    <apparmor.rule.network.NetworkRule object at 0x7f416b239e48>
we now get something like
    <NetworkRule> network inet stream,
(based on get_raw())

A NetworkRuleset will be printed as (also based on get_raw())

<NetworkRuleset>
  network inet stream,
  allow network inet stream, # comment
</NetworkRuleset>

Also add tests to test-network.py to ensure that __repr__() works as
expected.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-28 22:58:56 +01:00
Christian Boltz
cc9cf967b2 Add (abstract) get_clean() method to baserule
Also add a test to ensure it raises an AppArmorBug.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-28 22:52:07 +01:00
Christian Boltz
e700eb04d4 let logparser.py ignore file_inherit events without request_mask
That's not nice, but still better than a crash ;-)

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


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.9
2015-10-28 21:00:23 +01:00
Christian Boltz
274a98d8aa Let 'make check' work without logprof.conf
This patch checks if the cfg object is empty (happens if logprof.conf
doesn't exist). If so, it adds some empty sections to prevent various
failures in code that expects those sections to exist.

Another source of failures was using cfg['section']['setting']. The
patch changes various places to cfg['section'].get('setting') to prevent
those failures. (Those places all have a 'or ...' fallback.)

Finally, find_first_file() in config.py crashed if file_list was Null.
This is fixed by adding an "if file_list:" check before trying to
split() it.

With all those changes applied, 'make check' will work even if
/etc/apparmor/logprof.conf doesn't exist.


The patch also fixes the default value for inactive_profiledir
(I missed aa.py when I changed it to /usr/share/apparmor/extra-profiles/)


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


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:21:51 +02:00
Christian Boltz
bdd8884ab4 Fix handling of interpreters with parameters
If a script contains a hashbang like
    #! /usr/bin/perl -w
aa-autodep created a profile entry like
    "/usr/bin/perl -w" ix,
which is obviously incorrect.

This patch fixes this (by using only the first part of the hashbang line)
and also adds some tests for it.

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


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>

Bug: https://launchpad.net/bugs/1393979
2015-10-20 23:18:43 +02:00
Christian Boltz
d5e9a7ec70 merge script handling into get_interpreter_and_abstraction()
Both create_new_profile() and handle_children() check if the given exec
target is a script and add permissions for the interpreter and a
matching abstraction.

This patch merges that into the get_interpreter_and_abstraction()
function and changes create_new_profile() and handle_children() to use
this function.

A nice side effect is that handle_children() now knows more abstractions
(its original list was incomplete).
The behaviour of create_new_profile() doesn't change.

Also add tests for get_interpreter_and_abstraction() to make sure it
does what we expect.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>

Bug: https://launchpad.net/bugs/1505775
2015-10-20 23:16:41 +02:00
Christian Boltz
19d3b63db3 Add tests for create_new_profile()
These tests ensure that create_new_profile() sets the expected basic
permissions for scripts and non-script files.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:14:42 +02:00
Christian Boltz
3e5e0c11a0 Change utils/test/Makefile to use the in-tree libapparmor
Also add support for the USE_SYSTEM variable, which means:
- test against the in-tree libapparmor and python modules by default
- test against the system libapparmor and python modules if USE_SYSTEM
  is set

The old behaviour was a mix of both - it always used the in-tree python
modules and the system libapparmor.

For obvious reasons, you'll need to build libapparmor before running the
tests (unless you specify USE_SYSTEM=1 as parameter to make check).


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-10-20 23:04:23 +02:00
Christian Boltz
3fa19feb43 Parse all parser simple_tests with the utils code
Add a testcase that parses all tests in the parser/tst/simple_tests/
directory with parse_profile_data() to ensure that everything with valid
syntax is accepted, and that all tests marked as FAIL raise an
exception.

This already resulted in
- several patches to fix low-hanging fruits (including some bugs in the
  parser simple_tests itsself)
- a list of tests that don't behave as expected. Those files get their
  expected result reverted to make sure we notice any change in the
  tools behaviour, especially changing to the really expected resulted.
  This method also makes sure that the testcase doesn't report any of
  the known failures.
- a 5% improvement in test coverage - mostly caused by nearly completely
  covering parse_profile_data.
- addition of some missing testcased (as noticed by missing coverage),
  for example several "rule outside of a profile" testcases.

As indicated above, the tools don't work as expected on all test
profiles - most of the failures happen on expected-to-fail tests that
pass parse_profile_data() without raising an exception. There are also
some tests failing despite valid syntax, often with rarely used syntax
like if conditions and qualifier blocks.

Most of the failing (generated) tests are caused by features not
implemented in the tools yet:
- validating dbus rules (currently we just store them without any parsing)
- checks for conflicting x permissions
- permissions before path ("r /foo,")
- 'safe' and 'unsafe' keywords for *x rules
- 'Pux' and 'Cux' permissions (which actually mean PUx and CUx, and get
  rejected by the tools - ideally the generator script should create
  PUx and CUx tests instead)

skip_startswith excludes several generated tests from being run. I know
that skip_startswith also excludes tests that would not fail, but the
generated filenames (especially generated_x/exact-*) don't have a
pattern that I could easily use to exclude less tests - and I'm not too
keen to add a list with 1000 single filenames ;-)


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:00:56 +02:00
Christian Boltz
7c02bef563 Get rid of global variable 'logger'
The global variable 'logger' in aa.py is only used by aa-genprof.

This patch changes aa_genprof to use the (new) logger_path() function,
and moves the code for finding the logger path to that function.

Also make the error message more helpful if logger can't be found.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 22:03:58 +02:00
Christian Boltz
52c0494c2f make 'ldd' variable non-global
The 'ldd' variable in aa.py is only used by get_reqs(), therefore move
setting it (based on the configfile) into the function.

get_reqs() doesn't run too often (only called by create_new_profile(),
which means aa-genprof or when adding a Px or Cx rule to a non-existing
profile). This might even lead to a minor performance win - on average,
I'd guess not every aa-logprof run will lead to a completely new profile
or child profile. And, more important, we get rid of a global variable.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 20:37:17 +02:00
Christian Boltz
0dc861ef6d Fix missing profile init in create_new_profile()
create_new_profile() didn't init missing required_hats as
profile_storage(), which might lead to crashes when creating a profile
for an application listed in the required_hats config option (= in very
rare cases).

This patch adds the missing profile_storage() call.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-18 22:24:15 +02:00
Christian Boltz
cdc6f74f7e Store filename for includes and hats
This also means the duplicate detection can use the hat's filename instead
of the (possibly wrong) main profile's filename.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-18 22:12:53 +02:00
Christian Boltz
a1482f37d8 Add AARE tests for [chars] and [^chars] style globbing to test-aare.py.
With this addition, all globbing styles (as documented in apparmor.d(5))
are covered in the convert_regexp() tests.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-10-14 13:03:16 +02:00
Christian Boltz
75e3a212f1 load_include(): use include_dir_filelist()
load_include() used a custom os.listdir call instead of
include_dir_filelist() for directory includes, which means it also read
skippable files like *.rpmnew or README. (It seems nobody created a
README inside an included directory, otherwise we'd have seen a
bugreport ;-)

This patch changes load_include() to use include_dir_filelist(). This
function is used in some more places already and removes skippable files
from the file list.


Acked-by <timeout>
2015-10-11 20:34:02 +02:00
Christian Boltz
643ab7dde9 remove unused code from load_include()
load_include() has a "if not incdata:" block which would be entered if
parse_profile_data() returns None. However, parse_profile_data() always
returns a hasher with [incfile][incfile] = profile_storage(), so that
"if not incdata:" never matches.


Acked-by <timeout>
2015-10-11 20:32:22 +02:00
Christian Boltz
b6fc279676 load_include(): avoid loading directory includes multiple times
The "already loaded?" check in load_include() was done at the beginning
of the function, before entering the loop and before the individual
files of directory includes were added to the filelist. This resulted in
a (wrong) "Conflicting profiles" error for directory includes.

This patch moves the "alreay loaded?" check inside the loop, so that
it's executed for all files, including those of directory includes.


Acked-by <timeout>
2015-10-11 20:30:26 +02:00
Christian Boltz
06885e9377 Reset aa and original_aa in read_profiles()
TL;DR: aa-genprof crashes with a wrong 'Conflicting profiles' error.

aa-genprof uses autodep() to create a basic profile, which is then
stored in aa and original_aa. After that, read_profiles() is called,
which reads all profiles (including the new one) from disk, causing a
(wrong) 'Conflicting profiles' error in attach_profile_data() because
the autodep()-generated profile is already there.

Therefore this patch resets aa and original_aa in read_profiles() to
avoid that problem.


Acked-by <timeout>
2015-10-11 20:28:17 +02:00
Christian Boltz
ea9f9aeff2 move tests for convert_regexp() to (new) test-aare.py
The tests for convert_regexp() were hidden in common_test.py, where they
were never executed.

This patch moves them to the new file test-aare.py and also converts the
regex_tests.ini to a tests[] array to have the test data inside the test
file. (All tests from regex_tests.ini are in test-aare.py, and two tests
with prepended and appended path segments were added.)

Also add some tests that check the raw behaviour of convert_regexp() -
the tests "by example" are probably more useful and for sure more
readable ;-) but I want to have some examples of the converted regexes
available.


Acked-by <timeout>
2015-10-11 20:19:35 +02:00
Christian Boltz
ddc56bf3ac Accept more log formats in logparser.py
logparser.py does a regex check on log lines as performance improvement
so that it only hands over lines that look like AppArmor events to
LibAppArmor parsing. Those regexes were incomplete and didn't cover all
log formats LibAppArmor accepts, with the end result of "overlooking"
events.

This patch splits off common parts of the regex, adds more regexes for
several log types and finally merges everything into one regex.

test-libapparmor-test_multi.py now also checks all test_multi log lines
against the regex to ensure logparser.py doesn't silently ignore events.

test-logparser.py gets adjusted to the merged RE_LOG_ALL regex.

Finally, add a new test that was posted on IRC to the test_multi set.


As already threatened nearly a month ago,
   Acked by <timeout> for trunk and 2.9
2015-10-03 20:18:54 +02:00
Launchpad Translations on behalf of apparmor-dev
29cd792642 Launchpad automatic translations update. 2015-09-07 05:11:42 +00:00
Launchpad Translations on behalf of apparmor-dev
c00c4c9bf3 Launchpad automatic translations update. 2015-09-06 05:10:41 +00:00
Launchpad Translations on behalf of apparmor-dev
7415d319f3 Launchpad automatic translations update. 2015-09-05 05:10:42 +00:00
Christian Boltz
4794c7c488 Test libapparmor test_multi tests against logparser.py
This testcase will parse all libraries/libapparmor/testsuite/test_multi
tests and compare the result with the *.out files.

It also include a "ToDo list" of keywords that are not yet supported in
the python code - those are typically related to rule types not
supported in the tools yet (dbus, signal etc.).

An interesting special case are exec events with network details:
    testcase01.in, testcase12.in, testcase13.in
which might be hand-made, invalid logs, but nobody remembers ;-)


Acked-by <timeout>
2015-09-05 01:23:43 +02:00
Launchpad Translations on behalf of apparmor-dev
9bf465993e Launchpad automatic translations update. 2015-09-04 05:10:54 +00:00
Steve Beattie
486e42b221 utils/aa-logprof.pod: fix typo in manpage
Bug: https://bugs.launchpad.net/bugs/1485855
2015-08-25 14:53:55 -07:00
Christian Boltz
68854c5faa Add network mpls and ib to rule/network.py and the apparmor.d manpage
Those two showed up in apparmor.vim when building on latest openSUSE
tumbleweed.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-25 13:27:18 +02:00
Christian Boltz
6ce88bb695 map socket_create events to 'net' events
See libapparmor test_multi testcase24.* and testcase33.* for example logs.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-08-10 21:30:22 +02:00
Launchpad Translations on behalf of apparmor-dev
1c63019006 Launchpad automatic translations update. 2015-08-07 05:13:48 +00:00
Christian Boltz
c9e16d874e Check for duplicate profiles
Having two profiles for the same binary is "technically allowed", but it
leads to interesting[tm] behaviour because one of them "wins" depending
on the load order. To make things even more interesting, the kernel load
order can be different from the tools load order, leading to even more
fun.

Short version: you do _not_ want that situation ;-)

This patch adds a duplicate check to attach_profile_data() so that it
errors out if it finds duplicate profiles or hats, and lists the profile
files that contain them.



Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for both trunk and 2.9.
2015-08-03 01:17:53 +02:00
Christian Boltz
426edf3233 Fix name_to_prof_filename() error behaviour
In some cases, the return value of name_to_prof_filename() is undefined.
This happens when deleting the to-be-confined binary while running
aa-genprof and leads to a not-too-helpful
    File "/usr/lib/python3/dist-packages/apparmor/aa.py", line 265, in enforce
	      prof_filename, name = name_to_prof_filename(path)
	TypeError: 'NoneType' object is not iterable

(reported by maslen on IRC)

This patch makes sure name_to_prof_filename() always returns None, None
(instead of undefined aka just None) so that at least the caller can
successfully split it into two None values.

For the exotic aa-genprof usecase given above, this at least improves
the error message to
    Can't find $binary_name
(raised by enforce() via fatal_error())


The patch also changes fatal_error() to display the traceback first, and
the human-readable message at the end, which makes it more likely that
the user actually notices the human-readable message.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for both trunk and 2.9.
2015-08-03 01:14:38 +02:00
Christian Boltz
fd129e1802 Change RE_PROFILE_START to accept variables
Profile name and attachment can contain variables, so the
RE_PROFILE_START regex should accept it.
(Note: the variable content isn't checked.)

Also add some tests with variables.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-03 00:16:23 +02:00
Christian Boltz
61735c60b0 Split logparser.py add_event_to_tree() into multiple functions
add_event_to_tree() is a hard-to-test function because it hands over its
result to add_to_tree().

This patch converts add_event_to_tree() to a simple wrapper function and
moves the main code into parse_event_for_tree() and map_log_type(). These
two new functions return their results and are therefore easier to test.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-02 23:58:16 +02:00
Christian Boltz
67da39ff10 drop shebang from apparmor/rule/*.py
The '#!/usr/bin/env python' line in apparmor/rule/*.py is superfluous
and causes "non-executable script" rpmlint warnings on openSUSE.


Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-07-17 21:57:26 +02:00
Christian Boltz
7cf219a4b3 Initialize child profile in handle_children()
TL;DR: the answer is "yes" ;-)
(see the patch for the question...)

Long version:
When creating a new child profile with aa-logprof or aa-genprof, the
child profile wasn't properly initialized in handle_children(), which
lead to a crash in delete_duplicates() later because capability etc.
was not set to a CapabilityRuleset etc. class and therefore
profile['capability'] didn't have a .delete_duplicates() method.

Funnily there was already a comment "do we need to init the profile here?"

This patch replaces the question in the comment with the answer.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 20:05:40 +02:00
Christian Boltz
b30e85ade2 Add --no-reload option to aa-autodep
Besides adding this feature, this also fixes a crash in tools.py __init__():
    AttributeError: 'Namespace' object has no attribute 'do_reload'


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 01:45:42 +02:00
Christian Boltz
5d5da52a03 fix create_new_profile() to avoid aa-genprof crash
create_new_profile() created a wrong structure for local_profile, which
resulted in an aa-genprof crash directly at startup (in the autodep
phase).

This patch fixes it to use the correct structure.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 01:25:06 +02:00
Christian Boltz
45cb3d7ec3 Add cux and CUx to PROFILE_MODE_RE
cux and CUx are valid exec permissions, so they should be accepted
by validate_profile_mode() ;-)


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-07-11 22:57:36 +02:00
Christian Boltz
e59cf31a7b Update RlimitRule to match the parser changes
- allow only a specific set of time units
- optionally allow whitespace between rlimit value and unit
- move check for invalid time units to time_to_int()

Also update the tests:
- add several tests with whitespace between value and unit
- change a test that used the (now invalid) "1m" to "1min"
- change the time_to_int() tests to use 'us' as default unit, and add
  a test with 'seconds' as default unit


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-11 14:05:32 +02:00
Christian Boltz
0792e73ee9 Avoid raising an exception for hats in includes in aa-logprof
aa-logprof raises an exception if
- an include file contains a hat
- that file is included in a profile and
- aa-logprof hits an audit log entry for this profile

Reproducer ("works" on 2.9 and trunk):
python3 aa-logprof -f <(echo 'Jun 19 11:50:36 piorun kernel: [4474496.458789] audit: type=1400 audit(1434707436.696:153): apparmor="DENIED" operation="open" profile="/usr/sbin/apache2" name="/etc/gai.conf" pid=2910 comm="apache2" requested_mask="r" denied_mask="r" fsuid=0 ouid=0') -d ../profiles/apparmor.d/

This happens because profiles/apparmor.d/apache2.d/phpsysinfo was
already read when pre-loading the include files.

This patch changes aa.py parse_profile_data() to only raise the
exception if it is not handling includes currently.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-07-09 15:12:43 +02:00
Christian Boltz
877fd99c7d Add tests for RE_PROFILE_START and parse_profile_start_line() with unusual whitespace around flags
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:50:01 +02:00
Christian Boltz
cc4d04a7cc Allow variables in change_profile rules
Now that the parser allows variables in change_profile rules,
the tools should also do that ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:49:10 +02:00
Christian Boltz
0d842eae34 Handle #include <directory> in is_known_rule()
is_known_rule() ignored directory includes, which resulted in asking for
and adding superfluous rules that are already covered by a file in the
included directory.

This patch looks bigger than it is because it moves quite some lines
into the "else:" branch. Everything inside the "else:" just got an
additional whitespace level.

References: https://bugs.launchpad.net/apparmor/+bug/1471425
(however, trunk didn't crash, it "just" ignored directory includes)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:46:01 +02:00