Commit graph

1562 commits

Author SHA1 Message Date
Christian Boltz
e9b8139cee
Check variable errors when parsing simple_tests
... by calling active_profiles.get_all_merged_variables()

Also remove vars/vars_bad_add_assignment_1.sd from the
exception_not_raised list again - now it raises an exception as
expected.
2020-05-27 13:32:44 +02:00
Christian Boltz
7d86bf9fe2
severity: replace load_variables() with set_variables()
Add set_variables() to severity.py to set the variables for severity
rating. It typically gets the data from the get_all_merged_variables()
result.

This replaces the slightly broken load_variables() that parsed profile
files for variables. (For example, parsing "@{foo} = /bar" resulted
in a variable name "@{foo} " with trailing space.)

Also adjust aa.py and the severity tests to use set_variables() (with
get_all_merged_variables()) instead of load_variables().

This also re-adds the checks that were removed in the "Store variables
in active_profiles (ProfileList)" commit earlier, while still fixing
lp:1331856.

With this change, unload_variables() becomes useless (the variables get
overwritten in set_variables() anyway), drop it and its calls.

Note that load_variables() silently ignored non-existing files while the
get_all_merged_variables() call only works for existing files that are
known to active_profiles. Since the input of ask_the_questions() and
ask_exec() comes from log_dict (= audit.log or a profile to merge), add
a check if that profile actually exists in the set of active profiles.

Also adjust the severity tests to use set_variables().

Finally, drop the tests that check for handling non-existing include
files, redefining and adding to non-existing variables - all these
things get now handled in include_list_recursive() and
get_all_merged_variables() and their tests.

Fixes: https://bugs.launchpad.net/apparmor/+bug/1331856
2020-05-27 13:32:44 +02:00
Christian Boltz
7451c341a6
add get_all_merged_variables()
This function returns a dict with all variables and their values for a
given profile file. It also checks for redefined variables, and adding
to non-existing variables, and errors out in both cases. Note that it
does not check the include order and is therefore more forgiving than
apparmor_parser.

Also add some tests for get_all_merged_variables().

Note: the tests are based on reading "real" profiles, therefore we need
to initialize apparmor.aa and call some of its functions.

The alternative would be to construct ProfileList objects for some
profiles and includes manually, but doing that in a way that can replace
the tests with "real" profiles would be quite some work, and I'm not
bored enough for that ;-)
2020-05-27 13:32:44 +02:00
Christian Boltz
b13037e36d
Move reset_aa() from aa-mergeprof to aa.py
Some tests in the next commit also need it.
2020-05-27 13:32:44 +02:00
Christian Boltz
6155b356b3
VariableRuleset: add get_merged_variables()
This function returns a dict with variables, both definitions (=) and
value additions (+=).

Also add some tests.
2020-05-27 13:32:44 +02:00
Christian Boltz
9d2a10dec7
ProfileList: merge get_clean_first() into get_clean()
Now that ProfileList handles the whole preamble, there's no need to keep
two half functions.
2020-05-27 13:32:44 +02:00
Christian Boltz
fe3c0b0ef8
Get rid of the 'filelist' hasher()
Everything handled in 'filelist' gets handled in active_profiles now.

Note: the 'elif' branch in delete_all_duplicates() was probably never
hit because `if include.get(...)` always matched. The only possible
exception might be non-existing include files, but those cause a 'file
not found' error anyway.
2020-05-27 13:32:44 +02:00
Christian Boltz
430120879c
Drop now unused store_list_var() and its tests 2020-05-27 13:32:44 +02:00
Christian Boltz
abe0e2b246
ProfileStorage: Drop 'lvar' and write_list_vars()
Since the previous commit, variables never get stored in ProfileStorage,
and write_list_vars() is unused.
2020-05-27 13:32:44 +02:00
Christian Boltz
e5d38807df
Store variables in active_profiles (ProfileList)
... instead of filelist[file]['lvar'], and also write them from there.

Also fix detection of variable definitions inside a profile, which is
not allowed.

Note that ProfileList has a different write order than the old code -
first includes, then variable definitions. This makes more sense because
typical profiles first include tunables/global, and then define
additonal variables (that might use variables from tunables/global) or
extend variables defined in tunables/global.

