... and write them (only) from 'inc_ie' (IncludeRuleset), which can
handle both "include" and "include if exists" rules.
This duplicates storage of include rules because 'include' is still used
and needed at various places that work on/with the include rules.
With this, we get removal of duplicate include lines insinde a profile
in aa-cleanprof "for free" - extend cleanprof_test.in to confirm this.
... but not for abi rules, which (according to the simple_tests
profiles) do not share these bugs)
For unquoted paths, make sure that the path doesn't include whitespace.
... because after the previous three commits, nothing reads/needs this
anymore
Note: file_name in ask_exec() was only used in the (dropped) filelist
usage.
Instead of checking filelist[file]['profiles'] for duplicate hats, check
profile_data[profile][hat].
With this, the duplicate hat check is done in the same way as the check
for duplicate profiles and child profiles.
Also add tests for duplicate child profiles and duplicate hats.
The profile repo is dead since years and most likely won't come back, so
there's no point in keeping and maintaining the code for uploading and
downloading profiles.
- add_inc_ie() stores include and include if exists rules
- get_clean() and get_raw() return the profile preamble (currently only
the include rules)
Also add tests for the new functions.
This is similar to get_clean(), but keeps the original rule order
instead of sorting them.
This is useful for include rules in the preamble, where the order might
be relevant - for example if the first include defines a variable that
is then used or extended in the second include file.
Merge branch 'cboltz-profile-list-rename-add' into 'master'
See merge request apparmor/apparmor!502
Acked-by: Steve Beattie <steve.beattie@canonical.com>
For now, only 'include if exists' rules will be handled by IncludeRule.
Using it also for 'include' rules needs some more code changes so that
included files still get checked etc.
Also remove some testcases from test-parser-simple-tests.py unknown_line
which no longer fail.
These classes are meant to handle 'include' and 'include if exists'
rules.
Due to restrictions in re_match_include_parse(), some cases in
is_covered_localvars() and is_equal_localvars() can't be reached in the
unittests.
Also, IncludeRule isn't used in aa-logprof (yet?), which means
logprof_header_localvars() result format isn't decided yet, and
therefore not tested.
This means test coverage for the new classes isn't 100% this time ;-)
This function was introduced as a temporary (ahem...) solution in
95404bb2f3 but was never really correct.
It checked against other_value.regex (as a string!) and, while this was
somewhat generous in the results, could have unintended side effects.
Better error out on the safe side and add/keep a few superfluous rules
than having a wrong match in is_covered() and miss to add/keep a rule
that would be needed.
The perfect solution would be to really compare one AARE against the
other as the parser does. I'm not too keen to implement this in python,
and will wait until someone provides this function (which the parser
already has) via libapparmor ;-)
v2:
- parse partial log line broken at \n
- add testcase_dbus_10.* for partial log line
- remove quotes from testcasw_dbus_09.profile
The following log format has been seen in the wild, and currently results
in a RECORD_INVALID
[4835959.046111] audit: type=1107 audit(1561053426.749:186): pid=640 uid=103 auid=4294967295 ses=4294967295 msg='apparmor="ALLOWED" operation="dbus_method_call" bus="system" path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager" member="LookupDynamicUserByName" mask="send" name="org.freedesktop.systemd1" pid=20596 label="/usr/sbin/sshd" peer_pid=1 peer_label="unconfined"
exe="/usr/bin/dbus-daemon" sauid=103 hostname=? addr=? terminal=?'
Test parsing the above message with and without the \n embedded between
peer_label= and exec=
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
When dc010bc034 was
backported to the apparmor-2.13 branch (in commit
75236d62e2), it did not take into
account cb8c3377ba, which creates the
common/list_af_names.sh script as used in the test case, was not also
backported to the apparmor-2.13 branch.
Change the test case to get the list of network AF names via the same
make invocation taken by the utils/vim/create-apparmor.vim.py script
before the common/list_af_names.sh existed.
PR: https://gitlab.com/apparmor/apparmor/merge_requests/391
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
If final_name still includes null-*, that's most likely caused by nested
execs which aren't supported by the tools yet. Ignoring them is better
than creating a useless null-* hat.
Note: The tools always had this restriction, so this is not a regression ;-)
Also note that test-libapparmor-test_multi expects that null-* hats get
created (which makes sense because the one-line log sniplets don't have
any exec indication), therefore add an optional parameter to keep this
behaviour for the tests.
Now that all log events arrive in hashlog, having a separate 'prelog' no
longer makes sense. Changing collapse_log() to accept 'hashlog' directly
removes that level of indirection.
It's only used by two functions:
- handle_hashlog() - writes to prelog, and now returns it
- collapse_log() - reads prelog, and now gets it as parameter
'final_name' by default is the profile name, but ask_exec() will change
it for the target profile (which is a null-* profile at this stage)
based on exec mode choice. ask_addhat() will also change it based on the
chosen hat.
Choosing "deny" or "unconfined" will result in an empty final_name and
ignoring these log events.
All other choices set final_name to the full profile name ("foo" for Px,
"foo//bar" for Cx, current profile for ix).
Also fix the order of handling log events - since ask_exec() changes the
hashlog final_name, it has to run first so that ask_addhat() (which
"only" adjusts the hat name in final_name) and handle_hashlog() can work
with the updated profile name.
Finally, update test-libapparmor-test_multi.py to ignore final_name when
checking if hashlog is empty, and fix the call order of ask_exec() etc.
... and self.pid which is also unused.
This simple change also means to adjust all the code that uses ReadLog.
We get rid of log_pid in aa.py, and have to change lots of test-*
The only remaining job of handle_children() was to handle exec events.
(And recursively calling itsself if it hits nested log events, but
logparser.py never created such a log structure.)
Therefore:
- drop the dead code handling nested log (type != str)
- rename the remaining function to ask_exec()
- drop checks for typ = 'exec' (now done as part of the for loop
- drop the "else" branch for unknown event types
- change 'return' to 'continue' because ask_exec handles all exec events
in a loop instead of being called multiple times
- oh, and of course switch over to using hashlog
Finally, change do_logprof_pass() and the tests to call ask_exec()
instead of handle_children().
While on it, update a comment in test-translations.py which held the
last reference to handle_children().
Adjust logparser.py to store change_hat events in hashlog.
In aa.py,
- split off ask_addhat() from handle_children()
- change ask_addhat() to use hashlog
- call ask_addhat() from do_logprof_pass()
Also call ask_addhat() in test-libapparmor-test_multi.py to keep it in
sync with do_logprof_pass().
In logparser parse_event_for_tree() path event handling, drop mapping
permissions for request_mask because request_mask never gets used.
Also drop the validate_log_mode() call because the function has its own,
more strict check since the last commit.
In aamode.py, drop the now unused validate_log_mode() and
hide_log_mode() functions and the LOG_MODE_RE regex.
Finally, drop the validate_log_mode() tests from test-aamode.py
In logparser.py parse_event_for_tree, convert path handling to hashlog.
While on it, include 'owner' as part of hashlog so that aa.py doesn't
need to guess.
Also switch to a simple for loop instead of using log_str_to_mode() from
aamode.py to convert denied_mask to hasher keys (which would have been
needed to allow merging of several log events for the same path anyway).
Note that the check for 'mrawlk' (intentionally without 'x') is more
strict than the validate_log_mode(), but it should still cover all file
permissions. (validate_log_mode() also allows things like 'Px', which
we'll never hit in a logfile.)
In aa.py collapse_log() update the handling of path events to match the
additional [owner] key in hashlog/prelog. This makes the owner detection
in collapse_log() superfluous.
In aa.py handle_children(), remove 'path' handling from the 'path' or
'exec' section, and add an 'if True:' to avoid lots of whitespace
changes.
In aamode.py, drop the now unused split_mode() function, and
AA_OTHER_REMOVE() that was only used by split_mode().
Finally, remove sample log events with null-* hats from the list of
known failures in test-libapparmor-test_multi.py (we no longer filter
out null-* hats), and fix whitespace in two expected profiles.
logparser.py puts each log event on a big "stack" in self.pid. Later,
handle_children() in aa.py then converts that (named 'log' in aa.py) to
the prelog hasher.
This commit changes logparser.py to create the prelog structure itsself
(named hashlog), which
- removes one level of indirection
- probably saves some memory because the hashlog automatically
de-duplicates events
This commit does this for capability, network and signal events, and
adds the infrastructure needed for all event/rule types.
In aa.py, the new function handle_hashlog() copies the hashlog content
to prelog. OTOH, the now superfluous code handling capability, network
and signal events gets removed from handle_children().
Long-term, hashlog will replace log in aa.py. When this is done,
handle_hashlog() will be replaced by a simple prelog = hashlog.
logparser.py gets a new function init_hashlog() to initialize hashlog
for each profile. It also gets changed to store capability, network and
signal events into hashlog instead of storing them in self.pid.
hashlog uses the full profile name as key, which is the first baby step
to support nested child profiles. (for now, handle_hashlog() still
splits the profile name into profile and hat.)
Known issue: The new implementation doesn't handle exec yet, which means
that events get lost at the exec boundary (= in cases aa-logprof asks
which execute mode to use). This will be fixed in a later commit.