Commit graph

780 commits

Author SHA1 Message Date
Christian Boltz
1f9474e653 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:58:24 +02:00
Christian Boltz
a108416ae0 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.


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:50:35 +02:00
Christian Boltz
8374749f5d Add a missing check in rule class is_covered()
"capability foo".is_covered("deny capability foo") should return False
even if check_allow_deny is False.

Also add some tests with check_allow_deny=False.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-14 00:52:55 +02:00
Christian Boltz
51ce5f2758 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:20:31 +02:00
Christian Boltz
6ed926332f 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:15:18 +02:00
Christian Boltz
301449a96e 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:08 +02:00
Christian Boltz
7189347ace 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:27:50 +02:00
Christian Boltz
a313b674f7 simplify serialize_parse_profile_start()
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-03 17:32:06 +02:00
Christian Boltz
0dc795d181 fix is_skippable_dir() and add tests
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-03 17:29:44 +02:00
Christian Boltz
20cfa21695 replace RE_PROFILE_START
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-03 17:28:03 +02:00
Christian Boltz
a0a044f346 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-03 17:26:26 +02:00
Christian Boltz
bb3c972de9 [patch] make set_profile_flags more strict
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 ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-03 17:25:18 +02:00
Christian Boltz
38b1e3d30f rewrite set_profile_flags() to use write_header()
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

Note: test_set_flags_10, test_set_flags_12 and test_set_flags_nochange_09
will fail with this patch applied. The next patch will fix that.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-03 17:20:14 +02:00
Christian Boltz
67ae278436 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:39:00 +02:00
Christian Boltz
7ad490e266 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-02 13:33:14 +02:00
Christian Boltz
df6fce1a91 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-02 13:31:27 +02:00
Christian Boltz
eb0553f11f [patch] rewrite parse_profile_start()
Rewrite parse_profile_start() in aa.py to a more readable version.
The behaviour remains unchanged (and is covered by tests).

The patch also updates the comment about the internal struct of
aa[profile][hat] - initial_comment was missing.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-02 13:30:01 +02:00
Christian Boltz
87c5679b91 add tests for RE_PROFILE_START_2 and parse_profile_start_line()
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-02 11:42:28 +02:00
Christian Boltz
6651d4a3ee test new parameters of write_header()
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-02 01:31:22 +02:00
Christian Boltz
b81400185d [patch] extend and partially rewrite write_header()
- 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-02 01:30:01 +02:00
Christian Boltz
e0a8ed7673 add attachment to parse_profile_start() return values
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-01 23:58:29 +02:00
Christian Boltz
0478f6bb11 Add support for attachments to write_header()
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-01 23:50:04 +02:00
Christian Boltz
80e33751c9 add tests for write_header()
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-01 23:48:50 +02:00
Christian Boltz
35382be8d0 add tests for set_profile_flags() (and some fun)
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-01 23:43:29 +02:00
Christian Boltz
b8f0a5cbb2 convert serialize_parse_profile_start() to use parse_profile_start_line()
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.



Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-01 10:58:27 +02:00
Christian Boltz
90efcd7a92 add tests for serialize_parse_profile_start() to test-aa.py
to document the function's behaviour.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-01 10:57:24 +02:00
Christian Boltz
3ef67876cb add forgotten test-example.py
The commit message for r2976 says:

    [...]
    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>

but I forgot to add test-example.py to bzr, which I hereby do.
2015-04-01 10:55:33 +02:00
Christian Boltz
4ad6f486f8 update test-aa.py to match parse_profile_start() and get_profile_flags() changes
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-03-31 22:45:45 +02:00
Christian Boltz
da35c243d9 add and use parse_profile_start_line()
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.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-31 22:44:18 +02:00
Christian Boltz
d0d101779a Convert test-regex_matches.py to the new tests[] loop.
The test behaviour is the same with and without this patch - 166 tests
run, all successful.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-31 22:31:36 +02:00
Christian Boltz
7e8191400f add better loop support to common_test.py
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-03-31 22:29:06 +02:00
Jamie Strandboge
4951c29c11 incorporate feedback from Seth Arnold:
- fix typo in comment
- error() instead of warn() if can't find specified group
2015-03-28 07:16:22 -05:00
Jamie Strandboge
9e33b760cd implement tests for --include-templates-dir and --include-policy-groups-dir 2015-03-27 16:34:32 -05:00
Jamie Strandboge
0438db70b5 utils/aa-easyprof.pod: corrections for --show-templates and
--show-policy-groups
2015-03-27 16:33:35 -05:00
Jamie Strandboge
2652642c27 update copyright year for modified files 2015-03-26 17:14:52 -05:00
Jamie Strandboge
f47c54984d add --include-templates-dir and --include-policy-groups-dir options to
easyprof to support framework policy on snappy
2015-03-26 16:59:05 -05:00
Launchpad Translations on behalf of apparmor-dev
556babd125 Launchpad automatic translations update. 2015-03-18 05:08:23 +00:00
Launchpad Translations on behalf of apparmor-dev
17397a655b Launchpad automatic translations update. 2015-03-11 05:08:58 +00:00
Christian Boltz
0636dea5c6 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:08:17 +01:00
Christian Boltz
d1900f42c7 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:30:55 +01:00
Christian Boltz
05f78ee733 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>


---------- trunk only, unclear for 2.9 --------------
2015-03-07 13:26:10 +01:00
Christian Boltz
411436e32b 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:25:24 +01:00
Christian Boltz
0c216daa9f 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:24:19 +01:00
Alain BENEDETTI
f29e4a3965 utils/aa-status: don't crash when non-ASCII mountpoints are in use
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:17:05 -08:00
Christian Boltz
2867f0d656 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:17:05 +01:00
Christian Boltz
7262b71d47 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:15:00 +01:00
Christian Boltz
55a2809a5a 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>
2015-03-02 21:12:12 +01:00
Christian Boltz
c469b92afb 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>
2015-03-02 19:36:20 +01:00
Christian Boltz
0166960844 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>



Also update test-capability.py - it contains a test that needs
    'error_code': 0,
added to avoid a failure.

Patch by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-02-28 14:09:45 +01:00
Christian Boltz
4939f7ce14 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:24:11 +01:00