This change also fixes some problems with the simple_test test profiles.
The "adding to non-existing variable" check currently doesn't exist,
which "fixes" lp:1331856.

OTOH this also means that such cases are not detected, therefore add
vars_bad_add_assignment_1.sd to the exception_not_raised list.

The check will be re-added in a later commit
in get_all_merged_variables().
2020-05-27 13:32:44 +02:00
Christian Boltz
2a58e0ada2
Extend ProfileList to handle (store/write) variables
... and also add some tests.
2020-05-27 13:32:43 +02:00
Christian Boltz
61db5595aa
VariableRuleset: Prevent re-defining variables
When adding a variable with a name that is already known to the
VariableRuleset, raise an exception.

Also add a test for this.
2020-05-27 13:32:43 +02:00
Christian Boltz
39eb1939ba
Split variables
... and enable tests related to this
2020-05-27 13:32:43 +02:00
Christian Boltz
1eb9791ed7
move separate_vars() from aa.py to VariableRule
... and also move its tests to test-variable.py
2020-05-27 13:32:43 +02:00
Christian Boltz
215ec38ae3
Add VariableRule and VariableRuleset
... and a set of tests for them.

Note that the tests include some TODOs, these will be handled in the
following commits.
2020-05-27 13:32:43 +02:00
Steve Beattie
c5a7bcd50e
utils/tests: test-include.py sometimes fails due to ordering
With the includes rule class landing, this particular test failed
in a test vm due to the sort ordering being different. It's not
clear that there should be an expectation of ordering returned from
get_full_paths(), so sort the result.

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/548
2020-05-27 01:03:56 -07:00
Christian Boltz
373e8e23b1
Fix strip_quotes() to handle empty strings
strip_quotes() assumed its parameter is at least one character long, and
errored out on an empty string.

It also converted a string consisting of a single quote to an empty
string because that single quote had a quote as first and last char.

This commit fixes these two bugs.

Also rewrite TestStripQuotes to use tests[], and add some test for an empty
string, a one-char path (just a slash) and a single quote.
2020-05-24 13:41:13 +02:00
Christian Boltz
7629d18e04
convert RE_PROFILE_VARIABLE to named match groups
(no behaviour change, just easier to use)
2020-05-22 00:51:18 +02:00
John Johansen
4b79a58c25 Merge Switch handling of include rules from filelist to IncludeRule
This patch series moves include rule handling away from the `filelist` hasher to using IncludeRule and IncludeRuleset. This means that only variable handling is left in `filelist`.

As usual, check the individual commits for details.

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/537
Acked-by: John Johansen <john.johansen@canonical.com>
2020-05-21 08:52:49 +00:00
Christian Boltz
1d2e710b26
parse_profile_data(): drop old code for parsing include rules
With this, all include rules (with and without 'if exists') get handled
by the code that handles IncludeRule.
2020-05-20 18:57:54 +02:00
Christian Boltz
cefc64522d
Drop now unused 'include' from ProfileStorage and ProfileList 2020-05-20 18:57:54 +02:00
Christian Boltz
60e8c1ff41
No longer write to filelist['include] or profile['include']
All code is migrated to IncludeRuleset / 'inc_ie'], so there's no point
in filling 'include' anymore.
2020-05-20 18:57:54 +02:00
Christian Boltz
5cfab9b81b
serialize_profile(): write preamble without checking filelist
filelist is getting emptier and emptier, and checking against a
nearly-empty filelist would result in not writing the preamble.
2020-05-20 18:57:54 +02:00
Christian Boltz
f0fa69a010
Convert compare_profiles() to use inc_ie / IncludeRule 2020-05-20 18:57:54 +02:00
Christian Boltz
706138ed67
Convert remove_duplicate_rules() to use inc_ie / IncludeRule
Besides switching to 'inc_ie', also drop the old code that removed
duplicate 'include' rules.
2020-05-20 18:57:54 +02:00
Christian Boltz
c8fa3dec0a
aa-cleanprof: don't check profile includes against preamble includes
remove_duplicate_rules() composed the 'includes' list from a) the
include rules in the profile and b) the file_includes (preamble
includes), and then checked the profile includes against this
combination of profile and preamble includes.

