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