Checking profile includes against preamble includes is wrong, and the
only reason why this went unnoticed for years is that preamble include
files (like tunables) won't work inside a profile and therefore never
appear there.

In theory this might be a backport candidate, even if this shouldn't
cause a real-world bug.
2020-05-20 18:57:54 +02:00
Christian Boltz
6161641bcf
Convert match_includes() to use inc_ie / IncludeRule 2020-05-20 18:57:54 +02:00
Christian Boltz
cfdbcb20cc
add include_list_recursive()
This function returns a list of all includes in a profile and its
included files.

It's split off from is_known_rule() and get_file_perms() which shared
lots of common code to recursively get the include list. These functions
now use include_list_recursive().
2020-05-20 18:57:54 +02:00
Christian Boltz
6f1245ede9
Convert is_known_rule() to use inc_ie / IncludeRule
While on it, also add a missing check to avoid checking the same file
twice.
2020-05-20 18:57:54 +02:00
Christian Boltz
9f1b2f4014
collapse_log(): avoid accidently initializing aa[profile]
... or calling is_known_rule() on events for non-existing hats.

It's the usual hasher() "fun" again - accessing a non-existing element
will create its parent.

In theory this commit might be worth a backport. In practise, it doesn't cause
any visible problem.

However, starting with the next commit, it will cause lots of test errors.

Also add a missing is_known_rule() call for dbus rules, which might have
caused similar hasher() "fun".
2020-05-20 18:57:54 +02:00
Christian Boltz
fa67815698
Convert get_file_perms() to use inc_ie / IncludeRule 2020-05-20 18:54:53 +02:00
Christian Boltz
0cfef21713
IncludeRuleset: add get_all_full_paths()
This function returns a list of full paths of all includes.

Also add some tests.
2020-05-20 18:54:53 +02:00
Christian Boltz
057c916032
parse_profile_data(): call load_include() for IncludeRule
rule_obj.get_full_paths() handles directories and non-existing files
(depending on 'if exists'), so we can simply feed the resulting list
into load_include()
2020-05-20 18:54:53 +02:00
Christian Boltz
f3f597ff0b
IncludeRule: add get_full_paths()
This function returns a list of paths for an include rule. This can be
- a single path if the include file is a file and exists
- a single path if the include file doesn't exist, but doesn't have
  'if exists' (this will cause a 'file not found' error when used)
- a list of paths if the include is a directory
- an empty list if the rule has 'if exists' and the file doesn't exist

Also add some tests for get_full_paths()
2020-05-20 18:54:53 +02:00
Christian Boltz
d799195e0a
move is_skippable_file() from aa.py to common.py
IncludeRuleset needs to import it (next commit), which is impossible
when it lives in aa.py (would cause recursive import loop because aa.py
imports IncludeRuleset)
2020-05-20 18:54:53 +02:00
Christian Boltz
3f0f7154f7
Let aa-cleanprof remove duplicate preamble rules
Technically, this is done in the new function
delete_preamble_duplicates() in ProfileList.

Also add some tests to ensure this works as expected.
2020-05-20 18:54:53 +02:00
Christian Boltz
0cf15d54b6
aa-mergeprof: drop separate code asking for include rules
... because this is now done via IncludeRule, and keeping the separate
code would mean asking twice.

Note that the user interface changes slightly.

The old workflow was

    1 - #include <foo>
    2 - #include <bar>
    3 - #include <baz>
    [select 2 and (A)dd, then get the next question for the remainder]

    1 - #include <foo>
    2 - #include <baz>
    [(A)dd another one, or (I)gnore the remainder]

The new workflow will ask separately for each abstraction, and you can
(A)dd or (I)gnore it. This is probably easier to understand because it's
basically a yes/no question.
2020-05-20 18:52:16 +02:00
Christian Boltz
23af115fa5
store include rules (also) in 'inc_ie' (IncludeRueset)
... 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.
2020-05-20 18:50:20 +02:00
John Johansen
cc869c901e aa-notify: don't load policy includes
aa-notify does not need to load the policy includes for its current
features, so drop the unneeded overhead.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-05-19 02:47:21 -07:00
John Johansen
a7a727b1b0 Merge Make save_profiles() usable for aa-mergeprof
... and replace the aa-mergeprof code that asks about saving the profile with a call to save_profiles().

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/536
Acked-by: John Johansen <john.johansen@canonical.com>
2020-05-18 08:27:10 +00:00
John Johansen
69eeca80dd Merge aa-mergeprof: simplify internal parameter handover
Instead of stuffing two variables into a list and split them again, hand them over as plain separate variables.

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/535
Acked-by: John Johansen <john.johansen@canonical.com>
2020-05-18 08:22:26 +00:00
John Johansen
500acf7119 Merge valid_include(): move out unrelated check
alid_include() checks if the given include file exists or is whitelisted in cfg\['settings'\]\['custom_includes'\].

The check if that include file is already part of the profile is unrelated to that. Move it to match_includes() where it fits much better (and drop the now superfluous profile parameter from valid_include())

In theory is_known_rule() should prevent that case from ever happening, but let's restrict this commit to moving the code around and keep this check just to be sure.

While on it, add some documentation to both functions.

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/534
Acked-by: John Johansen <john.johansen@canonical.com>
2020-05-18 08:19:54 +00:00
John Johansen
c4d1cfa487 Merge split off ask_rule_questions() from ask_the_questions()
Also rename aa.py delete_duplicates() and make ruletypes a parameter.

See the commit messages for details.

This reduces usage of global variables.

The final change is that aa-genprof now asks about preamble rules that are \*Rule classes (currently `abi` and `include if exists`).

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/532
Acked-by: John Johansen <john.johansen@canonical.com>
2020-05-18 08:16:48 +00:00
Christian Boltz
34d4d9f5af
Make save_profiles() usable for aa-mergeprof
... and replace the aa-mergeprof code that asks about saving the profile
with a call to save_profiles().
2020-05-17 16:50:01 +02:00
Christian Boltz
ed0f2fe505
aa-mergeprof: simplify internal parameter handover
Instead of stuffing two variables into a list and split them again, hand
them over as plain separate variables.
2020-05-14 23:29:31 +02:00
Christian Boltz
7f7fc973f8
valid_include(): move out unrelated check
valid_include() checks if the given include file exists or is
whitelisted in cfg['settings']['custom_includes'].

The check if that include file is already part of the profile is
unrelated to that. Move it to match_includes() where it fits much
better (and drop the now superfluous profile parameter from
valid_include())

In theory is_known_rule() should prevent that case from ever happening,
but let's restrict this commit to moving the code around and keep this
check just to be sure.

While on it, add some documentation to both functions.
2020-05-14 22:48:20 +02:00
Christian Boltz
e0f9b7cb07 Merge branch 'cboltz-fail-verbose' into 'master'
read_profile(): don't fail silently

See merge request apparmor/apparmor!530

Acked-by: Steve Beattie <steve.beattie@canonical.com> for 2.11..master
2020-05-12 19:43:44 +00:00
Christian Boltz
85f2cd4ed4
Let aa-mergeprof ask about more preamble (*Rule) rules
For now, that means aa-mergeprof will ask for `abi` and `include if
exists` rules (currently hardcoded).

This needs storing of `active_profiles` in the Prof object - the
preamble `abi` and `include if exists` rules are stored there.

Since several functions expect an `include` dict, add an empty one to
ProfileList to prevent lots of errors and breakage. It can be removed
again when handling of `include` rules gets moved to IncludeRule.
2020-05-11 23:41:25 +02:00
Christian Boltz
3e0f4e1dba
rename aa.py delete_duplicates() and make ruletypes a parameter
Rename delete_duplicates() to delete_all_duplicates() to make the
function easier grep-able - the *rule classes have delete_duplicates()
which might be confused with the old name.

Also hand over 'ruletypes' as parameter to delete_all_duplicates()
instead of using the global variable.
2020-05-11 23:03:23 +02:00
Christian Boltz
ca693db3b0
split off ask_rule_questions() from ask_the_questions()
ask_the_questions() stays the "main" function, loops over all profiles,
and calls ask_rule_questions() for each profile.

ask_rule_questions() asks the questions for all events in a specific
profile or hat.

This reduces the usage of global variables in ask_rule_questions().
2020-05-11 23:01:06 +02:00