2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 22:35:35 +00:00

Compare commits

...

108 Commits

Author SHA1 Message Date
John Johansen
027faf20dd Prepare for AppArmor 2.13.8 release
- update version file
- update library version

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-05-24 00:58:15 -07:00
John Johansen
b41d34e638 Merge extend test profiles for mount
- in bad_?.sd, explain why the profile is bad (conflicting options)
- add a good profile with two space-separated options

This is a follow-up for https://gitlab.com/apparmor/apparmor/-/merge_requests/1029

If we backport !1029, we should also backport these test changes.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1035
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit d700f87d3e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-05-23 14:43:21 -07:00
Jon Tourville
a0df142852 Merge Merge Issue 312: added missing kernel mount options
This patch adds the following mount options: 'nostrictatime', 'lazytime', and 'nolazytime'.

The MS_STRICTATIME mount flag already existed, and 'nostrictatime' was listed along with 'strictatime' in the comments of parser/mount.cc, so this patch adds a mapping for 'nostrictatime' to clear MS_STRICTATIME.

Additionally, the Linux kernel includes the 'lazytime' option with MS_LAZYTIME mapping to (1<<25), so this patch adds MS_LAZYTIME to parser/mount.h and the corresponding mappings in parser/mount.cc for 'lazytime' and 'nolazytime'.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1005
Approved-by: John Johansen [john@jjmx.net](mailto:john@jjmx.net)
Merged-by: John Johansen [john@jjmx.net](mailto:john@jjmx.net)
(cherry picked from commit c37be61d17)
Signed-off-by: Jon Tourville [jon.tourville@canonical.com](mailto:jon.tourville@canonical.com)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1034
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 16:40:32 +00:00
John Johansen
70b764590b Merge Issue 312: added missing kernel mount options
This patch adds the following mount options: 'nostrictatime',
'lazytime', and 'nolazytime'.

The MS_STRICTATIME mount flag already existed, and 'nostrictatime' was
listed along with 'strictatime' in the comments of parser/mount.cc, so
this patch adds a mapping for 'nostrictatime' to clear MS_STRICTATIME.

Additionally, the Linux kernel includes the 'lazytime' option with
MS_LAZYTIME mapping to (1<<25), so this patch adds MS_LAZYTIME to
parser/mount.h and the corresponding mappings in parser/mount.cc for
'lazytime' and 'nolazytime'.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1005
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit c37be61d17)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:26:40 -05:00
John Johansen
6e7a4bac5e regression tests: make mount regression tests report skipped options
Don't silently skip options so that we know what is being tested.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit f3d5531516)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:25:51 -05:00
John Johansen
e6cfce0309 parse tests: add parse tests for missing mount options
add simple parsing tests for nostrictatime, lazytime, nolazytime

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit cfb77309d6)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:25:42 -05:00
John Johansen
534185b4ca docs apparmor.d: add missing mount options to man page
Add the missing options nostrictatime, lazytime, and nolazytime to the
apparmor.d manpage.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit b51602233d)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:24:49 -05:00
John Johansen
561a60a3c9 parser: fix conflicting mnt flag values message to have a space
The conflicting flags value message was hard to read
  conflicting flag value = lazytimenolazytime

change it to
  conflicting flag values = lazytime, nolazytime

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 89bc617d0d)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:24:44 -05:00
Oliver Calder
a1fa0ec51d parser: added nosymfollow mount option
Adds the corresponding `MS_NOSYMFOLLOW` flag to parser/mount.h as well,
defined as (1 << 8) just as in the util-linux and the kernel.

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 231c469d86)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:24:36 -05:00
Oliver Calder
f22e41f8c1 Added MS_LAZYTIME to MS_ALL_FLAGS
Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 257b3cfbf6)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:24:29 -05:00
Oliver Calder
83b7bf3431 Issue 312: added missing kernel mount options
This patch adds the following mount options: 'nostrictatime',
'lazytime', and 'nolazytime'.

The MS_STRICTATIME mount flag already existed, and 'nostrictatime' was
listed along with 'strictatime' in the comments of parser/mount.cc, so
this patch adds a mapping for 'nostrictatime' to clear MS_STRICTATIME.

Additionally, the Linux kernel includes the 'lazytime' option with
MS_LAZYTIME mapping to (1<<25), so this patch adds MS_LAZYTIME to
parser/mount.h and the corresponding mappings in parser/mount.cc for
'lazytime' and 'nolazytime'.

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit bc64b824fa)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 11:24:25 -05:00
Jon Tourville
dd0d6d3802 Merge Merge expand mount tests
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1006
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit e6e5e7981f)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1033
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 12:53:37 +00:00
Jon Tourville
b81ad9bb0f Check for newer mount options in regression test
The mount options MS_LAZYTIME and MS_NOSYMFOLLOW were added in
kernels 4.0 and 5.10, respectively. Update the mount test script
and helper to skip testing those options if they are not available.

Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
(cherry picked from commit 9a760def8d)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 06:41:45 -05:00
John Johansen
48673696a6 Merge expand mount tests
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1006
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit e6e5e7981f)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-18 06:41:45 -05:00
Jon Tourville
8409d7cd61 Merge Merge Fix mount rules encoding
This is a partial fix for CVE-2016-1585, it address the frontend rule encoding problems particularly
- Permissions being given that shouldn't happen
- Multiple option conditionals in a single rule resulting in wider permission instead of multiple rules
- optional flags not being handled correctly
- multiple backend rules being created out of one frontend rule when they shouldn't be

it does not address the backend issue of short cut permissions not being correctly updated when deny rules carve out permissions on an allow rule that has a short cut permission in the encoding.

Thanks to the additional work by Alexander Mikhalitsyn for beating this MR into shape so we can land it

Alexander Changelog:
- rebased to an actual tree
- addressed review comments from @wbumiller and @setharnold
- fixed compiler warnings about class_mount_hdr is uninitialized
- infinite loop fix
- MS_MAKE_CMDS bitmask value fixed
- fixed condition in `gen_flag_rules` to cover cases like `mount options in (bind) /d -> /4,` when flags are empty and only opt_flags are present
- marked some tests as a FAIL case behavior was changed after `parser: add conflicting flags check for options= conditionals` commit

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/333
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit c1a1a3a923)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1029
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-17 23:09:44 +00:00
Christian Boltz
536959d714 Merge nscd: add permission to allow supporting unscd
`unscd` is a drop-in replacement for `nscd` that uses the same binary location (`/usr/sbin/nscd`) and config file (`/etc/nscd.conf`). The `usr.sbin.nscd` profile only needs one additional permission to support it.

```
May 9 18:07:42 darkstar kernel: [ 2706.138823] audit: type=1400
audit(1683670062.580:839): apparmor="DENIED" operation="sendmsg"
profile="nscd" name="/run/systemd/notify" pid=4343 comm="nscd"
requested_mask="w" denied_mask="w" fsuid=125 ouid=0
```

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1031
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit dec3815f07)

bd0d401b nscd: add permission to allow supporting unscd
2023-05-10 10:55:00 +00:00
John Johansen
1d17d5399c Merge Fix mount rules encoding
This is a partial fix for CVE-2016-1585, it address the frontend rule encoding problems particularly
- Permissions being given that shouldn't happen
- Multiple option conditionals in a single rule resulting in wider permission instead of multiple rules
- optional flags not being handled correctly
- multiple backend rules being created out of one frontend rule when they shouldn't be

it does not address the backend issue of short cut permissions not being correctly updated when deny rules carve out permissions on an allow rule that has a short cut permission in the encoding.

Thanks to the additional work by Alexander Mikhalitsyn for beating this MR into shape so we can land it

Alexander Changelog:
- rebased to an actual tree
- addressed review comments from @wbumiller and @setharnold
- fixed compiler warnings about class_mount_hdr is uninitialized
- infinite loop fix
- MS_MAKE_CMDS bitmask value fixed
- fixed condition in `gen_flag_rules` to cover cases like `mount options in (bind) /d -> /4,` when flags are empty and only opt_flags are present
- marked some tests as a FAIL case behavior was changed after `parser: add conflicting flags check for options= conditionals` commit

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/333
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit c1a1a3a923)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:12:40 +00:00
Alexander Mikhalitsyn
5642b9b36e parser: simple_tests: mount: mark ok_[16-19] tests as bad
These tests contains incompatible mount options and broken
after ("parser: add conflicting flags check for options= conditionals")

Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 4b7e868e54)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:08:14 +00:00
John Johansen
ea401061c4 parser: fixup gen_flag_rules
gen_flag_rules has a boolean vs bit and case where parenthesis are
helpful to express the intended order of operations.

It also doesn't handle the case where there are no matches. Fix this
by causing that case to fail.

also improve the debug of option extraction.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit f09676f5f9)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:08:07 +00:00
John Johansen
bd315a7039 parser: support multiple mount conditionals in a single rule
Now that flag processing for mount rules with single option
conditionals are fixed e-enable multiple mount conditionals on a
single mount rule. The mount conditionals are equivalent to specifying
multiple rules.

      mount options=(a,b,c) options=(c,d),
    is the same as
      mount options=(a,b,c),
      mount options=(c,d),

    and
      mount options in (a,b,c) options in (c,d),
      is the same as
        mount options in (a,b,c),
        mount options in (c,d),

    when multiple options= and options in are combined in a single rule
    it is the same as the cross product of the options.

    where
      mount options=(a,b,c) options in (d,e),
    is a single rule.

      mount options=(a,b,c) options=(d,e) options in (f),
    is equivalent to
      mount options=(a,b,c) options in (f),
      mount options=(d,e) options in (f),

    and while it is not recommended that multiple options= and options in
    conditions be used in a single rule.
      mount options=(a,b,c) options=(d,e) options in (f) options in (g),
    is equivalent to
      mount options=(a,b,c) options in (f),
      mount options=(a,b,c) options in (g),
      mount options=(d,e) options in (f),
      mount options=(d,e) options in (g),

Bug Link: https://bugs.launchpad.net/apparmor/+bug/1597017

Signed-off-by: John Johansen <john.johansen@canonical.com>
- rebased to bba1a023bf
- fixed infinite loop in mnt_rule::gen_policy_re
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 1ec39fd437)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:07:48 +00:00
John Johansen
0e35af4663 parser: add conflicting flags check for options= conditionals
Signed-off-by: John Johansen <john.johansen@canonical.com>
- rebased to bba1a023bf
- after this commit tests mount/ok_[16-19].sd are failing,
   but it's correct
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ecfaf73300)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:04:26 +00:00
John Johansen
d11d2b4922 parser: fix option flag processing for single conditional rules
The combined optional flag and exact match flag processing is problematic
separate out the optional flag processing so it is only combined during
match string generation.

While doing so we fix the flag output so that multiple rules are
not output when they shouldn't be.

In addition we temporarily break multiple options= and 'options in'
conditionals in a single rule, which we will fix in a separate patch.

Bug Link: https://bugs.launchpad.net/apparmor/+bug/1597017

Signed-off-by: John Johansen <john.johansen@canonical.com>
- rebased to bba1a023bf
- made tests happy by changing condition in gen_policy_re()
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 300889c3a4)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:04:19 +00:00
John Johansen
14f1641ab9 Cleanup mount commands flag masking for policy generation
Simplify flag masking and fix the MS_MAKE_CMDS flag set. This is a
step in fixing

Bug Link: https://bugs.launchpad.net/apparmor/+bug/1597017

Signed-off-by: John Johansen <john.johansen@canonical.com>
- rebased to bba1a023bf
- fixed MS_MAKE_CMDS definition to the correct one.
We shouldn't add (MS_ALL_FLAGS & ~(MNT_FLAGS)) to this bitmask.
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ae1950b004)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:04:14 +00:00
John Johansen
e5c71fd1bf Rework mount rule to specicial case multiple rule generation
A step in cleaning up mount rule generation, split out the handling
of mount rules that imply multiple rules to make it easier to
see what is going on.

Bug Link: https://bugs.launchpad.net/apparmor/+bug/1597017

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 206d199a07)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:04:02 +00:00
John Johansen
248edc1e88 refactor: mount gen_policy_re
Do a minimal code refactoring (ie. no functional changes, just moving
code,adding boiler plate and glue) in preparation to fix
bug https://bugs.launchpad.net/apparmor/+bug/1597017

Bug Link: https://bugs.launchpad.net/apparmor/+bug/1597017

Signed-off-by: John Johansen <john.johansen@canonical.com>

- rebased to bba1a023bf
- fixed compiler warnings:
    <built-in>: In member function ‘int mnt_rule::gen_policy_new_mount(Profile&, int&, unsigned int, unsigned int)’:
    <built-in>: note: by argument 1 of type ‘const char*’ to ‘long unsigned int __builtin_strlen(const char*)’ declared here
    mount.cc:880:14: note: ‘class_mount_hdr’ declared here
      880 |         char class_mount_hdr[64];
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit f17e43392b)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-04 13:03:36 +00:00
Christian Boltz
9cd55ff4a5 Merge tests regression: fix failure on older versions of Make
Older versions of Make will choke on the # character in the $(shell
expression, treating it as the beginning of a comment. Resulting in
the following error

make unterminated call to function 'shell': missing ')'.  Stop.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/639
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 8cf3534a5b)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1025
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>
2023-05-03 18:08:13 +00:00
John Johansen
4a8223a547 tests regression: fix failure on older versions of Make
Older versions of Make will choke on the # character in the $(shell
expression, treating it as the beginning of a comment. Resulting in
the following error

make unterminated call to function 'shell': missing ')'.  Stop.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/639
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 8cf3534a5b)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-03 14:49:42 +00:00
John Johansen
b42e033770 Merge Support rule qualifiers in regression tests
This allows regression tests to generate profiles that use rule qualifiers,
such as allow, deny, and audit. Qualifiers can be specified for a rule by
prepending 'qual=', followed by a comma-separated list of rule qualifiers,
then a ':', then the rule itself.

Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
(cherry picked from commit f6bfd141bd)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1020
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
2023-05-02 12:30:44 +00:00
Jon Tourville
e9f69bca3f Support rule qualifiers in regression tests
This allows regression tests to generate profiles that use rule qualifiers,
such as allow, deny, and audit. Qualifiers can be specified for a rule by
prepending 'qual=', followed by a comma-separated list of rule qualifiers,
then a ':', then the rule itself.

Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
(cherry picked from commit f6bfd141bd)
Signed-off-by: Jon Tourville <jon.tourville@canonical.com>
2023-05-02 11:53:50 +02:00
John Johansen
6da000f4e4 Merge fix af_unix tests for v8 networking.
The unix network tests are not being run on a v8 network capable kernel. Under v8 there needs to be some adjustments to the tests because unix rules get downgraded to the socket rule ```network unix,``` which does not have the same set of conditionals or fine grained permissions, meaning some tests that would fail under af_unix (like missing permission tests) will pass under v8 network rules.

Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/893
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 59b4109a8b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-05-01 05:23:25 -07:00
John Johansen
0f0e268b38 tests: regression: fix test failure due to mmap semantic changes
The regression tests are failing on some older kernels due to
commit 9f834ec18defc369d73ccf9e87a2790bfa05bf46 being cherry-picked
back to them without the corresponding apparmor patch
34c426acb75cc21bdf84685e106db0c1a3565057.

This means we can not rely on a simple features/flag check to determine
how the kernel is behaving with regard to mmap. Since this test is
not concerned with testing mmap, instead of adding a more complex
conditional simplify by always adding the m permission.

Fixes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1830984
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Georgia Garcia  <georgia.garcia@canonical.com>
(cherry picked from commit e6e112fba1)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-05-01 05:23:11 -07:00
John Johansen
911a4ded2e Merge abstractions/freedesktop.org: allow custom cursors
... by allowing to read all files below ~/.icons instead of only the
directory listing.

I propose this patch for all branches.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1008
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>


(cherry picked from commit fa86a7f1d9)

954b11fc abstractions/freedesktop.org: allow custom cursors
2023-04-25 19:44:53 +00:00
John Johansen
569423b8e8 Merge Fix error when choosing named exec with plane profile names
When a user choooses to execute to a named profile (not: named child),
make sure to get the profile filename in the correct way to avoid a crash.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/314

I propose this patch for 2.13..master. (Note: I verified that the bug already exists in 2.13, and that this patch fixes it.)

Closes #314
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1013
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>


(cherry picked from commit 30dd1cec42)

103be8e1 Fix error when choosing named exec with plane profile names
2023-04-25 19:42:55 +00:00
Christian Boltz
d93539fa11 Merge abstractions/base: allow reading tzdata ICU zoneinfo DB
This is used by various applications including libreoffice etc so it may as well
be added to the base abstraction along with the existing zoneinfo DB access.

AVC apparmor="DENIED" operation="open" class="file" profile="snap.libreoffice.calc" name="/usr/share/zoneinfo-icu/44/le/zoneinfo64.res" pid=44742 comm="soffice.bin" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

Signed-off-by: Alex Murray <alex.murray@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1007
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 8d9985ac0b)

c691b11d abstractions/base: allow reading tzdata ICU zoneinfo DB
2023-04-11 19:21:59 +00:00
John Johansen
16dc572886 Merge syslogd: allow reading /dev/kmsg
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/307

I propose this patch for master and 3.x (the profile in 2.13 is very different which makes automatic merging impossible)

Closes #307
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1003
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit 6f65faa164)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-03-31 20:11:13 -07:00
John Johansen
a19951a19f Merge abstractions/openssl: allow reading /etc/ssl/openssl-*.cnf
openSUSE Tumbleweed uses /etc/ssl/openssl-1_1.cnf to make the migration
to openssl 3 possible.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1207911

I propose this patch for at least 3.1 and master, ideally for all branches (as long as it can easily be merged)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/984
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit f223ed063e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-02-25 17:07:30 -08:00
Christian Boltz
284cfd891c Merge abstractioms/nvidia: add new cache directory
Some applications (like Firefox or Steam, but for some reason not
glxgears) now writes to ~/.cache/nvidia/*:

```
type=AVC msg=audit(1676115846.764:605): apparmor="DENIED" operation="open" profile="firefox" name="/home/vincas/.cache/nvidia/GLCache/2c0cfcdab4d7b05f8130d8f
ba8838943/ec9a05ca3988cfd1/1fee83e04c0ea4d8.toc" pid=26827 comm="firefox" requested_mask="rac" denied_mask="rac" fsuid=1000 ouid=1000^]FSUID="vincas" OUID="v
incas"
```

```
type=AVC msg=audit(1676134465.264:2166): apparmor="DENIED" operation="open" profile="steam" name="/home/vincas/.cache/nvidia/GLCache/95f6d95b1adf9af310bc94af5f19e509/6b24ef0587ddc7e4/23b502f99abb563c.toc" pid=56082 comm="steam" requested_mask="wr" denied_mask="wr" fsuid=1000 ouid=1000^]FSUID="vincas" OUID="vincas"
```

Update nvidia abstraction to allow create caches in .cache subdirectory.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/982
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit d713f75086)

15b92cd2 abstractioms/nvidia: add new cache directory
2023-02-16 17:42:39 +00:00
Christian Boltz
1cf262a026 Merge nvidia_modprobe: update for driver families and /sys path
Debian have split NVIDIA drivers into current, tesla and legacy:

```
$ apt-file search /etc/nvidia/ | grep -P -o -e
"(?<=/etc/nvidia/).[^/]*/" | sort -u
current/
current-open/
legacy-340xx/
legacy-390xx/
tesla/
tesla-418/
tesla-450/
tesla-460/
tesla-470/
tesla-510/
```

These paths are used by nvidia_modprobe -> kmod:

```
type=AVC msg=audit(1676135718.796:2592): apparmor="DENIED" operation="open" profile="nvidia_modprobe//kmod" name="/etc/nvidia/tesla-470/nvidia-blacklists-nouveau.conf" pid=62094 comm="modprobe" requested_mask="r" denied_mask="r" fsuid=0 ouid=0FSUID="root" OUID="root"
type=AVC msg=audit(1676135718.796:2593): apparmor="DENIED" operation="open" profile="nvidia_modprobe//kmod" name="/etc/nvidia/tesla-470/nvidia-options.conf" pid=62094 comm="modprobe" requested_mask="r" denied_mask="r" fsuid=0 ouid=0FSUID="root" OUID="root"
type=AVC msg=audit(1676135718.796:2594): apparmor="DENIED" operation="open" profile="nvidia_modprobe//kmod" name="/etc/nvidia/tesla-470/nvidia-modprobe.conf" pid=62094 comm="modprobe" requested_mask="r" denied_mask="r" fsuid=0 ouid=0FSUID="root" OUID="root"
```

Also, additional /sys path is accessed:

```
type=AVC msg=audit(1676136251.680:2956): apparmor="DENIED" operation="open" profile="nvidia_modprobe//kmod" name="/sys/module/drm/initstate" pid=63642 comm="modprobe" requested_mask="r" denied_mask="r" fsuid=0 ouid=0FSUID="root" OUID="root"
```

Update nvidia_modprobe profile to this these denials.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/983
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 94d2faab71)

8e50c351 nvidia_modprobe: update for driver families and /sys path
2023-02-14 18:40:29 +00:00
John Johansen
97bf8be391 Merge postfix-tlsmgr: allow reading openssl.cnf
Seen/needed on openSUSE Tumbleweed

I propose this patch for all branches.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/981
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 3e89b4aab2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-02-09 00:19:45 -08:00
John Johansen
b0ace37606 Merge nscd: allow using systemd-userdb
If systemd-userdb is used to configure some users, nscd needs to read
the userdb files.

See also https://www.freedesktop.org/software/systemd/man/nss-systemd.html
for the list of possible filenames (and symlinks).

Fixes: http://bugzilla.opensuse.org/show_bug.cgi?id=1207698

I propose this patch for all branches.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/977
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 5df8da3c37)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-02-01 19:56:55 -08:00
John Johansen
7efbb659a8 Merge Fix mode not being printed when debugging AF_UNIX socket rules.
This was due to the values being defined in both af_unix and af_rule leaving the latter values unset.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/979
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit da7d3a2101)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-02-01 19:52:15 -08:00
Georgia Garcia
8bb8f56f4c Merge Fix spacing when printing out AF_UNIX addresses
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/978
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 608560ee43)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-02-01 19:52:12 -08:00
John Johansen
7d5e5bfdb8 Merge libapparmor: add scanner support for dbus method
In the [merge request that adds AppArmor support on D-Bus Broker](https://github.com/bus1/dbus-broker/pull/286), the word "method" is used instead of "member" on the auditing logs.
So we are adding support to parse "method" the same way as "member" on D-Bus audit logs.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/958
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit a96fa35bd5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-01-25 13:11:08 -08:00
Georgia Garcia
e220954f5d Merge log parsing fixes
small fixes on log parsing

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/959
Approved-by: Jon Tourville <jon.tourville@canonical.com>
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 4f2d2a8cab)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2022-12-16 17:01:13 -03:00
John Johansen
fe2970ebb6 Merge smbd: allow reading /var/lib/nscd/netgroup
(reported on the opensuse-factory mailinglist)

I propose this patch for 2.13..master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/948
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit ba01d479e2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-11-29 12:57:15 -08:00
Christian Boltz
9139dfd309 Merge abstractions/nvidia: allow reading @{pid}/comm
On Debian Sid, NVIDIA driver spams log with:

```
type=AVC msg=audit(1669542108.552:11855): apparmor="DENIED"
operation="open" profile="qtox" name="/proc/21222/comm" pid=21222
comm="qtox" requested_mask="r" denied_mask="r" fsuid=1000
ouid=1000FSUID="vincas" OUID="vincas"
```

```
type=AVC msg=audit(1669541506.703:11329): apparmor="DENIED"
operation="open" profile="skypeforlinux" name="/proc/19851/comm"
pid=19851 comm="skypeforlinux" requested_mask="r" denied_mask="r"
fsuid=1000 ouid=1000FSUID="vincas" OUID="vincas"
```

Read is initiated within libnvidia-glcore.so:

```
Thread 1 "qtox" hit Catchpoint 1 (call to syscall openat), 0x00007fb797b16ed0 in __libc_open64 (file=file@entry=0x7fb742adbb50 "/proc/self/comm", oflag=0) at ../sysdeps/unix/sysv/linux/open64.c:41
41	in ../sysdeps/unix/sysv/linux/open64.c
$27 = 0x7fb742adbb50 "/proc/self/comm"
0  0x00007fb797b16ed0 in __libc_open64 (file=file@entry=0x7fb742adbb50 "/proc/self/comm", oflag=0) at ../sysdeps/unix/sysv/linux/open64.c:41
1  0x00007fb797aa0862 in __GI__IO_file_open (fp=fp@entry=0x55795176e600, filename=filename@entry=0x7fb742adbb50 "/proc/self/comm", posix_mode=<optimized out>, prot=prot@entry=438, read_write=8, is32not64=<optimized out>) at ./libio/fileops.c:188
2  0x00007fb797aa0a1b in _IO_new_file_fopen (fp=fp@entry=0x55795176e600, filename=filename@entry=0x7fb742adbb50 "/proc/self/comm", mode=<optimized out>, mode@entry=0x7fb7428effe2 "r", is32not64=is32not64@entry=1) at ./libio/fileops.c:280
3  0x00007fb797a950f9 in __fopen_internal (filename=0x7fb742adbb50 "/proc/self/comm", mode=0x7fb7428effe2 "r", is32=1) at ./libio/iofopen.c:75
4  0x00007fb7423d791f in ?? () from /lib/x86_64-linux-gnu/libnvidia-glcore.so.470.141.03
5  0x00007fb7423d4515 in ?? () from /lib/x86_64-linux-gnu/libnvidia-glcore.so.470.141.03
6  0x00007fb7423d0226 in ?? () from /lib/x86_64-linux-gnu/libnvidia-glcore.so.470.141.03
7  0x00007fb7423e1961 in ?? () from /lib/x86_64-linux-gnu/libnvidia-glcore.so.470.141.03
8  0x00007fb74824bc79 in ?? () from /lib/x86_64-linux-gnu/libGLX_nvidia.so.0
9  0x00007fb7482b1c56 in ?? () from /lib/x86_64-linux-gnu/libGLX_nvidia.so.0
10 0x000000000000001d in ?? ()
11 0x00005579518975f0 in ?? ()
12 0x0000000000000001 in ?? ()
13 0x00007fb74824b1eb in ?? () from /lib/x86_64-linux-gnu/libGLX_nvidia.so.0
14 0x00005579518975f0 in ?? ()
15 0x00007fb79b2dda79 in call_init (env=0x7ffd92d7aac8, argv=0x7ffd92d7aab8, argc=-1831363648, l=0x7fb748516f70) at ./elf/dl-init.c:56
16 call_init (l=0x7fb748516f70, argc=-1831363648, argv=0x7ffd92d7aab8, env=0x7ffd92d7aac8) at ./elf/dl-init.c:26
17 0x00007fb79b2ddba4 in _dl_init (main_map=0x5579518975f0, argc=1, argv=0x7ffd92d7aab8, env=0x7ffd92d7aac8) at ./elf/dl-init.c:117
18 0x00007fb797b6def4 in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:182
19 0x00007fb79b2e430e in dl_open_worker (a=a@entry=0x7ffd92d79f20) at ./elf/dl-open.c:808
20 0x00007fb797b6de9a in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:208
21 0x00007fb79b2e46a8 in _dl_open (file=0x557951888020 "libGLX_nvidia.so.0", mode=<optimized out>, caller_dlopen=0x7fb78d7d4d27, nsid=<optimized out>, argc=1, argv=0x7ffd92d7aab8, env=0x7ffd92d7aac8) at ./elf/dl-open.c:884
22 0x00007fb797aa42d8 in dlopen_doit (a=a@entry=0x7ffd92d7a190) at ./dlfcn/dlopen.c:56
23 0x00007fb797b6de9a in __GI__dl_catch_exception (exception=exception@entry=0x7ffd92d7a0f0, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:208
24 0x00007fb797b6df4f in __GI__dl_catch_error (objname=0x7ffd92d7a148, errstring=0x7ffd92d7a150, mallocedp=0x7ffd92d7a147, operate=<optimized out>, args=<optimized out>) at ./elf/dl-error-skeleton.c:227
25 0x00007fb797aa3dc7 in _dlerror_run (operate=operate@entry=0x7fb797aa4280 <dlopen_doit>, args=args@entry=0x7ffd92d7a190) at ./dlfcn/dlerror.c:138
26 0x00007fb797aa4389 in dlopen_implementation (dl_caller=<optimized out>, mode=<optimized out>, file=<optimized out>) at ./dlfcn/dlopen.c:71
27 ___dlopen (file=<optimized out>, mode=<optimized out>) at ./dlfcn/dlopen.c:81
28 0x00007fb78d7d4d27 in ?? () from /lib/x86_64-linux-gnu/libGLX.so.0
29 0x00007fb78d7d6335 in ?? () from /lib/x86_64-linux-gnu/libGLX.so.0
30 0x00007fb78d7cf9f8 in glXChooseFBConfig () from /lib/x86_64-linux-gnu/libGLX.so.0
31 0x00007fb748646f6a in ?? () from /usr/lib/x86_64-linux-gnu/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so
32 0x00007fb748644450 in ?? () from /usr/lib/x86_64-linux-gnu/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so
33 0x00007fb7486421b7 in ?? () from /usr/lib/x86_64-linux-gnu/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so
34 0x00007fb79838262d in QOpenGLContext::create() () from /lib/x86_64-linux-gnu/libQt5Gui.so.5
35 0x00007fb74bb4303c in ?? () from /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/KDEPlasmaPlatformTheme.so
36 0x00007fb797eb7aaf in qt_call_pre_routines () at kernel/qcoreapplication.cpp:317
37 QCoreApplicationPrivate::init (this=<optimized out>) at kernel/qcoreapplication.cpp:849
38 0x00007fb7983379dc in QGuiApplicationPrivate::init() () from /lib/x86_64-linux-gnu/libQt5Gui.so.5
39 0x00007fb798b684c9 in QApplicationPrivate::init() () from /lib/x86_64-linux-gnu/libQt5Widgets.so.5
40 0x0000557950f1d597 in main ()
```

Add read rule to allow reading @{pid}/comm.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/954
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 2597fd5db8)

948cbb56 abstractions/nvidia: allow reading @{pid}/comm
2022-11-27 13:07:20 +00:00
Christian Boltz
ef5da8cecc Merge lsb_release: allow cat and cut
lsb_release fails on Debian Sid:

```
$ sudo aa-exec -p lsb_release lsb_release
/usr/bin/lsb_release: 70: cut: Permission denied
/usr/bin/lsb_release: 70: cut: Permission denied
```

```
$ sudo aa-exec -p lsb_release lsb_release -h
/usr/bin/lsb_release: 11: cat: Permission denied
```

```
type=AVC msg=audit(1669540199.087:2680): apparmor="DENIED"
operation="exec" profile="lsb_release" name="/usr/bin/cut" pid=17419
comm="lsb_release" requested_mask="x" denied_mask="x" fsuid=0
ouid=0FSUID="root" OUID="root"
```

```
type=AVC msg=audit(1669540392.244:2944): apparmor="DENIED"
operation="exec" profile="lsb_release" name="/usr/bin/cat" pid=17847
comm="lsb_release" requested_mask="x" denied_mask="x" fsuid=0
ouid=0FSUID="root" OUID="root"
```

Update profile to allow lsb_release script to invoke required
executables.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/953
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 495f68c797)

f596a176 lsb_release: allow cat and cut
2022-11-27 13:00:50 +00:00
John Johansen
b51a2d271d Prepare for AppArmor 2.13.7 release
- update version file

Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-11-21 15:34:09 -08:00
Christian Ehrhardt
f8286feada Allow access to possible cpus for glibc-2.36
Glibc in 2.36 and later will [1] access sysfs at
/sys/devices/system/cpu/possible when usig sysconf
for _SC_NPROCESSORS_CONF.

That will make a lot of different code, for example
anything linked against libnuma, trigger this apparmor
denial.

  apparmor="DENIED" operation="open" class="file" ...
  name="/sys/devices/system/cpu/possible" ...
  requested_mask="r" denied_mask="r" fsuid=0 ouid=0

This entry seems rather safe, and it follows others
that are already in place. Instead of fixing each
software individually this should go into the base
profile as well.

Initially reported via
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1989073
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/267
MR: none - ML
Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit c159d0925a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-11-14 21:48:08 -08:00
John Johansen
5700ff9e40 Merge syslog-ng: allow reading *.journal in flatter directory structure
On openSUSE Leap 15.4 (and probably also 15.3), the journal lives in
/var/log/journal/*.journal - without an additional subdirectory level.

I propose this patch for 2.13..master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/932
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit e049b31c04)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-10-28 06:02:47 -07:00
Christian Boltz
ee0ae96566 Merge [2.13+3.0] Use string startswith() and endswith() methods
... instead of slicing to check for prefixes and suffixes.

This change prevents a crash in aa-mergeprof - if `replacement` is empty,
trying to access `replacement[0]` causes an IndexError.
Using `.startswith()` works without crashing.

This backports parts of the severity.py changes in
commit 091c6ad59d
by Mark Grassi.

I propose this fix for 2.13 and 3.0. (3.1 and master already have this fix.)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/931
Approved-by: Jon Tourville <jon.tourville@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 7ebb259610)

e1714b96 Use string startswith() and endswith() methods
2022-10-11 16:18:43 +00:00
John Johansen
67e7b302a4 Merge dnsmasq: Add missing r permissions for libvirt_leaseshelper
Note: This was reported for /usr/libexec/libvirt_leaseshelper, but since
this is probably unrelated to the path or a path change, this commit
also adds r permissions for the previous path.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1202161

I propose this patch for 3.0 and master (optionally also for 2.12 and 2.13 - please tell me if you want that after reviewing the patch, or just merge ;-)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/905
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>


(cherry picked from commit f51049ea2e)

c9c5208f dnsmasq: Add missing r permissions for libvirt_leaseshelper
2022-08-22 21:52:43 +00:00
John Johansen
157c8ee36a Merge [2.11..2.13] Add 'mctp' network domain keyword [only to utils]
Reported as comment on https://build.opensuse.org/request/show/951354
(update to glibc 2.35)

This is a partial backport of
https://gitlab.com/apparmor/apparmor/-/merge_requests/832

I propose this patch for 2.11, 2.12 and 2.13.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/911
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2022-08-22 21:44:14 +00:00
Christian Boltz
d62b5a9a7d Add 'mctp' network domain keyword [only to utils]
Reported as comment on https://build.opensuse.org/request/show/951354
(update to glibc 2.35)

This is a partial backport of
https://gitlab.com/apparmor/apparmor/-/merge_requests/832
2022-08-22 23:32:29 +02:00
John Johansen
3c047517a4 Merge [2.11..2.13] Support setuptools >= 61.2 in Python tests
Fix for #253, by mirroring the change from 1c23f5e1e4

On top of that, fix setuptools version detection in buildpath.py. libraries/libapparmor/swig/python/test/buildpath.py: The changes introduced in cc7f549665 targetted a wrong setuptools version (61.2). The change in build directory naming has been introduced with 62.0.

Fixes #259 Fixes #39

The first 3 commits are based on https://gitlab.com/apparmor/apparmor/-/merge_requests/897, the other two come from https://gitlab.com/apparmor/apparmor/-/merge_requests/904. Since there are several differences between 2.13 and >= 3.0, I had to adjust the patches at several places.

I propose this MR for 2.11, 2.12 and 2.13.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/910
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2022-08-22 21:31:33 +00:00
David Runge
9fff1c5c6a Use basepath.py in profiles Makefile
profiles/Makefile:
Set PYTHON_DIST_BUILD_PATH using
libraries/libapparmor/swig/python/test/buildpath.py as it solves the
problem of setting the build directory generically.

(cherry picked from commit 1ff0c2c7d6,
 adjusted to 2.13 which used a different python command before)
2022-08-22 22:24:21 +02:00
David Runge
d415e48646 Fix setuptools version detection in buildpath.py
libraries/libapparmor/swig/python/test/buildpath.py:
The changes introduced in
cc7f549665
targetted a wrong setuptools version (61.2).
The change in build directory naming has been introduced with 62.1
(1c23f5e1e4).

(cherry picked from commit fda390983f)
2022-08-22 22:22:40 +02:00
Ben Greiner
63751d20e2 reviewed edits
(cherry picked from commit d442584a0a)
2022-08-22 22:21:11 +02:00
Christian Boltz
411249b3b5 add setuptools to test-utils CI job
This is based on 85734c3bac, but the
.gitlab-ci.yml (and therefore also this patch) is completely different
in 2.13.
2022-08-22 22:19:22 +02:00
Ben Greiner
8921644ab4 use new build_platlib path with setuptools >= 61.2
(cherry picked from commit 47d68dac0f,
 adjusted to the 2.13 branch which used slightly different python
 commands. Also, utils/test/README.md doesn't exist in 2.13, therefore
 drop the part that changes it)
2022-08-22 22:16:09 +02:00
Christian Boltz
fd1b463643 Merge [2.11..2.13] Grep away deprecation warning for distutils
... which will be removed in Python 3.12, and that probably won't be
used on systems running the AppArmor 2.1x branches.

This prevents CI failures on gitlab.com, which uses a new-enough python
to show

    DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives

For 3.0 and master, the proper fix (switching to setuptools) was done in
!813.

I propose this patch for 2.11, 2.12 and 2.13.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/908
Approved-by: John Johansen <john@jjmx.net>
Merged-by: Christian Boltz <apparmor@cboltz.de>
2022-08-22 20:02:46 +00:00
Christian Boltz
ca3e5be507 Grep away deprecation warning for distutils
... which will be removed in Python 3.12, and that probably won't be
used on systems running the AppArmor 2.1x branches.

This prevents CI failures on gitlab.com, which uses a new-enough python
to show

    DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives

For 3.0 and master, the proper fix (switching to setuptools) was done in
!813.
2022-08-16 23:24:44 +02:00
Christian Boltz
37d938b815 Merge Set (instead of compare) exresult
Interestingly this accidentally worked because `if exresult` is true for
both a non-empty string ("PASS") as well as a real `True` value.

Found by Mark Grassi as part of
https://gitlab.com/apparmor/apparmor/-/merge_requests/906

I propose this patch for all branches.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/907
Approved-by: Jon Tourville <jon.tourville@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit c06ea77445)

5a2fb856 Set (instead of compare) exresult
2022-08-16 19:27:04 +00:00
John Johansen
3f4e97e228 Merge Update for the mesa abstraction
I noticed that some apps return the following errors when launched:

```
  kernel: audit: type=1400 audit(1651244478.255:5501): apparmor="DENIED" operation="open" profile="some_app" name="/sys/devices/pci0000:00/0000:00:02.0/revision" pid=1877976 comm="some_app" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
  kernel: audit: type=1400 audit(1651244478.255:5502): apparmor="DENIED" operation="open" profile="some_app" name="/sys/devices/pci0000:00/0000:00:02.0/config" pid=1877976 comm="some_app" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
```

Blocking the files results in the following errors when the app is executed in a terminal:

```
  MESA: error: Failed to query drm device.
  libGL error: failed to create dri screen
  libGL error: failed to load driver: crocus
  MESA: error: Failed to query drm device.
  libGL error: failed to create dri screen
  libGL error: failed to load driver: crocus
```

Since they have something to do with MESA, I think the mesa abstraction should
be updated to fix the issue.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/879
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-05-23 15:37:14 -07:00
John Johansen
7e6df95729 Merge profiles: update snap_browsers permissions
The snap_browsers abstraction requires more permissions
due to updates on snaps.

Some of the permissions are not required in older versions of
Ubuntu that use 2.12 and 2.13, but are introduced for unification
and ease of maintenance purposes. These include:
```
    all dbus permissions,
    @{PROC}/sys/kernel/random/uuid r,
    owner @{PROC}/@{pid}/cgroup r,
    /var/lib/snapd/sequence/{chromium,firefox,opera}.json r,
```

I also propose a cherry-pick of this commit to 2.12, 2.13 and 3.0

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/877
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit bfa67b369d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-04-19 11:38:07 -07:00
Christian Boltz
1a3b81857a Merge Allow dovecot to use all signals
similar to commit 2f9d172c64
we discovered that there was a service outage
when dovecot tried to send a usr1 signal

type=AVC msg=audit(1648024138.249:184964): apparmor="DENIED" operation="signal" profile="dovecot" pid=1690 comm="dovecot" requested_mask="send" denied_mask="send" signal=usr1 peer="dovecot-imap-login"

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/865
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>


(cherry picked from commit 83685ba703)

f0919f83 Allow dovecot to use all signals
2022-03-25 20:53:20 +00:00
Georgia Garcia
e3371f871f add snap-browsers profile
Whenever the evince deb package tries to open a snap browser which was
selected as the default, we get the following denial:

audit[2110]: AVC apparmor="DENIED" operation="exec" profile="/usr/bin/evince" name="/usr/bin/snap" pid=2110 comm="env" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0

As a short-term solution, we are adding a snap-browsers profile
which restricts what snaps opened by evince can do.
The long-term solution is currently not available, but could be
accomplished by using enhanced environment variable filtering/mediation
and delegation of open fds.

Bug: https://launchpad.net/bugs/1794064

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit fb3283f37e)
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/863
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2022-03-17 09:42:07 -03:00
John Johansen
2d6380c26a Merge smbd, samba-bgqd: allow reading openssl.cnf
References: https://bugzilla.opensuse.org/show_bug.cgi?id=1195463#c10

I propose this patch for 3.0 and master. (<= 2.13 don't have the samba-bgpd profile - if we want to backport to 2.x, we'll have to pick only the smbd part.)

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1195463#c10
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/862
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

backport: drop ../profiles/apparmor.d/samba-bgqd
(cherry picked from commit c3f64513f2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-03-13 08:13:00 -07:00
John Johansen
5f3f4ba087 Merge [2.x..3.0] aa-remove-unknown: abort on parser failure
If apparmor_parser -N (in profiles_names_list()) fails,
aa-remove-unknown possibly gets an incomplete list of profiles in
/etc/apparmor.d/ and therefore might remove more profiles than it
should.

Replace the profiles_names_list() call with a direct apparmor_parser
call, and abort aa-remove-unknown if it exits with $? != 0

Before:
```
aa-remove-unknown -n
AppArmor parser error for /etc/apparmor.d/broken in profile /etc/apparmor.d/broken at line 1: syntax error, unexpected TOK_ID, expecting TOK_OPEN
Would remove 'delete_me'
```

After:
```
./aa-remove-unknown -n
AppArmor parser error for /etc/apparmor.d in profile /etc/apparmor.d/zbroken at line 1: syntax error, unexpected TOK_ID, expecting TOK_OPEN
apparmor_parser exited with failure, aborting.
```

And of course, after fixing the broken profile:
```
./aa-remove-unknown -n
Would remove 'delete_me'
```

(cherry picked from commit 5053a01d84)

This backports the fix in `aa-remove-unknown` from !836, but doesn't backport the cleanup in `rc.apparmor.functions`.

I propose this patch for 3.0 and all 2.x branches.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/859
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit c6324c2a3e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-03-09 16:56:16 -08:00
John Johansen
4540cb2f50 libapparmor: fix building with link time optimization (lto)
Currently libapparmor fails to build when lto is used because it uses
the asm directive to provide different version of some symbols.
Unfortunately gcc does not recognize this and the symbols defined by
asm are lost and optimized out by lto and then the link fails.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/214
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/831
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 7cde91f57f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-02-04 15:51:28 -08:00
John Johansen
3cdfe944ac Merge Fix: Opening links with Chrome
Permission denied when Evince tries to use Chrome to open link.

In config is missing the bin: `/opt/google/chrome/crashpad_handler`.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/830
Acked-by: John Johansen <john@jjmx.net>
(cherry picked from commit 08f32ac703)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-02-04 02:18:41 -08:00
John Johansen
15e5b5c459 Merge abstractions/openssl: allow /etc/ssl/{engdef,engines}.d/
These directories were introduced in openssl in https://patchwork.ozlabs.org/project/openwrt/patch/20210429153530.10020-2-cotequeiroz@gmail.com/

I propose this patch for 3.0 and master. Optionally also for older branches, even if it's unlikely that systems using 2.13.x or older get a new-enough openssl to need this ;-)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/818
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 2b270216aa)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-01-17 12:10:18 -08:00
John Johansen
3da24e0116 Merge Add missing /proc permissions to avahi-daemon profile
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/203

MR:https://gitlab.com/apparmor/apparmor/-/merge_requests/811
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ee9e61aad2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-10-30 02:18:48 -07:00
Christian Boltz
be8ab7d538 Merge branch 'fix-lexer' into 'master'
parser: Fix unknown state condition RLIMIT_MODEINCLDE

See merge request apparmor/apparmor!803

Acked-by: Christian Boltz for all branches

(cherry picked from commit b0bc0d5323)

dc7755e5 parser: Fix unknown state condition RLIMIT_MODEINCLDE
2021-09-24 11:26:55 +00:00
Steve Beattie
b469e1f3e8 utils: Add new python versions to logprof.conf
Adding everything up to 3.19 should make the file future-proof for a
while ;-)

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/193
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/795
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 4559a2997c)
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
2021-08-26 10:55:00 -07:00
Christian Boltz
2993533d61 Merge branch 'fix-video-abstraction' into 'master'
add a missing slash at the end of the sys rule

See merge request apparmor/apparmor!791

Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.12..master

(cherry picked from commit 4fd7bcc289)

b3dcd02d add a missing slash at the end of the sys rule
2021-08-20 18:16:32 +00:00
Christian Boltz
5d7b35d30d Merge branch 'cboltz-typo' into 'master'
Fix typo in manpage

Closes #192

See merge request apparmor/apparmor!789

Acked-by: Acked-by: Seth Arnold <seth.arnold@canonical.com> for all branches

(cherry picked from commit 131ae8425b)

1459f49b Fix typo in manpage
2021-08-17 18:26:30 +00:00
John Johansen
2686a0af6c Merge Update abstractions/python and profiles for python 3.10
Add support for python 3.10 in abstractions and profiles.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/187
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/783
Acked-by: John Johansen <john.johansen@canonical.com>
(backported from commit 31fda3eee7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-08-13 13:37:06 -07:00
John Johansen
9de934c3e7 Merge allow Prometheus metrics end-point in dovecot/stats
Patch by Michael Ströder <michael@stroeder.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/776
Acked-by: John Johansen <john@jjmx.net>
(cherry picked from commit d8ec3dafb7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-07-21 12:30:15 -07:00
John Johansen
701943948c parser: fix cache time stamp check to include dir time stamps
Currently for directory includes the directory timestamp is ignored.
This is wrong as operations like removing a file from the dir won't
be considered in the timestamp check.

Fix this by updating the timestamp check to include the included
directories timestamp.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/760
Signed-off-by: John Johansen <john@jjmx.net>
Acked-by: Georgia Garcia  <georgia.garcia@canonical.com>
(cherry picked from commit 3d1232e640)
2021-07-13 18:44:04 -07:00
Georgia Garcia
47bb1a31b0 tests: fix i18n.sh regression test on arm64
The following errors are happening on the regression tests
of i18n.sh on arm64 hirsute/impish:

Error: open failed. Test 'i18n (194) OPEN (octal) "/tmp/sdtest.3654-6536-J2ZwFM/file__post" RW' was expected to 'pass'. Reason for failure 'FAIL: open /tmp/sdtest.3654-6536-J2ZwFM/file__post failed - Permission denied'
...

The cause is a bash bug handling UTF-8 on subshells.

Fixes: https://bugs.launchpad.net/apparmor/+bug/1932331
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/765

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 458a981b62)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2021-06-28 15:49:46 -03:00
Christian Boltz
898c2cda7a abstractions/php: support PHP 8
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1186267
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/755
(cherry picked from commit 5853f52233)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-05-24 03:11:42 -07:00
John Johansen
14ed051657 profiles: dhclient: allow setting task comm name
dhclient wants to set its thread names to functional names for
introspection purposes. Eg.

$ pstree -at 3395
dhclient ens3
  ├─{isc-socket}
  ├─{isc-timer}
  └─{isc-worker0000}

When denied this can result in dhclient breaking and failing to obtain
IPv4 addresses.

Fixes: https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1918410
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit c734839551)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-31 03:02:21 -07:00
John Johansen
8e04e39b7c Merge look up python-config using AC_PATH_TOOL
Doing so adds the $ac_tool_prefix during cross compilation and will end up using the correct, architecture-dependent python-config.

This is the second and last upstreamable change from https://bugs.debian.org/984582. It looks a little simpler here, because apparmor evolved upstream compared to the Debian version. Fortunately, it got a lot simpler in the process.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/729
Acked-by: John Johansen <john.johansen@canonical.com>
(debian version of commit c32c970d00)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-20 03:35:06 -07:00
John Johansen
552ee5d621 Merge Do not abuse AC_CHECK_FILE
AC_CHECK_FILE is meant to check for host files and therefore fails hard during cross compilation unless one supplies a cached check result. Here we want to know about the presence of a build system file though, so AC_CHECK_FILE is the wrong tool.

This is part of https://bugs.debian.org/984582.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/728
Acked-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit f17143b5c3)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-20 03:13:50 -07:00
John Johansen
c8e57213f9 profiles: dhcpd: add rule for port_range
The following AppArmor denial errors are shown on startup:

Oct 25 00:52:00 xxx kernel: [  556.231990] audit: type=1400 audit(1603601520.710:32): apparmor="DENIED" operation="open" profile="/usr/sbin/dhcpd" name="/proc/sys/net/ipv4/ip_local_port_range" pid=1982 comm="dhcpd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

Oct 25 00:52:00 xxx kernel: [  556.232257] audit: type=1400 audit(1603601520.710:33): apparmor="DENIED" operation="open" profile="/usr/sbin/dhcpd" name="/proc/sys/net/ipv4/ip_local_port_range" pid=1982 comm="dhcpd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

Fixes: https://bugs.launchpad.net/bugs/1901373
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/726
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 277677daf3)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-15 23:58:50 -07:00
John Johansen
44e6f90f23 parser: fix filter slashes for link targets
The parser is failing to properly filter the slashes in the link name
after variable expansion. Causing match failures when multiple slashes
occur.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/153
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/723
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 2852e1ecdf)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-15 00:53:06 -07:00
Mikhail Morfikov
dd03484866 abstractions: Add missing rule in wutmp abstraction
Currently the wutmp abstraction has the following rules:
  /var/log/lastlog  rwk,
  /var/log/wtmp     wk,
  @{run}/utmp       rwk,

According to what I see in my apparmor profiles, just a few apps want
to interact with the files listed above, especially with the
/var/log/wtmp . But when the apps do this, they sometimes want the
read access to this file. An example could be the last command. Is
there any reason for not having the r in the rule?  The second thing
is the file /var/log/btmp (which isn't included in the
abstracion). Whenever I see an app, which wants to access the
/var/log/wtmp file, it also tries to interact with the /var/log/btmp
file, for instance lightdm/sddm or su . Most of the time they need
just wk permissions, but sometimes apps need also r on this file, an
example could be the lastb command, which is just a link to last.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/152
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/724
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit d4e0a94511)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-14 11:55:27 -07:00
John Johansen
00396b8f13 parser: fix backport of MR700
The backport of
  855dbd4a parser: fix rule downgrade for unix rules

using the rule_t::warn_once which doesn't exist in the 2.x parser
series. Switch this the the static function warn_once.

Fixes: 3d85e123 parser: fix rule downgrade for unix rules
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-14 09:02:27 -07:00
John Johansen
3d85e1234a parser: fix rule downgrade for unix rules
Rule downgrades are used to provide some confinement when a feature
is only partially supported by the kernel.

  Eg. On a kernel that doesn't support fine grained af_unix mediation
      but does support network mediation.

        unix (connect, receive, send)
              type=stream
              peer=(addr="@/tmp/.ICE-unix/[0-9]*"),

      will be downgraded to

        network unix type=stream,

Which while more permissive still provides some mediation while
allowing the appication to still function. However making the rule
a deny rule result in tightening the profile.

  Eg.
        deny unix (connect, receive, send)
              type=stream
              peer=(addr="@/tmp/.ICE-unix/[0-9]*"),

      will be downgraded to

        deny network unix type=stream,

and that deny rule will take priority over any allow rule. Which means
that if the profile also had unix allow rules they will get blocked by
the downgraded deny rule, because deny rules have a higher priority,
and the application will break. Even worse there is no way to add the
functionality back to the profile without deleting the offending deny
rule.

To fix this we drop deny rules that can't be downgraded in a way that
won't break the application.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1180766
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/700
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 855dbd4ac8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-14 07:19:16 -07:00
Rose Kunkel
4c8ac78605 Fix nscd conflict with systemd-homed
My main user account is managed by systemd-homed. When I enable
AppArmor and have nscd running, I get inconsistent behavior with my
user account - sometimes I can't log in, sometimes I can log in but
not use sudo, etc.

This is the output of getent passwd:
  $ getent passwd
  root0:0::/root:/usr/bin/zsh
  bin1:1::/:/sbin/nologin
  daemon2:2::/:/sbin/nologin
  mail8:12::/var/spool/mail:/sbin/nologin
  ftp14:11::/srv/ftp:/sbin/nologin
  http33:33::/srv/http:/sbin/nologin
  nobody65534:65534:Nobody:/:/sbin/nologin
  dbus81:81:System Message Bus:/:/sbin/nologin
  [...]
  rose1000:1000:Rose Kunkel:/home/rose:/usr/bin/zsh

But getent passwd rose and getent passwd 1000 both return no output.
Stopping nscd.service fixes these problems. Checking the apparmor
logs, I noticed that nscd was denied access to
/etc/machine-id. Allowing access to that file seems to have fixed the
issue.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/707
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/145
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ee5303c8a0)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-02-11 22:56:09 -08:00
Seth Arnold
17032f2254 profiles: firefox Add support for widevine DRM
Ubuntu 18.04, Firefox 60.0.1+build2-0ubuntu0.18.04.1

Running firefix, then going to netflix.com and attempting to play a
movie. The widevinecdm plugin crashes, the following is found in
syslog:

Jun 15 19:13:22 xplt kernel: [301351.553043] audit: type=1400 audit(1529046802.585:246): apparmor="DENIED" operation="file_mmap" profile="/usr/lib/firefox/firefox{,*[^s][^h]}" name="/home/xav/.mozilla/firefox/wiavokxk.default-1510977878171/gmp-widevinecdm/1.4.8.1008/libwidevinecdm.so" pid=16118 comm="plugin-containe" requested_mask="m" denied_mask="m" fsuid=1000 ouid=1000
Jun 15 19:13:22 xplt kernel: [301351.553236] audit: type=1400 audit(1529046802.585:247): apparmor="DENIED" operation="ptrace" profile="/usr/lib/firefox/firefox{,*[^s][^h]}" pid=24714 comm="firefox" requested_mask="trace" denied_mask="trace" peer="/usr/lib/firefox/firefox{,*[^s][^h]}"
Jun 15 19:13:22 xplt kernel: [301351.553259] plugin-containe[16118]: segfault at 0 ip 00007fcdfdaa76af sp 00007ffc1ff03e28 error 6 in libxul.so[7fcdfb77a000+6111000]
Jun 15 19:13:22 xplt snmpd[2334]: error on subcontainer 'ia_addr' insert
...

Fixes: https://bugs.launchpad.net/ubuntu/+source/firefox/+bug/1777070
Reported-by: Xav Paice <xav.paice@canonical.com>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/684
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 656f2103ed)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-02-11 19:40:38 -08:00
John Johansen
de784f55d3 parser: fix --jobs so job scaling is applied correctly
job scaling allows the parser to resample the number of cpus available
and increase the number of jobs that can be launched if cpu available
increases.

Unfortunately job scaling was being applied even when a fixed number
of jobs was specified. So
  --jobs=2

doesn't actually clamp the compile at 2 jobs.

Instead job scaling should only be applied when --jobs=auto or when
jobs are set to a multiple of the cpus.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/703
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
(cherry picked from commit 65ba20b955)
2021-02-10 19:20:27 -08:00
Steve Beattie
ad0a6ac6bf profiles: add new deny path for kwallet (used in KDE 5)
Reported on IRC by finalspacevoid

Acked-by: Steve Beattie <steve@nxnw.org>
Merge branch 'cboltz-kwallet-path' into 'master'
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/704

(cherry picked from commit 15e897cad0)
(Fixed up conflict due to 2.13 not containing the include rule for
 abstractions/private-files-strict.d/)
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-07 22:04:03 -08:00
Christian Boltz
95aa5b5895 apparmor.vim: add support for abi rules
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/690
(cherry picked from commit c421fcd38a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-12-11 14:56:00 -08:00
John Johansen
c16fff8cb4 Release: Bump revisions for 2.13.6 release
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-12-07 03:27:44 -08:00
Christian Boltz
2db3d94ce2 aa-autodep: load abstractions on start
So far, aa-autodep "accidently" loaded the abstractions when parsing the
existing profiles. Obviously, this only worked if there is at least one
profile in the active or extra profile directory.

Without any existing profiles, aa-autodep crashed with
KeyError: '/tmp/apparmor.d/abstractions/base'

Prevent this crash by explicitely loading the abstractions on start.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1178527#c1 [1]
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/682
(cherry picked from commit f6b3de7116)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-11-28 05:13:51 -08:00
Christian Boltz
b174705a31 abstractions/X: Allow (only) reading X compose cache
... (/var/cache/libx11/compose/*), and deny any write attempts

Reported by darix,
https://git.nordisch.org/darix/apparmor-profiles-nordisch/-/blob/master/apparmor.d/teams

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/685
(cherry picked from commit 78bd811e2a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-11-17 02:07:11 -08:00
John Johansen
56cc87aace Merge [2.13] Check hotkey conflicts case-insensitive
This is needed to catch conflicts between uppercase and lowercase hotkeys of the same letter, as seen with `(B)enannt` and `A(b)lehnen` in the german utils translations.

(cherry picked from commit 07bd11390e)

Also fix hotkey conflict in utils id.po and sv.po (cherry picked from commit 7cf54f2cd8)

Note that 7cf54f2cd8 also included fixes for de.po which are not needed in the 2.13 branch.

This is the 2.13 variant of MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/675.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/678
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-03 09:43:39 +00:00
Christian Boltz
ca0d9f758b Fix hotkey conflict in utils id.po and sv.po
(cherry picked from commit 7cf54f2cd8)

Note that 7cf54f2cd8 also included fixes
for de.po which are not needed in the 2.13 branch.
2020-11-01 22:58:19 +01:00
Christian Boltz
a606a59d96 Check hotkey conflicts case-insensitive
This is needed to catch conflicts between uppercase and lowercase
hotkeys of the same letter, as seen with `(B)enannt` and `A(b)lehnen` in
the german utils translations.

(cherry picked from commit 07bd11390e)
2020-11-01 22:39:49 +01:00
John Johansen
6a8a5de637 Merge dovecot: backport usr.lib.dovecot.script-login to 2.13
Backport profile to fix denials in Debian Buster+Bullseye.

Add hashes for #include's, remove abi specification.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/672
Acked-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-27 20:56:09 +00:00
Vincas Dargis
1bcf85737b dovecot: backport usr.lib.dovecot.script-login to 2.13
Backport profile to fix denials in Debian Buster+Bullseye.

Add hashes for #include's, remove abi specification.
2020-10-27 21:14:37 +02:00
Vincas Dargis
ea55ef22e7 dovecot: allow reading dh.pem
Dovecot is hit with this denial on Debian 10 (buster):
```
type=AVC msg=audit(1603647096.369:24514): apparmor="DENIED"
operation="open" profile="dovecot" name="/usr/share/dovecot/dh.pem"
pid=28774 comm="doveconf" requested_mask="r" denied_mask="r" fsuid=0
ouid=0
```

This results in fatal error:

```
Oct 25 19:31:36 dovecot[28774]: doveconf: Fatal: Error in configuration
file /etc/dovecot/conf.d/10-ssl.conf line 50: ssl_dh: Can't open file
/usr/share/dovecot/dh.pem: Permission denied
```

Add rule to allow reading dh.pem.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/671
(cherry picked from commit 9d8e111abe)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-26 15:20:31 -07:00
Vincas Dargis
dc3e2c39fb dovecot: allow kill signal
Dovecot might try to kill related processes:

```
type=AVC msg=audit(1601314853.031:9327): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/auth"

type=AVC msg=audit(1601315453.655:9369): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3"

type=AVC msg=audit(1602939754.145:101362): apparmor="DENIED"
operation="signal" profile="dovecot" pid=31632 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3-login"
```
This discovered on low-power high-load machine (last resort timeout
handling?).

Update signal rule to allow SIGKILL.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/671
(cherry picked from commit 2f9d172c64)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-26 15:20:14 -07:00
John Johansen
1335b80ff4 utils: fix make -C profiles check-logprof fails
On arch
  make -C profiles check-logprof

fails with
  *** Checking profiles from ./apparmor.d against logprof

  ERROR: Can't find AppArmor profiles in /etc/apparmor.d
  make: *** [Makefile:113: check-logprof] Error 1
  make: Leaving directory '/build/apparmor/src/apparmor-2.13.3/profiles'

because /etc/apparmor.d/ is not available in the build environment
and aa-logprofs --dir argument, is not being passed to init_aa()
but used to update profiles_dir after the fact.

Fix this by passing profiledir as an argument to init_aa()

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/36
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/663
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
(backported from commit 15dc06248c)
2020-10-25 01:44:11 -07:00
John Johansen
1808d14e35 Merge Fix 2.13 libapparmor so version
ab0f4ab2ed increased `AA_LIB_REVISION` and `AA_LIB_AGE`, with the result that 2.13.5 builds `libapparmor.so.0.7.3`, while 2.13.4 had `libapparmor-1.6.2`

This patch reverts the `AA_LIB_AGE` increase to fix the so name so that we'll get `libapparmor-1.6.3`.

Note: If you want to apply this fix on top of the 2.13.5 tarball, you'll need to also apply the patch to `Makefile.in`.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/658
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-20 10:39:27 +00:00
Christian Boltz
145136f604 Fix 2.13 libapparmor so version
ab0f4ab2ed increased AA_LIB_REVISION and
AA_LIB_AGE, with the result that 2.13.5 builds libapparmor.so.0.7.3,
while 2.13.4 had libapparmor-1.6.2

This patch reverts the AA_LIB_AGE increase to fix the so name so that
we'll get libapparmor-1.6.3.

Note: If you want to apply this fix on top of the 2.13.5 tarball, you'll
need to also apply the patch to Makefile.in.
2020-10-17 17:30:39 +02:00
115 changed files with 1540 additions and 551 deletions

View File

@@ -1,7 +1,7 @@
---
image: ubuntu:latest
before_script:
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil zlib1g-dev
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil python3-setuptools zlib1g-dev
- lsb_release -a
- uname -a

View File

@@ -1 +1 @@
2.13.5
2.13.8

View File

@@ -58,7 +58,7 @@ if test "$with_perl" = "yes"; then
AC_PATH_PROG(PERL, perl)
test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings])
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no)
AS_IF([test -e "$perl_includedir/perl.h"], enable_perl=yes, enable_perl=no)
fi

View File

@@ -64,7 +64,7 @@ variable to configure. See ``configure --help'' for reference.
# Check if you have distutils, else fail
#
AC_MSG_CHECKING([for the distutils Python package])
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1 | grep -v DeprecationWarning`
if test -z "$ac_distutils_result"; then
AC_MSG_RESULT([yes])
else
@@ -75,12 +75,14 @@ $ac_distutils_result])
PYTHON_VERSION=""
fi
AC_PATH_TOOL([PYTHON_CONFIG],[`basename $PYTHON`-config])
#
# Check for Python include path
#
AC_MSG_CHECKING([for Python include path])
if type $PYTHON-config; then
PYTHON_CPPFLAGS=`$PYTHON-config --includes`
if test -n "$PYTHON_CONFIG"; then
PYTHON_CPPFLAGS=`$PYTHON_CONFIG --includes`
fi
if test -z "$PYTHON_CPPFLAGS"; then
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
@@ -97,8 +99,8 @@ sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
# Check for Python library path
#
AC_MSG_CHECKING([for Python library path])
if type $PYTHON-config; then
PYTHON_LDFLAGS=`$PYTHON-config --ldflags`
if test -n "$PYTHON_CONFIG"; then
PYTHON_LDFLAGS=`$PYTHON_CONFIG --ldflags`
fi
if test -z "$PYTHON_LDFLAGS"; then
# (makes two attempts to ensure we've got a version number

View File

@@ -27,15 +27,15 @@ INCLUDES = $(all_includes)
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
#
AA_LIB_CURRENT = 7
AA_LIB_REVISION = 3
AA_LIB_AGE = 7
AA_LIB_REVISION = 4
AA_LIB_AGE = 6
SUFFIXES = .pc.in .pc
BUILT_SOURCES = grammar.h scanner.h af_protos.h
AM_LFLAGS = -v
AM_YFLAGS = -d -p aalogparse_
AM_CFLAGS = -Wall
AM_CFLAGS = -Wall -flto-partition=none
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
scanner.h: scanner.l
$(LEX) -v $<

View File

@@ -43,6 +43,7 @@
__asm__ (".symver " #real "," #name "@" #version)
#define default_symbol_version(real, name, version) \
__asm__ (".symver " #real "," #name "@@" #version)
#define DLLEXPORT __attribute__((visibility("default"),externally_visible))
#define UNCONFINED "unconfined"
#define UNCONFINED_SIZE strlen(UNCONFINED)
@@ -500,7 +501,7 @@ int aa_change_onexec(const char *profile)
}
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
DLLEXPORT extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
@@ -889,7 +890,7 @@ int query_label(uint32_t mask, char *query, size_t size, int *allowed,
/* export multiple aa_query_label symbols to compensate for downstream
* releases with differing symbol versions. */
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
DLLEXPORT extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);

View File

@@ -6,14 +6,14 @@
IMMUNIX_1.0 {
global:
change_hat;
change_hat; __old_change_hat;
local:
*;
};
APPARMOR_1.0 {
global:
change_hat;
change_hat; __change_hat;
parse_record;
free_record;
local:
@@ -24,7 +24,7 @@ APPARMOR_1.1 {
global:
aa_is_enabled;
aa_find_mountpoint;
aa_change_hat;
aa_change_hat; __old_change_hat;
aa_change_hatv;
aa_change_hat_vargs;
aa_change_profile;
@@ -37,7 +37,7 @@ APPARMOR_1.1 {
free_record;
aa_getprocattr_raw;
aa_getprocattr;
aa_query_label;
aa_query_label; __aa_query_label;
# no more symbols here, please
@@ -47,7 +47,7 @@ APPARMOR_1.1 {
APPARMOR_2.9 {
global:
aa_query_label;
aa_query_label; query_label;
local:
*;
} APPARMOR_1.1;

View File

@@ -161,6 +161,7 @@ key_dest "dest"
key_path "path"
key_interface "interface"
key_member "member"
key_method "method"
key_signal "signal"
key_peer "peer"
key_fstype "fstype"
@@ -345,6 +346,7 @@ yy_flex_debug = 0;
{key_path} { return(TOK_KEY_PATH); }
{key_interface} { return(TOK_KEY_INTERFACE); }
{key_member} { return(TOK_KEY_MEMBER); }
{key_method} { return(TOK_KEY_MEMBER); }
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
{key_fstype} { return(TOK_KEY_FSTYPE); }

View File

@@ -10,8 +10,7 @@ test_python.py: test_python.py.in $(top_builddir)/config.status
CLEANFILES = test_python.py
# bah, how brittle is this?
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")'
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
TESTS = test_python.py
TESTS_ENVIRONMENT = \

View File

@@ -0,0 +1,13 @@
#!/usr/bin/python3
# the build path has changed in setuptools 62.1:
# https://github.com/pypa/setuptools/commit/1c23f5e1e4b18b50081cbabb2dea22bf345f5894
import sys
import sysconfig
import setuptools
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
identifier = sys.implementation.cache_tag
else:
identifier = "%d.%d" % sys.version_info[:2]
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))

View File

@@ -0,0 +1 @@
Dec 15 17:32:17 kinetic kernel: [4835959.046111] audit: type=1107 audit(1671125537.724:209): pid=7308 uid=0 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call" bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" method="Hello" mask="send" label="/tmp/apparmor/tests/regression/apparmor/dbus_message" peer_label="unconfined" exe="/usr/local/bin/dbus-broker" sauid=0 hostname=? addr=? terminal=?'

View File

@@ -0,0 +1,15 @@
START
File: testcase_dbus_11.in
Event type: AA_RECORD_DENIED
Audit ID: 1671125537.724:209
Operation: dbus_method_call
Denied Mask: send
Profile: /tmp/apparmor/tests/regression/apparmor/dbus_message
Peer profile: unconfined
Command: /usr/local/bin/dbus-broker
DBus bus: session
DBus path: /org/freedesktop/DBus
DBus interface: org.freedesktop.DBus
DBus member: Hello
Epoch: 1671125537
Audit subid: 209

View File

@@ -0,0 +1,4 @@
/tmp/apparmor/tests/regression/apparmor/dbus_message {
dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello peer=(label=unconfined),
}

View File

@@ -105,8 +105,7 @@ unix_rule::unix_rule(unsigned int type_p, bool audit_p, bool denied):
unix_rule::unix_rule(int mode_p, struct cond_entry *conds,
struct cond_entry *peer_conds):
af_rule("unix"), addr(NULL), peer_addr(NULL),
audit(0), deny(0)
af_rule("unix"), addr(NULL), peer_addr(NULL)
{
move_conditionals(conds);
move_peer_conditionals(peer_conds);
@@ -130,7 +129,7 @@ ostream &unix_rule::dump_local(ostream &os)
{
af_rule::dump_local(os);
if (addr)
os << "addr='" << addr << "'";
os << " addr='" << addr << "'";
return os;
}
@@ -138,7 +137,7 @@ ostream &unix_rule::dump_peer(ostream &os)
{
af_rule::dump_peer(os);
if (peer_addr)
os << "addr='" << peer_addr << "'";
os << " addr='" << peer_addr << "'";
return os;
}
@@ -204,14 +203,18 @@ void unix_rule::downgrade_rule(Profile &prof) {
yyerror(_("Memory allocation error."));
if (sock_type_n != -1)
mask = 1 << sock_type_n;
if (deny) {
prof.net.deny[AF_UNIX] |= mask;
if (!audit)
prof.net.quiet[AF_UNIX] |= mask;
} else {
if (!deny) {
prof.net.allow[AF_UNIX] |= mask;
if (audit)
prof.net.audit[AF_UNIX] |= mask;
} else {
/* deny rules have to be dropped because the downgrade makes
* the rule less specific meaning it will make the profile more
* restrictive and may end up denying accesses that might be
* allowed by the profile.
*/
if (warnflags & WARN_RULE_NOT_ENFORCED)
warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
}
}

View File

@@ -36,9 +36,6 @@ class unix_rule: public af_rule {
public:
char *addr;
char *peer_addr;
int mode;
int audit;
bool deny;
unix_rule(unsigned int type_p, bool audit_p, bool denied);
unix_rule(int mode, struct cond_entry *conds,

View File

@@ -135,7 +135,7 @@ B<MOUNT FLAGS EXPRESSION> = ( I<MOUNT FLAGS LIST> | I<MOUNT EXPRESSION> )
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nouser' | 'user' )
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nostrictatime' | 'lazytime' | 'nolazytime' | 'nouser' | 'user' | 'symfollow' | 'nosymfollow' )
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
@@ -664,7 +664,7 @@ and other operations that are typically reserved for the root user.
AppArmor supports simple coarse grained network mediation. The network
rule restrict all socket(2) based operations. The mediation done is
a course grained check on whether a socket of a given type and family
a coarse-grained check on whether a socket of a given type and family
can be created, read, or written. There is no mediation based of port
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
only specify type 'dgram' and 'raw'.

View File

@@ -314,12 +314,15 @@ Eg.
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
-jx1 is equivalent to -jauto
The default value is the number of cpus in the system.
The default value is the number of cpus in the system. Note that if jobs
is a positive integer number the --jobs-max parameter is automatically
set to the same value.
=item --max-jobs n
Set a hard cap on the value that can be specified by the --jobs flag.
It takes the same set of options available to the --jobs option, and
When --jobs is set to a scaling value (ie. auto or xN) the specify a
hard cap on the value that can be specified by the --jobs flag. It
takes the same set of options available to the --jobs option, and
defaults to 8*cpus
=item -O n, --optimize=n

View File

@@ -98,6 +98,9 @@
* nomand
* #define MS_DIRSYNC 128 Directory modifications are synchronous
* dirsync
* #define MS_NOSYMFOLLOW 256 Do not follow symlinks
* symfollow
* nosymfollow
* #define MS_NOATIME 1024 Do not update access times
* noatime
* atime
@@ -139,6 +142,9 @@
* #define MS_STRICTATIME (1<<24) Always perform atime updates
* strictatime
* nostrictatime
* #define MS_LAZYTIME (1<<25) Update the on-disk [acm]times lazily
* lazytime
* nolazytime
* #define MS_NOSEC (1<<28)
* #define MS_BORN (1<<29)
* #define MS_ACTIVE (1<<30)
@@ -247,6 +253,8 @@ static struct mnt_keyword_table mnt_opts_table[] = {
{"mand", MS_MAND, 0},
{"nomand", 0, MS_MAND},
{"dirsync", MS_DIRSYNC, 0},
{"symfollow", 0, MS_NOSYMFOLLOW},
{"nosymfollow", MS_NOSYMFOLLOW, 0},
{"atime", 0, MS_NOATIME},
{"noatime", MS_NOATIME, 0},
{"diratime", 0, MS_NODIRATIME},
@@ -284,6 +292,9 @@ static struct mnt_keyword_table mnt_opts_table[] = {
{"iversion", MS_IVERSION, 0},
{"noiversion", 0, MS_IVERSION},
{"strictatime", MS_STRICTATIME, 0},
{"nostrictatime", 0, MS_STRICTATIME},
{"lazytime", MS_LAZYTIME, 0},
{"nolazytime", 0, MS_LAZYTIME},
{"user", 0, (unsigned int) MS_NOUSER},
{"nouser", (unsigned int) MS_NOUSER, 0},
@@ -299,6 +310,22 @@ static struct mnt_keyword_table mnt_conds_table[] = {
{NULL, 0, 0}
};
static ostream &dump_flags(ostream &os,
pair <unsigned int, unsigned int> flags)
{
for (int i = 0; mnt_opts_table[i].keyword; i++) {
if ((flags.first & mnt_opts_table[i].set) ||
(flags.second & mnt_opts_table[i].clear))
os << mnt_opts_table[i].keyword;
}
return os;
}
ostream &operator<<(ostream &os, pair<unsigned int, unsigned int> flags)
{
return dump_flags(os, flags);
}
static int find_mnt_keyword(struct mnt_keyword_table *table, const char *name)
{
int i;
@@ -321,7 +348,7 @@ int is_valid_mnt_cond(const char *name, int src)
static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
{
unsigned int flags = 0;
unsigned int flags = 0, invflags = 0;
*inv = 0;
struct value_list *entry, *tmp, *prev = NULL;
@@ -330,11 +357,11 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
i = find_mnt_keyword(mnt_opts_table, entry->value);
if (i != -1) {
flags |= mnt_opts_table[i].set;
*inv |= mnt_opts_table[i].clear;
invflags |= mnt_opts_table[i].clear;
PDEBUG(" extracting mount flag %s req: 0x%x inv: 0x%x"
" => req: 0x%x inv: 0x%x\n",
entry->value, mnt_opts_table[i].set,
mnt_opts_table[i].clear, flags, *inv);
mnt_opts_table[i].clear, flags, invflags);
if (prev)
prev->next = tmp;
if (entry == *list)
@@ -345,9 +372,27 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
prev = entry;
}
if (inv)
*inv = invflags;
return flags;
}
static bool conflicting_flags(unsigned int flags, unsigned int inv)
{
if (flags & inv) {
for (int i = 0; i < 31; i++) {
unsigned int mask = 1 << i;
if ((flags & inv) & mask) {
cerr << "conflicting flag values = "
<< flags << ", " << inv << "\n";
}
}
return true;
}
return false;
}
static struct value_list *extract_fstype(struct cond_entry **conds)
{
struct value_list *list = NULL;
@@ -370,22 +415,19 @@ static struct value_list *extract_fstype(struct cond_entry **conds)
return list;
}
static struct value_list *extract_options(struct cond_entry **conds, int eq)
static struct cond_entry *extract_options(struct cond_entry **conds, int eq)
{
struct value_list *list = NULL;
struct cond_entry *entry, *tmp, *prev = NULL;
struct cond_entry *list = NULL, *entry, *tmp, *prev = NULL;
list_for_each_safe(*conds, entry, tmp) {
if ((strcmp(entry->name, "options") == 0 ||
strcmp(entry->name, "option") == 0) &&
entry->eq == eq) {
list_remove_at(*conds, prev, entry);
PDEBUG(" extracting option %s\n", entry->name);
list_append(entry->vals, list);
list = entry->vals;
entry->vals = NULL;
free_cond_entry(entry);
PDEBUG(" extracting %s %s\n", entry->name, entry->eq ?
"=" : "in");
list_append(entry, list);
list = entry;
} else
prev = entry;
}
@@ -393,60 +435,129 @@ static struct value_list *extract_options(struct cond_entry **conds, int eq)
return list;
}
static void perror_conds(const char *rule, struct cond_entry *conds)
{
struct cond_entry *entry;
list_for_each(conds, entry) {
PERROR( "unsupported %s condition '%s%s(...)'\n", rule, entry->name, entry->eq ? "=" : " in ");
}
}
static void perror_vals(const char *rule, struct value_list *vals)
{
struct value_list *entry;
list_for_each(vals, entry) {
PERROR( "unsupported %s value '%s'\n", rule, entry->value);
}
}
static void process_one_option(struct cond_entry *&opts, unsigned int &flags,
unsigned int &inv_flags)
{
struct cond_entry *entry;
struct value_list *vals;
entry = list_pop(opts);
vals = entry->vals;
entry->vals = NULL;
/* fail if there are any unknown optional flags */
if (opts) {
PERROR(" unsupported multiple 'mount options %s(...)'\n", entry->eq ? "=" : " in ");
exit(1);
}
free_cond_entry(entry);
flags = extract_flags(&vals, &inv_flags);
if (vals) {
perror_vals("mount option", vals);
exit(1);
}
}
mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
struct cond_entry *dst_conds unused, char *mnt_point_p,
int allow_p):
mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
flags(0), inv_flags(0), audit(0), deny(0)
flagsv(0), opt_flagsv(0), audit(0), deny(0)
{
/* FIXME: dst_conds are ignored atm */
dev_type = extract_fstype(&src_conds);
if (src_conds) {
struct value_list *list = extract_options(&src_conds, 0);
/* move options in () to local list */
struct cond_entry *opts_in = extract_options(&src_conds, 0);
opts = extract_options(&src_conds, 1);
if (opts)
flags = extract_flags(&opts, &inv_flags);
if (opts_in) {
unsigned int tmpflags = 0, tmpinv_flags = 0;
struct cond_entry *entry;
if (list) {
unsigned int tmpflags, tmpinv_flags = 0;
tmpflags = extract_flags(&list, &tmpinv_flags);
/* these flags are optional so set both */
tmpflags |= tmpinv_flags;
tmpinv_flags |= tmpflags;
flags |= tmpflags;
inv_flags |= tmpinv_flags;
if (opts)
list_append(opts, list);
else if (list)
opts = list;
while ((entry = list_pop(opts_in))) {
process_one_option(entry, tmpflags,
tmpinv_flags);
/* optional flags if set/clear mean the same
* thing and can be represented by a single
* bitset, also there is no need to check for
* conflicting flags when they are optional
*/
opt_flagsv.push_back(tmpflags | tmpinv_flags);
}
}
/* move options=() to opts list */
struct cond_entry *opts_eq = extract_options(&src_conds, 1);
if (opts_eq) {
unsigned int tmpflags = 0, tmpinv_flags = 0;
struct cond_entry *entry;
while ((entry = list_pop(opts_eq))) {
process_one_option(entry, tmpflags,
tmpinv_flags);
/* throw away tmpinv_flags, only needed in
* consistancy check
*/
if (allow_p & AA_DUMMY_REMOUNT)
tmpflags |= MS_REMOUNT;
if (conflicting_flags(tmpflags, tmpinv_flags)) {
PERROR("conflicting flags in the rule\n");
exit(1);
}
flagsv.push_back(tmpflags);
}
}
if (src_conds) {
perror_conds("mount", src_conds);
exit(1);
}
}
if (!(flagsv.size() + opt_flagsv.size())) {
/* no flag options, and not remount, allow everything */
if (allow_p & AA_DUMMY_REMOUNT) {
flagsv.push_back(MS_REMOUNT);
opt_flagsv.push_back(MS_REMOUNT_FLAGS & ~MS_REMOUNT);
} else {
flagsv.push_back(MS_ALL_FLAGS);
opt_flagsv.push_back(MS_ALL_FLAGS);
}
} else if (!(flagsv.size())) {
/* no flags but opts set */
if (allow_p & AA_DUMMY_REMOUNT)
flagsv.push_back(MS_REMOUNT);
else
flagsv.push_back(0);
} else if (!(opt_flagsv.size())) {
opt_flagsv.push_back(0);
}
if (allow_p & AA_DUMMY_REMOUNT) {
allow_p = AA_MAY_MOUNT;
flags |= MS_REMOUNT;
inv_flags = 0;
} else if (!(flags | inv_flags)) {
/* no flag options, and not remount, allow everything */
flags = MS_ALL_FLAGS;
inv_flags = MS_ALL_FLAGS;
}
allow = allow_p;
if (src_conds) {
PERROR(" unsupported mount conditions\n");
exit(1);
}
if (opts) {
PERROR(" unsupported mount options\n");
exit(1);
}
}
ostream &mnt_rule::dump(ostream &os)
@@ -460,7 +571,11 @@ ostream &mnt_rule::dump(ostream &os)
else
os << "error: unknonwn mount perm";
os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
for (unsigned int i = 0; i < flagsv.size(); i++)
os << " flags=(0x" << hex << flagsv[i] << ")";
for (unsigned int i = 0; i < opt_flagsv.size(); i++)
os << " flags in (0x" << hex << opt_flagsv[i] << ")";
if (dev_type) {
os << " type=";
print_value_list(dev_type);
@@ -516,7 +631,7 @@ int mnt_rule::expand_variables(void)
}
static int build_mnt_flags(char *buffer, int size, unsigned int flags,
unsigned int inv_flags)
unsigned int opt_flags)
{
char *p = buffer;
int i, len = 0;
@@ -529,7 +644,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
return TRUE;
}
for (i = 0; i <= 31; ++i) {
if ((flags & inv_flags) & (1 << i))
if ((opt_flags) & (1 << i))
len = snprintf(p, size, "(\\x%02x|)", i + 1);
else if (flags & (1 << i))
len = snprintf(p, size, "\\x%02x", i + 1);
@@ -595,7 +710,9 @@ static void warn_once(const char *name)
}
}
int mnt_rule::gen_policy_re(Profile &prof)
int mnt_rule::gen_policy_remount(Profile &prof, int &count,
unsigned int flags, unsigned int opt_flags)
{
std::string mntbuf;
std::string devbuf;
@@ -604,215 +721,317 @@ int mnt_rule::gen_policy_re(Profile &prof)
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
int count = 0;
unsigned int tmpflags, tmpinv_flags;
int tmpallow;
if (!kernel_supports_mount) {
warn_once(prof.name);
return RULE_NOT_SUPPORTED;
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* remount can't be conditional on device and type */
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (mnt_point) {
/* both device && mnt_point or just mnt_point */
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
} else {
if (!convert_entry(mntbuf, device))
goto fail;
vec[0] = mntbuf.c_str();
}
/* skip device */
vec[1] = default_match_pattern;
/* skip type */
vec[2] = default_match_pattern;
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_REMOUNT_FLAGS,
opt_flags & MS_REMOUNT_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (opts)
tmpallow = AA_MATCH_CONT;
else
tmpallow = allow;
/* rule for match without required data || data MATCH_CONT */
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
audit | AA_AUDIT_MNT_DATA, 4,
vec, dfaflags))
goto fail;
count++;
if (opts) {
/* rule with data match required */
optsbuf.clear();
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(deny, allow,
audit | AA_AUDIT_MNT_DATA,
5, vec, dfaflags))
goto fail;
count++;
}
return RULE_OK;
fail:
return RULE_ERROR;
}
int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
unsigned int flags, unsigned int opt_flags)
{
std::string mntbuf;
std::string devbuf;
std::string typebuf;
char flagsbuf[PATH_MAX + 3];
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* bind mount rules can't be conditional on dev_type or data */
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
/* skip type */
vec[2] = default_match_pattern;
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_BIND_FLAGS,
opt_flags & MS_BIND_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
return RULE_OK;
fail:
return RULE_ERROR;
}
int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
unsigned int flags,
unsigned int opt_flags)
{
std::string mntbuf;
std::string devbuf;
std::string typebuf;
char flagsbuf[PATH_MAX + 3];
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* change type base rules can not be conditional on device,
* device type or data
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
/* skip device and type */
vec[1] = default_match_pattern;
vec[2] = default_match_pattern;
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MAKE_FLAGS,
opt_flags & MS_MAKE_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
return RULE_OK;
fail:
return RULE_ERROR;
}
int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
unsigned int flags, unsigned int opt_flags)
{
std::string mntbuf;
std::string devbuf;
std::string typebuf;
char flagsbuf[PATH_MAX + 3];
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* mount move rules can not be conditional on dev_type,
* or data
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
/* skip type */
vec[2] = default_match_pattern;
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MOVE_FLAGS,
opt_flags & MS_MOVE_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
return RULE_OK;
fail:
return RULE_ERROR;
}
int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
unsigned int flags, unsigned int opt_flags)
{
std::string mntbuf;
std::string devbuf;
std::string typebuf;
char flagsbuf[PATH_MAX + 3];
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
int tmpallow;
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
typebuf.clear();
if (!build_list_val_expr(typebuf, dev_type))
goto fail;
vec[2] = typebuf.c_str();
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_NEW_FLAGS,
opt_flags & MS_NEW_FLAGS))
goto fail;
vec[3] = flagsbuf;
if (opts)
tmpallow = AA_MATCH_CONT;
else
tmpallow = allow;
/* rule for match without required data || data MATCH_CONT */
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
audit | AA_AUDIT_MNT_DATA, 4,
vec, dfaflags))
goto fail;
count++;
if (opts) {
/* rule with data match required */
optsbuf.clear();
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(deny, allow,
audit | AA_AUDIT_MNT_DATA,
5, vec, dfaflags))
goto fail;
count++;
}
return RULE_OK;
fail:
return RULE_ERROR;
}
int mnt_rule::gen_flag_rules(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags)
{
/*
* XXX: added !flags to cover cases like:
* mount options in (bind) /d -> /4,
*/
if ((allow & AA_MAY_MOUNT) && (!flags || flags == MS_ALL_FLAGS)) {
/* no mount flags specified, generate multiple rules */
if (!device && !dev_type &&
gen_policy_remount(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
if (!dev_type && !opts &&
gen_policy_bind_mount(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
if (!device && !dev_type && !opts &&
gen_policy_change_mount_type(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
if (!dev_type && !opts &&
gen_policy_move_mount(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
return gen_policy_new_mount(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
&& !device && !dev_type) {
return gen_policy_remount(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
&& !dev_type && !opts) {
return gen_policy_bind_mount(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) &&
(flags & (MS_MAKE_CMDS))
&& !device && !dev_type && !opts) {
return gen_policy_change_mount_type(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
&& !dev_type && !opts) {
return gen_policy_move_mount(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) &&
((flags | opt_flags) & ~MS_CMDS)) {
/* generic mount if flags are set that are not covered by
* above commands
*/
return gen_policy_new_mount(prof, count, flags, opt_flags);
} /* else must be RULE_OK for some rules */
return RULE_OK;
}
int mnt_rule::gen_policy_re(Profile &prof)
{
std::string mntbuf;
std::string devbuf;
std::string typebuf;
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
int count = 0;
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* a single mount rule may result in multiple matching rules being
* created in the backend to cover all the possible choices
*/
if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
&& !device && !dev_type) {
int tmpallow;
/* remount can't be conditional on device and type */
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (mnt_point) {
/* both device && mnt_point or just mnt_point */
if (!convert_entry(mntbuf, mnt_point))
for (size_t i = 0; i < flagsv.size(); i++) {
for (size_t j = 0; j < opt_flagsv.size(); j++) {
if (gen_flag_rules(prof, count, flagsv[i], opt_flagsv[j]) == RULE_ERROR)
goto fail;
vec[0] = mntbuf.c_str();
} else {
if (!convert_entry(mntbuf, device))
goto fail;
vec[0] = mntbuf.c_str();
}
/* skip device */
vec[1] = default_match_pattern;
/* skip type */
vec[2] = default_match_pattern;
tmpflags = flags;
tmpinv_flags = inv_flags;
if (tmpflags != MS_ALL_FLAGS)
tmpflags &= MS_REMOUNT_FLAGS;
if (tmpinv_flags != MS_ALL_FLAGS)
tmpflags &= MS_REMOUNT_FLAGS;
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
goto fail;
vec[3] = flagsbuf;
if (opts)
tmpallow = AA_MATCH_CONT;
else
tmpallow = allow;
/* rule for match without required data || data MATCH_CONT */
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
audit | AA_AUDIT_MNT_DATA, 4,
vec, dfaflags))
goto fail;
count++;
if (opts) {
/* rule with data match required */
optsbuf.clear();
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(deny, allow,
audit | AA_AUDIT_MNT_DATA,
5, vec, dfaflags))
goto fail;
count++;
}
}
if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
&& !dev_type && !opts) {
/* bind mount rules can't be conditional on dev_type or data */
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
/* skip type */
vec[2] = default_match_pattern;
tmpflags = flags;
tmpinv_flags = inv_flags;
if (tmpflags != MS_ALL_FLAGS)
tmpflags &= MS_BIND_FLAGS;
if (tmpinv_flags != MS_ALL_FLAGS)
tmpflags &= MS_BIND_FLAGS;
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
}
if ((allow & AA_MAY_MOUNT) &&
(flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
&& !device && !dev_type && !opts) {
/* change type base rules can not be conditional on device,
* device type or data
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
/* skip device and type */
vec[1] = default_match_pattern;
vec[2] = default_match_pattern;
tmpflags = flags;
tmpinv_flags = inv_flags;
if (tmpflags != MS_ALL_FLAGS)
tmpflags &= MS_MAKE_FLAGS;
if (tmpinv_flags != MS_ALL_FLAGS)
tmpflags &= MS_MAKE_FLAGS;
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
}
if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
&& !dev_type && !opts) {
/* mount move rules can not be conditional on dev_type,
* or data
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
/* skip type */
vec[2] = default_match_pattern;
tmpflags = flags;
tmpinv_flags = inv_flags;
if (tmpflags != MS_ALL_FLAGS)
tmpflags &= MS_MOVE_FLAGS;
if (tmpinv_flags != MS_ALL_FLAGS)
tmpflags &= MS_MOVE_FLAGS;
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
goto fail;
vec[3] = flagsbuf;
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
dfaflags))
goto fail;
count++;
}
if ((allow & AA_MAY_MOUNT) &&
(flags | inv_flags) & ~MS_CMDS) {
int tmpallow;
/* generic mount if flags are set that are not covered by
* above commands
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
goto fail;
vec[0] = mntbuf.c_str();
if (!clear_and_convert_entry(devbuf, device))
goto fail;
vec[1] = devbuf.c_str();
typebuf.clear();
if (!build_list_val_expr(typebuf, dev_type))
goto fail;
vec[2] = typebuf.c_str();
tmpflags = flags;
tmpinv_flags = inv_flags;
if (tmpflags != MS_ALL_FLAGS)
tmpflags &= ~MS_CMDS;
if (tmpinv_flags != MS_ALL_FLAGS)
tmpinv_flags &= ~MS_CMDS;
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
goto fail;
vec[3] = flagsbuf;
if (opts)
tmpallow = AA_MATCH_CONT;
else
tmpallow = allow;
/* rule for match without required data || data MATCH_CONT */
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
audit | AA_AUDIT_MNT_DATA, 4,
vec, dfaflags))
goto fail;
count++;
if (opts) {
/* rule with data match required */
optsbuf.clear();
if (!build_mnt_opts(optsbuf, opts))
goto fail;
vec[4] = optsbuf.c_str();
if (!prof.policy.rules->add_rule_vec(deny, allow,
audit | AA_AUDIT_MNT_DATA,
5, vec, dfaflags))
goto fail;
count++;
}
}
if (allow & AA_MAY_UMOUNT) {

View File

@@ -20,6 +20,7 @@
#define __AA_MOUNT_H
#include <ostream>
#include <vector>
#include "parser.h"
#include "rule.h"
@@ -39,6 +40,8 @@
#define MS_MAND (1 << 6)
#define MS_NOMAND 0
#define MS_DIRSYNC (1 << 7)
#define MS_SYMFOLLOW 0
#define MS_NOSYMFOLLOW (1 << 8)
#define MS_NODIRSYNC 0
#define MS_NOATIME (1 << 10)
#define MS_ATIME 0
@@ -61,6 +64,7 @@
#define MS_IVERSION (1 << 23)
#define MS_NOIVERSION 0
#define MS_STRICTATIME (1 << 24)
#define MS_LAZYTIME (1 << 25)
#define MS_NOUSER (1 << 31)
#define MS_USER 0
@@ -74,12 +78,14 @@
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
MS_NOSYMFOLLOW | \
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
MS_MOVE | MS_VERBOSE | MS_ACL | \
MS_UNBINDABLE | MS_RUNBINDABLE | \
MS_PRIVATE | MS_RPRIVATE | \
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED | \
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | MS_USER)
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | \
MS_LAZYTIME | MS_USER)
/* set of flags we don't use but define (but not with the kernel values)
* for MNT_FLAGS
@@ -94,16 +100,15 @@
MS_KERNMOUNT | MS_STRICTATIME)
#define MS_BIND_FLAGS (MS_BIND | MS_RBIND)
#define MS_MAKE_FLAGS ((MS_UNBINDABLE | MS_RUNBINDABLE | \
#define MS_MAKE_CMDS (MS_UNBINDABLE | MS_RUNBINDABLE | \
MS_PRIVATE | MS_RPRIVATE | \
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED) | \
(MS_ALL_FLAGS & ~(MNT_FLAGS)))
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
#define MS_MAKE_FLAGS (MS_ALL_FLAGS & ~(MNT_FLAGS))
#define MS_MOVE_FLAGS (MS_MOVE)
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | \
MS_UNBINDABLE | MS_RUNBINDABLE | MS_PRIVATE | MS_RPRIVATE | \
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | MS_MAKE_CMDS)
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
#define MS_NEW_FLAGS (MS_ALL_FLAGS & ~MS_CMDS)
#define MNT_SRC_OPT 1
#define MNT_DST_OPT 2
@@ -121,6 +126,19 @@
class mnt_rule: public rule_t {
int gen_policy_remount(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags);
int gen_policy_bind_mount(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags);
int gen_policy_change_mount_type(Profile &prof, int &count,
unsigned int flags,
unsigned int opt_flags);
int gen_policy_move_mount(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags);
int gen_policy_new_mount(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags);
int gen_flag_rules(Profile &prof, int &count, unsigned int flags,
unsigned int opt_flags);
public:
char *mnt_point;
char *device;
@@ -128,7 +146,7 @@ public:
struct value_list *dev_type;
struct value_list *opts;
unsigned int flags, inv_flags;
std::vector<unsigned int> flagsv, opt_flagsv;
int allow, audit;
int deny;

View File

@@ -204,6 +204,7 @@ do { \
#endif
#define list_first(LIST) (LIST)
#define list_for_each(LIST, ENTRY) \
for ((ENTRY) = (LIST); (ENTRY); (ENTRY) = (ENTRY)->next)
#define list_for_each_safe(LIST, ENTRY, TMP) \
@@ -237,6 +238,16 @@ do { \
prev; \
})
#define list_pop(LIST) \
({ \
typeof(LIST) _entry = (LIST); \
if (LIST) { \
(LIST) = (LIST)->next; \
_entry->next = NULL; \
} \
_entry; \
})
#define list_remove_at(LIST, PREV, ENTRY) \
if (PREV) \
(PREV)->next = (ENTRY)->next; \

View File

@@ -180,6 +180,7 @@ void include_filename(char *filename, int search, bool if_exists)
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
} else if (S_ISDIR(my_stat.st_mode)) {
struct cb_struct data = { fullpath, filename };
update_mru_tstamp(include_file, fullpath);
fclose(include_file);
include_file = NULL;
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
@@ -715,7 +716,7 @@ include/{WS} {
}
}
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODEINCLUDE,INCLUDE_EXISTS,ABI_MODE>{
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODE,INCLUDE,INCLUDE_EXISTS,ABI_MODE>{
(.|\n) {
DUMP_PREPROCESS;
/* Something we didn't expect */

View File

@@ -638,6 +638,8 @@ static int process_arg(int c, char *optarg)
break;
case 'j':
jobs = process_jobs_arg("-j", optarg);
if (jobs != JOBS_AUTO && jobs < LONG_MAX)
jobs_max = jobs;
break;
case 136:
jobs_max = process_jobs_arg("max-jobs", optarg);
@@ -1183,6 +1185,8 @@ static void setup_parallel_compile(void)
if (maxn == -1)
/* unable to determine number of processors, default to 1 */
maxn = 1;
if (jobs < 0 || jobs == JOBS_AUTO)
jobs_scale = 1;
jobs = compute_jobs(n, jobs);
jobs_max = compute_jobs(maxn, jobs_max);
@@ -1190,7 +1194,7 @@ static void setup_parallel_compile(void)
pwarn("%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
progname, jobs_max, jobs);
jobs = jobs_max;
} else if (jobs < jobs_max)
} else if (jobs_scale && jobs < jobs_max)
/* the bigger the difference the more sample chances given */
jobs_scale = jobs_max + 1 - n;

View File

@@ -564,6 +564,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
int pos;
vec[0] = tbuf.c_str();
if (entry->link_name) {
filter_slashes(entry->link_name);
ptype = convert_aaregex_to_pcre(entry->link_name, 0, glob_default, lbuf, &pos);
if (ptype == ePatternInvalid)
return FALSE;

View File

@@ -547,7 +547,21 @@ verify_binary_equality "set rlimit memlock <= 2GB" \
"/t { set rlimit memlock <= 2GB, }" \
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }" \
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
# verify slash filtering for link rules
verify_binary_equality "link rules slash filtering" \
"/t { link /dev/foo -> /mnt/bar, }" \
"/t { link ///dev/foo -> /mnt/bar, }" \
"/t { link /dev/foo -> /mnt//bar, }" \
"/t { link /dev///foo -> ////mnt/bar, }" \
"@{BAR}=/mnt/
/t { link /dev///foo -> @{BAR}/bar, }" \
"@{FOO}=/dev/
/t { link @{FOO}//foo -> /mnt/bar, }" \
"@{FOO}=/dev/
@{BAR}=/mnt/
/t { link @{FOO}/foo -> @{BAR}/bar, }" \
if [ $fails -ne 0 -o $errors -ne 0 ]
then

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule with incompatible options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(rw, ro) -> /foo,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule with incompatible options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(rw ro) -> /foo,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule with incompatible options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(rw ro) fstype=procfs -> /foo,
}

View File

@@ -1,6 +1,6 @@
#
#=Description basic mount rule
#=EXRESULT PASS
#=Description basic mount rule with incompatible options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(rw ro) fstype=(procfs) none -> /foo,

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting = options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(strictatime, nostrictatime) -> /foo,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting = options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(lazytime, nolazytime) -> /foo,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting = options
#=EXRESULT FAIL
#
/usr/bin/foo {
mount options=(symfollow, nosymfollow) -> /foo,
}

View File

@@ -3,5 +3,5 @@
#=EXRESULT PASS
#
/usr/bin/foo {
mount options=(rw, ro) -> /foo,
mount options=(rw nosuid) -> /foo,
}

View File

@@ -1,7 +0,0 @@
#
#=Description basic mount rule
#=EXRESULT PASS
#
/usr/bin/foo {
mount options=(rw ro) -> /foo,
}

View File

@@ -1,7 +0,0 @@
#
#=Description basic mount rule
#=EXRESULT PASS
#
/usr/bin/foo {
mount options=(rw ro) fstype=procfs -> /foo,
}

View File

@@ -0,0 +1,8 @@
#
#=Description basic rules to test the "nostrictatime" mount option
#=EXRESULT PASS
/usr/bin/foo {
mount options=nostrictatime /a -> /1,
mount options=(nostrictatime) /b -> /2,
mount options in (nostrictatime) /d -> /4,
}

View File

@@ -0,0 +1,8 @@
#
#=Description basic rules to test the "lazytime" mount option
#=EXRESULT PASS
/usr/bin/foo {
mount options=lazytime /a -> /1,
mount options=(lazytime) /b -> /2,
mount options in (lazytime) /d -> /4,
}

View File

@@ -0,0 +1,8 @@
#
#=Description basic rules to test the "nolazytime" mount option
#=EXRESULT PASS
/usr/bin/foo {
mount options=nolazytime /a -> /1,
mount options=(nolazytime) /b -> /2,
mount options in (nolazytime) /d -> /4,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic rules to test the "strictatime" mount option in combination
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw,strictatime) /c -> /3,
mount options in (ro,strictatime) /e -> /5,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic rules to test the "nostrictatime" mount option in combination
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw,nostrictatime) /c -> /3,
mount options in (ro,nostrictatime) /e -> /5,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic rules to test the "lazytime" mount option in combination
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw,lazytime) /c -> /3,
mount options in (ro,lazytime) /e -> /5,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic rules to test the "nolazytime" mount option in combination
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw,nolazytime) /c -> /3,
mount options in (ro,nolazytime) /e -> /5,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting options with in
#=EXRESULT PASS
#
/usr/bin/foo {
mount options in (strictatime, nostrictatime) -> /foo,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting options with in
#=EXRESULT PASS
#
/usr/bin/foo {
mount options in (lazytime, nolazytime) -> /foo,
}

View File

@@ -0,0 +1,8 @@
#
#=Description basic rules to test the "nosymfollow" mount option
#=EXRESULT PASS
/usr/bin/foo {
mount options=nosymfollow /a -> /1,
mount options=(nosymfollow) /b -> /2,
mount options in (nosymfollow) /d -> /4,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic rules to test the "symfollow" mount option in combination
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw,symfollow) /c -> /3,
mount options in (ro,symfollow) /e -> /5,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic mount rule conflicting options with in
#=EXRESULT PASS
#
/usr/bin/foo {
mount options in (symfollow, nosymfollow) -> /foo,
}

View File

@@ -41,7 +41,7 @@ ifdef USE_SYSTEM
LOGPROF?=aa-logprof
else
# PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")
PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) ../libraries/libapparmor/swig/python/test/buildpath.py)
LIBAPPARMOR_PATH=../libraries/libapparmor/src/.libs/
LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)

View File

@@ -49,6 +49,8 @@
# Xcompose
owner @{HOME}/.XCompose r,
/var/cache/libx11/compose/* r,
deny /var/cache/libx11/compose/* wlk,
# mouse themes
/etc/X11/cursors/ r,

View File

@@ -34,8 +34,8 @@
/usr/share/locale-langpack/** r,
/usr/share/locale/** r,
/usr/share/**/locale/** r,
/usr/share/zoneinfo/ r,
/usr/share/zoneinfo/** r,
/usr/share/zoneinfo{,-icu}/ r,
/usr/share/zoneinfo{,-icu}/** r,
/usr/share/X11/locale/** r,
/run/systemd/journal/dev-log w,
# systemd native journal API (see sd_journal_print(4))
@@ -94,6 +94,7 @@
@{PROC}/cpuinfo r,
@{sys}/devices/system/cpu/ r,
@{sys}/devices/system/cpu/online r,
@{sys}/devices/system/cpu/possible r,
# glibc's *printf protections read the maps file
@{PROC}/@{pid}/{maps,auxv,status} r,

View File

@@ -18,7 +18,7 @@
@{system_share_dirs}/mime/** r,
# per-user configurations
owner @{HOME}/.icons/ r,
owner @{HOME}/.icons/{,**} r,
owner @{HOME}/.recently-used.xbel* rw,
owner @{HOME}/.local/share/recently-used.xbel* rw,
owner @{HOME}/.config/user-dirs.dirs r,

View File

@@ -8,6 +8,8 @@
# (src/intel/perf/gen_perf.c, load_oa_metrics())
@{PROC}/sys/dev/i915/perf_stream_paranoid r,
@{sys}/devices/pci[0-9]*/**/{revision,config} r,
# User files
owner @{HOME}/.cache/ w, # if user clears all caches
owner @{HOME}/.cache/mesa_shader_cache/ w,

View File

@@ -21,8 +21,12 @@
@{sys}/devices/system/memory/block_size_bytes r,
owner @{HOME}/.cache/nvidia/ w,
owner @{HOME}/.cache/nvidia/GLCache/ rw,
owner @{HOME}/.cache/nvidia/GLCache/** rwk,
owner @{HOME}/.nv/ w,
owner @{HOME}/.nv/GLCache/ rw,
owner @{HOME}/.nv/GLCache/** rwk,
owner @{PROC}/@{pid}/comm r, # somehwere in libnvidia-glcore.so
unix (send, receive) type=dgram peer=(addr="@nvidia[0-9a-f]*"),

View File

@@ -9,6 +9,9 @@
# ------------------------------------------------------------------
/etc/ssl/openssl.cnf r,
/etc/ssl/openssl-*.cnf r,
/etc/ssl/{engdef,engines}.d/ r,
/etc/ssl/{engdef,engines}.d/*.cnf r,
/usr/share/ssl/openssl.cnf r,
@{PROC}/sys/crypto/fips_enabled r,

View File

@@ -11,26 +11,26 @@
# ------------------------------------------------------------------
# shared snippets for config files
/etc/php{,5,7}/**/ r,
/etc/php{,5,7}/**.ini r,
/etc/php{,5,7,8}/**/ r,
/etc/php{,5,7,8}/**.ini r,
# Xlibs
/usr/X11R6/lib{,32,64}/lib*.so* mr,
# php extensions
/usr/lib{64,}/php{,5,7}/*/*.so mr,
/usr/lib{64,}/php{,5,7,8}/*/*.so mr,
# ICU (unicode support) data tables
/usr/share/icu/*/*.dat r,
# php session mmap socket
/var/lib/php{,5,7}/session_mm_* rwlk,
/var/lib/php{,5,7,8}/session_mm_* rwlk,
# file based session handler
/var/lib/php{,5,7}/sess_* rwlk,
/var/lib/php{,5,7}/sessions/* rwlk,
/var/lib/php{,5,7,8}/sess_* rwlk,
/var/lib/php{,5,7,8}/sessions/* rwlk,
# php libraries
/usr/share/php{,5,7}/ r,
/usr/share/php{,5,7}/** mr,
/usr/share/php{,5,7,8}/ r,
/usr/share/php{,5,7,8}/** mr,
# MySQL extension
/usr/share/mysql/** r,

View File

@@ -22,4 +22,4 @@
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
audit deny @{HOME}/.kde{,4}/share/apps/kmail{,2}/{,**} mrwkl,
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,

View File

@@ -10,18 +10,19 @@
#
# ------------------------------------------------------------------
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so} mr,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth} r,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/**.{pyc,so} mr,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/**.{egg,py,pth} r,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
/usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python3.{1,}[0-9]/lib-dynload/*.so mr,
# Site-wide configuration
/etc/python{2.[4-7],3.[0-9]}/** r,
/etc/python{2.[4-7],3.[0-9],3.1[0-9]}/** r,
# shared python paths
/usr/share/{pyshared,pycentral,python-support}/** r,
@@ -34,4 +35,4 @@
/usr/lib/wx/python/*.pth r,
# python build configuration and headers
/usr/include/python{2.[4-7],3.[0-9]}*/pyconfig.h r,
/usr/include/python{2.[4-7],3.[0-9],3.1[0-9]}*/pyconfig.h r,

View File

@@ -0,0 +1,42 @@
profile snap_browsers {
include if exists <abstractions/snap_browsers.d>
include <abstractions/base>
include <abstractions/dbus-session-strict>
/etc/passwd r,
/etc/nsswitch.conf r,
/etc/fstab r,
# noisy
deny owner /run/user/[0-9]*/gdm/Xauthority r, # not needed on Ubuntu
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/bin/snap mrix, # re-exec
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/info r,
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snapd r,
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snap-seccomp rPix,
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snap-confine Pix,
/var/lib/snapd/system-key r,
/run/snapd.socket rw,
@{PROC}/version r,
@{PROC}/cmdline r,
@{PROC}/sys/net/core/somaxconn r,
@{PROC}/sys/kernel/seccomp/actions_avail r,
@{PROC}/sys/kernel/random/uuid r,
owner @{PROC}/@{pid}/cgroup r,
owner @{PROC}/@{pid}/mountinfo r,
owner @{HOME}/.snap/auth.json r, # if exists, required
dbus send bus="session" path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager" member="StartTransientUnit" peer=(name="org.freedesktop.systemd1"),
dbus receive bus="session" path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager" member="JobRemoved",
/sys/kernel/security/apparmor/features/ r,
# allow launching official browser snaps.
/snap/chromium/[0-9]*/meta/{snap.yaml,hooks/} r,
/snap/firefox/[0-9]*/meta/{snap.yaml,hooks/} r,
/snap/opera/[0-9]*/meta/{snap.yaml,hooks/} r,
/var/lib/snapd/sequence/{chromium,firefox,opera}.json r,
# add other browsers here
}

View File

@@ -12,6 +12,7 @@
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
# Comment this out if using gpg plugin/addons
audit deny @{HOME}/.gnupg/{,**} mrwkl,

View File

@@ -70,6 +70,7 @@ profile sanitized_helper {
/opt/google/chrome{,-beta,-unstable}/chrome-sandbox PUxr,
/opt/google/chrome{,-beta,-unstable}/google-chrome Pixr,
/opt/google/chrome{,-beta,-unstable}/chrome Pixr,
/opt/google/chrome{,-beta,-unstable}/chrome_crashpad_handler Pixr,
/opt/google/chrome{,-beta,-unstable}/{,**/}lib*.so{,.*} m,
# Full access

View File

@@ -2,5 +2,5 @@
# video device access
# System devices
@{sys}/class/video4linux r,
@{sys}/class/video4linux/ r,
@{sys}/class/video4linux/** r,

View File

@@ -12,5 +12,6 @@
# some services update wtmp, utmp, and lastlog with per-user
# connection information
/var/log/lastlog rwk,
/var/log/wtmp wk,
/var/log/wtmp rwk,
/var/log/btmp rwk,
/{,var/}run/utmp rwk,

View File

@@ -16,7 +16,7 @@ profile lsb_release {
/dev/tty rw,
/usr/bin/lsb_release r,
/usr/bin/python3.[0-9] mr,
/usr/bin/python3.{1,}[0-9] mr,
/etc/debian_version r,
/etc/default/apport r,
@@ -28,6 +28,8 @@ profile lsb_release {
/{usr/,}bin/dash ixr,
/usr/bin/basename ixr,
/usr/bin/dpkg-query ixr,
/usr/bin/cat ixr,
/usr/bin/cut ixr,
/usr/bin/getopt ixr,
/usr/bin/sed ixr,
/usr/bin/tr ixr,

View File

@@ -52,10 +52,10 @@ profile nvidia_modprobe {
# System files
/etc/modprobe.d/{,*.conf} r,
/etc/nvidia/current/*.conf r,
/etc/nvidia/{current,legacy*,tesla*}/*.conf r,
@{sys}/module/ipmi_devintf/initstate r,
@{sys}/module/ipmi_msghandler/initstate r,
@{sys}/module/nvidia/initstate r,
@{sys}/module/{drm,nvidia}/initstate r,
@{PROC}/cmdline r,
}

View File

@@ -62,6 +62,7 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
/{var,var/run,run}/log/journal/*/*.journal r,
/{var/,}run/syslog-ng.ctl a,
/{var/,}run/syslog-ng/additional-log-sockets.conf r,
/{var,var/run,run}/log/journal/*.journal r,
# Site-specific additions and overrides. See local/README for details.
#include <local/sbin.syslog-ng>

View File

@@ -29,6 +29,8 @@ profile syslogd /{usr/,}{bin,sbin}/syslogd {
/dev/log wl,
/var/lib/*/dev/log wl,
/dev/kmsg r,
/proc/kmsg r,
/dev/tty* w,
/dev/xconsole rw,
/etc/syslog.conf r,

View File

@@ -0,0 +1,33 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2020 Michael Hirmke
# Copyright (C) 2020 Christian Boltz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# vim: ft=apparmor
#include <tunables/global>
profile dovecot-script-login /usr/lib/dovecot/script-login {
#include <abstractions/base>
#include <abstractions/dovecot-common>
#include <abstractions/nameservice>
capability setuid,
/usr/lib/dovecot/script-login mrPx,
# NOTE: You'll need to allow execution of your actual login script.
# The recommended way is to add a rule for it in local/usr.lib.dovecot.script-login
# for example
# /home/vmail/bin/postlogin.sh Px,
# and then to create the profile for the script.
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.lib.dovecot.script-login>
}

View File

@@ -18,6 +18,10 @@
capability setuid,
capability sys_chroot,
# for metrics end-point (Prometheus)
network inet stream,
network inet6 stream,
/usr/lib/dovecot/stats mr,
# Site-specific additions and overrides. See local/README for details.

View File

@@ -20,6 +20,9 @@ profile avahi-daemon /usr/{bin,sbin}/avahi-daemon {
/etc/avahi/services/ r,
/etc/avahi/services/*.service r,
@{PROC}/@{pid}/fd/ r,
@{PROC}/1/environ r,
@{PROC}/cmdline r,
@{PROC}/sys/kernel/osrelease r,
/usr/{bin,sbin}/avahi-daemon mr,
/usr/share/avahi/introspection/*.introspect r,
/usr/share/dbus-1/interfaces/org.freedesktop.Avahi.*.xml r,

View File

@@ -116,8 +116,8 @@ profile /usr/sbin/dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
/etc/libnl-3/classid r,
/usr/lib{,64}/libvirt/libvirt_leaseshelper m,
/usr/libexec/libvirt_leaseshelper m,
/usr/lib{,64}/libvirt/libvirt_leaseshelper mr,
/usr/libexec/libvirt_leaseshelper mr,
owner @{PROC}/@{pid}/net/psched r,
owner @{PROC}/@{pid}/status r,

View File

@@ -31,7 +31,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
capability sys_chroot,
capability sys_resource,
signal send set=(int,quit,term) peer=/usr/lib/dovecot/*,
signal send peer=/usr/lib/dovecot/*,
signal send peer=dovecot-*,
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
@@ -55,10 +56,12 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
/usr/lib/dovecot/managesieve-login Pxmr,
/usr/lib/dovecot/pop3 mrPx,
/usr/lib/dovecot/pop3-login Pxmr,
/usr/lib/dovecot/script-login Px,
/usr/lib/dovecot/ssl-build-param rix,
/usr/lib/dovecot/ssl-params mrPx,
/usr/lib/dovecot/stats Px,
/usr/{bin,sbin}/dovecot mrix,
/usr/share/dovecot/dh.pem r,
/usr/share/dovecot/protocols.d/ r,
/usr/share/dovecot/protocols.d/** r,
/var/lib/dovecot/ w,

View File

@@ -21,6 +21,7 @@ profile nscd /usr/{bin,sbin}/nscd {
capability setgid,
capability setuid,
/etc/machine-id r,
/etc/netgroup r,
/etc/nscd.conf r,
/usr/{bin,sbin}/nscd rmix,
@@ -38,6 +39,13 @@ profile nscd /usr/{bin,sbin}/nscd {
@{PROC}/@{pid}/fd/* r,
@{PROC}/@{pid}/mounts r,
# systemd-userdb
/{etc,run,run/host,/usr/lib}/userdb/ r,
/{etc,run,run/host,/usr/lib}/userdb/*.{user,user-privileged,group,group-privileged} r,
# needed by unscd
@{run}/systemd/notify w,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.sbin.nscd>
}

View File

@@ -6,6 +6,7 @@ profile smbd /usr/{bin,sbin}/smbd {
#include <abstractions/consoles>
#include <abstractions/cups-client>
#include <abstractions/nameservice>
#include <abstractions/openssl>
#include <abstractions/samba>
#include <abstractions/user-tmp>
#include <abstractions/wutmp>
@@ -41,6 +42,7 @@ profile smbd /usr/{bin,sbin}/smbd {
/usr/{bin,sbin}/smbldap-useradd Px,
/var/cache/samba/** rwk,
/var/{cache,lib}/samba/printing/printers.tdb mrw,
/var/lib/nscd/netgroup r,
/var/lib/samba/** rwk,
/var/lib/sss/pubconf/kdcinfo.* r,
/{,var/}run/dbus/system_bus_socket rw,

View File

@@ -43,6 +43,11 @@ profile dhclient /{usr/,}sbin/dhclient {
@{PROC}/interrupts r,
@{PROC}/@{pid}/net/dev r,
@{PROC}/rtc r,
# dhcliet wants to update its threads with functional names
# see lp1918410
owner @{PROC}/@{pid}/task/[0-9]*/comm rw,
# following rule shouldn't work, self is a symlink
@{PROC}/self/status r,
/{usr/,}sbin/arp mrix,

View File

@@ -121,6 +121,10 @@
deny /usr/share/mozilla/extensions/**/ w,
deny /usr/share/mozilla/ w,
# needed by widevine
ptrace (trace) peer=@{profile_name},
@{HOME}/.mozilla/firefox/*/gmp-widevinecdm/*/lib*so m,
# Site-specific additions and overrides. See local/README for details.
# Local path is disabled, we only enable them for profiles we promote
# out of extras.

View File

@@ -15,6 +15,7 @@
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/openssl>
#include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,

View File

@@ -30,6 +30,7 @@
/etc/hosts.allow r,
/etc/hosts.deny r,
@{PROC}/net/dev r,
@{PROC}/sys/net/ipv4/ip_local_port_range r,
/usr/sbin/dhcpd rmix,
/var/lib/dhcp/{db/,}dhcpd.leases* rwl,
/var/lib/dhcp/etc/dhcpd.conf r,

View File

@@ -69,8 +69,8 @@ endif # USE_SYSTEM
CFLAGS += -g -O0 -Wall -Wstrict-prototypes
USE_SYSCTL:=$(shell echo "#include <sys/sysctl.h>" | cpp -dM >/dev/null 2>/dev/null && echo true)
SYSCTL_INCLUDE="\#include <sys/sysctl.h>"
USE_SYSCTL:=$(shell echo $(SYSCTL_INCLUDE) | cpp -dM >/dev/null 2>/dev/null && echo true)
SRC=access.c \
at_secure.c \
@@ -307,6 +307,9 @@ unix_socket_client: unix_socket_client.c unix_socket_common.o
unix_socket: unix_socket.c unix_socket_common.o unix_socket_client
${CC} ${CFLAGS} ${LDFLAGS} $(filter-out unix_socket_client, $^) -o $@ ${LDLIBS}
mount: mount.c
${CC} ${CFLAGS} -std=gnu99 ${LDFLAGS} $^ -o $@ ${LDLIBS}
tests: all
@if [ `whoami` = "root" ] ;\
then \

View File

@@ -16,7 +16,7 @@ fi
out=$($1 -- cat /proc/self/attr/current 2>&1)
rc=$?
if [ $rc -eq 0 ] && [ "$out" == "$2" ]; then
if [ $rc -eq 0 ] && [ "$out" = "$2" ]; then
echo PASS
exit 0
elif [ $rc -ne 0 ]; then

View File

@@ -97,7 +97,7 @@ for TEST in ${TESTS} ; do
# no capabilities allowed
genprofile ${my_entries}
if [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ] ; then
if [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ] ; then
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
# capability + ptrace rule needed between pids
runchecktest "${TEST} -- no caps" pass ${my_arg}
@@ -111,9 +111,9 @@ for TEST in ${TESTS} ; do
# iterate through each of the capabilities
for cap in ${CAPABILITIES} ; do
if [ "X$(eval echo \${${TEST}_${cap}})" == "XTRUE" ] ; then
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
expected_result=pass
elif [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ]; then
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
expected_result=pass
else
expected_result=fail
@@ -126,7 +126,7 @@ for TEST in ${TESTS} ; do
# a subprofile.
settest ${testwrapper}
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} ${my_entries}
if [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ] ; then
if [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ] ; then
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
# capability + ptrace rule needed between pids
runchecktest "${TEST} changehat -- no caps" pass $bin/${TEST} ${my_arg}
@@ -139,9 +139,9 @@ for TEST in ${TESTS} ; do
runchecktest "${TEST} changehat -- all caps" pass $bin/${TEST} ${my_arg}
for cap in ${CAPABILITIES} ; do
if [ "X$(eval echo \${${TEST}_${cap}})" == "XTRUE" ] ; then
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
expected_result=pass
elif [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ]; then
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
expected_result=pass
else
expected_result=fail
@@ -156,75 +156,75 @@ cap=sys_chroot
settest syscall_chroot
# test deny keyword works
genprofile cap:${cap}:deny ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, deny keyword" fail ${syscall_chroot_args}
# test allow keyword works
genprofile cap:${cap}:allow ${syscall_chroot_extra_entries}
genprofile qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow keyword" pass ${syscall_chroot_args}
### allow/deny overlap tests ###
# test allow & deny keyword behavior, allow first
genprofile cap:${cap}:allow cap:${cap}:deny ${syscall_chroot_extra_entries}
genprofile qual=allow:cap:${cap} qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, allow first" fail ${syscall_chroot_args}
# test implicit allow & deny keyword behavior, allow first
genprofile cap:${cap} cap:${cap}:deny ${syscall_chroot_extra_entries}
genprofile cap:${cap} qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, allow first" fail ${syscall_chroot_args}
# test allow & deny keyword behavior, deny first
genprofile cap:${cap}:deny cap:${cap}:allow ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:${cap} qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, deny first" fail ${syscall_chroot_args}
# test implicit allow & deny keyword behavior, deny first
genprofile cap:${cap}:deny cap:${cap} ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:${cap} cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, deny first" fail ${syscall_chroot_args}
# test allow all & deny all capability keyword behavior, allow first
genprofile cap:ALL:allow cap:ALL:deny ${syscall_chroot_extra_entries}
genprofile qual=allow:cap:ALL qual=deny:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, allow first" fail ${syscall_chroot_args}
# test implicit allow all & deny all capability keyword behavior, allow first
genprofile cap:ALL cap:ALL:deny ${syscall_chroot_extra_entries}
genprofile cap:ALL qual=deny:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny all caps keyword, allow first" fail ${syscall_chroot_args}
# test allow all & deny all capability keyword behavior, deny first
genprofile cap:ALL:deny cap:ALL:allow ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:ALL qual=allow:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
# test implicit allow all & deny all capability keyword behavior, deny first
genprofile cap:ALL:deny cap:ALL ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:ALL cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
# test allow all & deny keywords behavior, allow first
genprofile cap:ALL:allow cap:${cap}:deny ${syscall_chroot_extra_entries}
genprofile qual=allow:cap:ALL qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, allow first" fail ${syscall_chroot_args}
# test implicit allow all & deny keywords behavior, allow first
genprofile cap:ALL cap:${cap}:deny ${syscall_chroot_extra_entries}
genprofile cap:ALL qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, allow first" fail ${syscall_chroot_args}
# test allow all & deny keywords behavior, deny first
genprofile cap:${cap}:deny cap:ALL:allow ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:${cap} qual=allow:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, deny first" fail ${syscall_chroot_args}
# test implicit allow all & deny keywords behavior, deny first
genprofile cap:${cap}:deny cap:ALL ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:${cap} cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, deny first" fail ${syscall_chroot_args}
# test allow & deny all keywords behavior, allow first
genprofile cap:${cap}:allow cap:ALL:deny ${syscall_chroot_extra_entries}
genprofile qual=allow:cap:${cap} qual=deny:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, allow first" fail ${syscall_chroot_args}
# test implicit allow & deny all keywords behavior, allow first
genprofile cap:${cap} cap:ALL:deny ${syscall_chroot_extra_entries}
genprofile cap:${cap} qual=deny:cap:ALL ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, allow first" fail ${syscall_chroot_args}
# test allow & deny all keywords behavior, deny first
genprofile cap:ALL:deny cap:${cap}:allow ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:ALL qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, deny first" fail ${syscall_chroot_args}
# test implicit allow & deny all keywords behavior, deny first
genprofile cap:ALL:deny cap:${cap} ${syscall_chroot_extra_entries}
genprofile qual=deny:cap:ALL cap:${cap} ${syscall_chroot_extra_entries}
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, deny first" fail ${syscall_chroot_args}

View File

@@ -47,7 +47,7 @@ runchecktest "NO CHANGEPROFILE (access parent file)" pass nochange $file
runchecktest "NO CHANGEPROFILE (access sub file)" fail nochange $subfile
errno=EACCES
if [ "$(kernel_features domain/stack)" == "true" ]; then
if [ "$(kernel_features domain/stack)" = "true" ]; then
# The returned errno changed in the set of kernel patches that
# introduced AppArmor profile stacking
errno=ENOENT

View File

@@ -18,7 +18,7 @@ cleancorefile()
checkcorefile()
{
# global _testdesc _pfmode _known outfile
if [ ${1:0:1} == "x" ] ; then
if [ ${1:0:1} = "x" ] ; then
requirement=${1#x}
_known=" (known problem)"
else

View File

@@ -65,7 +65,9 @@ okperm=rwl
badperm=wl
af_unix=""
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
if [ "$(kernel_features network_v8)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
af_unix="unix:create"
elif [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
af_unix="unix:create"
fi

View File

@@ -57,7 +57,7 @@ local_runchecktest()
checktestbg
if [ "$teststatus" == "pass" -a -n "$actual_confinement" -a "$actual_confinement" != "$expected_confinement" ]
if [ "$teststatus" = "pass" -a -n "$actual_confinement" -a "$actual_confinement" != "$expected_confinement" ]
then
echo "Error: ${testname} failed. Test '${_testdesc}' actual confinement '$actual_confinement' differed from expected confinement '$expected_confinement'"
testfailed

View File

@@ -43,11 +43,19 @@ stackthirdok="change_profile->:&$thirdtest"
touch $file $otherfile $sharedfile $thirdfile
if [ "$(kernel_features domain/fix_binfmt_elf_mmap)" == "true" ]; then
elfmmap="m"
else
elfmmap=""
fi
# We used to do a conditional test (below) for mmap permissions to
# address the change introduced by
# 9f834ec18defc369d73ccf9e87a2790bfa05bf46 but there are too many
# kernels in the wild with a backport/cherrypick of that commit that
# skipped cherry-picking 34c426acb75cc21bdf84685e106db0c1a3565057
# meaning the below conditional check has the wrong results for those
# kernels. Since this test is not about testing mmap just always add
# the mmap perm
#if [ "$(kernel_features domain/fix_binfmt_elf_mmap)" = "true" ]; then
# elfmmap="m"
#else
# elfmmap=""
#fi
# Verify file access and contexts by an unconfined process
runchecktest "EXEC_STACK (unconfined - file)" pass -f $file
@@ -72,7 +80,7 @@ runchecktest "EXEC_STACK (not stacked - bad mode)" fail -l "$test" -m complain
# Verify file access and contexts by 2 stacked profiles
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
image=$othertest addimage:$test $otherok $sharedok $getcon $test:r$elfmmap
image=$othertest addimage:$test $otherok $sharedok $getcon $test:rm
runchecktest_errno EACCES "EXEC_STACK (2 stacked - file)" fail -- $test -f $file
runchecktest_errno EACCES "EXEC_STACK (2 stacked - otherfile)" fail -- $test -f $otherfile
runchecktest_errno EACCES "EXEC_STACK (2 stacked - thirdfile)" fail -- $test -f $thirdfile
@@ -85,7 +93,7 @@ runchecktest "EXEC_STACK (2 stacked - bad mode)" fail -- $test -l "${test}//&${t
# Verify file access and contexts by 3 stacked profiles
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
image=$othertest addimage:$test $otherok $sharedok $getcon $test:"rix -> &$thirdtest" -- \
image=$thirdtest addimage:$test $thirdok $sharedok $getcon $test:r$elfmmap
image=$thirdtest addimage:$test $thirdok $sharedok $getcon $test:rm
runchecktest_errno EACCES "EXEC_STACK (3 stacked - file)" fail -- $test -- $test -f $file
runchecktest_errno EACCES "EXEC_STACK (3 stacked - otherfile)" fail -- $test -- $test -f $otherfile
runchecktest_errno EACCES "EXEC_STACK (3 stacked - thirdfile)" fail -- $test -- $test -f $thirdfile
@@ -95,7 +103,7 @@ runchecktest "EXEC_STACK (3 stacked - okcon)" pass -- $test -- $test -l "${third
genprofile -I $sharedok $stackotherok $stackthirdok $test:"rix -> &$othertest" -- \
image=$othertest addimage:$test $sharedok $stackthirdok $test:"rix -> &$thirdtest" -- \
image=$thirdtest addimage:$test $sharedok $stackthirdok $test:r$elfmmap
image=$thirdtest addimage:$test $sharedok $stackthirdok $test:rm
# Triggered an AppArmor WARN in the initial stacking patch set
runchecktest "EXEC_STACK (3 stacked - old AA WARN)" pass -p $othertest -- $test -p $thirdtest -f $sharedfile
@@ -126,7 +134,7 @@ runchecktest "EXEC_STACK (stacked with namespaced profile - okcon)" pass -- $tes
# Verify file access and contexts in mixed mode
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
image=$othertest flag:complain addimage:$test $otherok $sharedok $getcon $test:r$elfmmap
image=$othertest flag:complain addimage:$test $otherok $sharedok $getcon $test:rm
runchecktest "EXEC_STACK (mixed mode - file)" pass -- $test -f $file
runchecktest_errno EACCES "EXEC_STACK (mixed mode - otherfile)" fail -- $test -f $otherfile
runchecktest "EXEC_STACK (mixed mode - sharedfile)" pass -- $test -f $sharedfile

View File

@@ -13,6 +13,8 @@
# in the name.
#=END
LANG=C
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`

View File

@@ -35,10 +35,17 @@ sub usage {
print STDERR "Usage $0 [--nowarn|--escape] execname [rules]\n";
print STDERR " $0 --help\n";
print STDERR " $0 --stdin\n";
print STDERR "Options:\n";
print STDERR " nowarn: don't warn if execname does not exist\n";
print STDERR " nodefault: don't include default rules/ldd output\n";
print STDERR " escape: escape stuff that would be treated as regexs\n";
print STDERR " help: print this message\n";
print STDERR "Rule Qualifiers:\n";
print STDERR " qualifiers can optionally be added to a rule with 'qual='\n";
print STDERR " Examples:\n";
print STDERR " /path/to/file:rw\n";
print STDERR " qual=audit:/path/to/file:rw\n";
print STDERR " qual=audit,deny:/path/to/file:rw\n";
}
# genprofile passes in $bin:w as default rule atm
@@ -139,185 +146,183 @@ sub gen_binary($) {
}
}
sub gen_netdomain($) {
my $rule = shift;
sub gen_netdomain($@) {
my ($rule, $qualifier) = @_;
# only split on single ':'s
my @rules = split (/(?<!:):(?!:)/, $rule);
# convert '::' to ':' -- for port designations
foreach (@rules) { s/::/:/g; }
push (@{$output_rules{$hat}}, " @rules,\n");
push (@{$output_rules{$hat}}, " ${qualifier}@rules,\n");
}
sub gen_network($) {
my $rule = shift;
sub gen_network($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
push (@{$output_rules{$hat}}, " @rules,\n");
push (@{$output_rules{$hat}}, " ${qualifier}@rules,\n");
}
sub gen_unix($) {
my $rule = shift;
sub gen_unix($@) {
my ($rule, $qualifier) = @_;
if ($rule =~ /^unix:ALL$/) {
push (@{$output_rules{$hat}}, " unix,\n");
} else {
$rule =~ s/:/ /g;
push(@{$output_rules{$hat}}, " " . $rule . ",\n");
push(@{$output_rules{$hat}}, " " . $qualifier . $rule . ",\n");
}
}
sub gen_cap($) {
my $rule = shift;
sub gen_cap($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " capability,\n");
push (@{$output_rules{$hat}}, " ${qualifier}capability,\n");
} else {
push (@{$output_rules{$hat}}, " capability $rules[1],\n");
}
} elsif (@rules == 3) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " $rules[2] capability,\n");
} else {
push (@{$output_rules{$hat}}, " $rules[2] capability $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}capability $rules[1],\n");
}
} else {
(!$nowarn) && print STDERR "Warning: invalid capability description '$rule', ignored\n";
}
}
sub gen_ptrace($) {
my $rule = shift;
sub gen_ptrace($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " ptrace,\n");
push (@{$output_rules{$hat}}, " ${qualifier}ptrace,\n");
} else {
push (@{$output_rules{$hat}}, " ptrace $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}ptrace $rules[1],\n");
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " ptrace $rules[1] $rules[2],\n");
push (@{$output_rules{$hat}}, " ${qualifier}ptrace $rules[1] $rules[2],\n");
} else {
(!$nowarn) && print STDERR "Warning: invalid ptrace description '$rule', ignored\n";
}
}
sub gen_signal($) {
my $rule = shift;
sub gen_signal($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " signal,\n");
push (@{$output_rules{$hat}}, " ${qualifier}signal,\n");
} else {
push (@{$output_rules{$hat}}, " signal $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}signal $rules[1],\n");
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " signal $rules[1] $rules[2],\n");
push (@{$output_rules{$hat}}, " ${qualifier}signal $rules[1] $rules[2],\n");
} else {
(!$nowarn) && print STDERR "Warning: invalid signal description '$rule', ignored\n";
}
}
sub gen_mount($) {
my $rule = shift;
sub gen_mount($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " mount,\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount,\n");
} else {
push (@{$output_rules{$hat}}, " mount $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1],\n");
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2],\n");
} elsif (@rules == 4) {
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3],\n");
} elsif (@rules == 5) {
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4],\n");
} elsif (@rules == 6) {
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
} elsif (@rules == 7) {
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
} else {
(!$nowarn) && print STDERR "Warning: invalid mount description '$rule', ignored\n";
}
}
sub gen_remount($) {
my $rule = shift;
sub gen_remount($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " remount,\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount,\n");
} else {
push (@{$output_rules{$hat}}, " remount $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1],\n");
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2],\n");
} elsif (@rules == 4) {
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3],\n");
} elsif (@rules == 5) {
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4],\n");
} elsif (@rules == 6) {
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
} elsif (@rules == 7) {
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
} else {
(!$nowarn) && print STDERR "Warning: invalid remount description '$rule', ignored\n";
}
}
sub gen_umount($) {
my $rule = shift;
sub gen_umount($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " umount,\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount,\n");
} else {
push (@{$output_rules{$hat}}, " umount $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1],\n");
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2],\n");
} elsif (@rules == 4) {
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3],\n");
} elsif (@rules == 5) {
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4],\n");
} elsif (@rules == 6) {
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
} elsif (@rules == 7) {
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
} else {
(!$nowarn) && print STDERR "Warning: invalid umount description '$rule', ignored\n";
}
}
sub gen_pivot_root($) {
my $rule = shift;
sub gen_pivot_root($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " pivot_root,\n");
push (@{$output_rules{$hat}}, " ${qualifier}pivot_root,\n");
} else {
push (@{$output_rules{$hat}}, " pivot_root $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}pivot_root $rules[1],\n");
}
} else {
(!$nowarn) && print STDERR "Warning: invalid pivot_root description '$rule', ignored\n";
}
}
sub gen_file($) {
my $rule = shift;
sub gen_file($@) {
my ($rule, $qualifier) = @_;
if (!$qualifier) {
$qualifier = "";
}
my @rules = split (/:/, $rule);
# default: file rules
if (@rules == 1) {
# support raw rules
push (@{$output_rules{$hat}}, " $rules[0],\n");
push (@{$output_rules{$hat}}, " ${qualifier}$rules[0],\n");
} elsif (@rules == 2) {
if ($escape) {
$rules[0]=~ s/(["[\]{}\:])/\\$1/g;
$rules[0]=~ s/(\#)/\\043/g;
}
if ($rules[0]=~ /[\s\!\"\^]/) {
push (@{$output_rules{$hat}}, " \"$rules[0]\" $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}\"$rules[0]\" $rules[1],\n");
} else {
push (@{$output_rules{$hat}}, " $rules[0] $rules[1],\n");
push (@{$output_rules{$hat}}, " ${qualifier}$rules[0] $rules[1],\n");
}
} else {
(!$nowarn) && print STDERR "Warning: invalid file access '$rule', ignored\n";
@@ -334,33 +339,33 @@ sub gen_flag($) {
}
}
sub gen_change_profile($) {
my $rule = shift;
sub gen_change_profile($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules == 2) {
if ($rules[1] =~ /^ALL$/) {
push (@{$output_rules{$hat}}, " change_profile,\n",);
push (@{$output_rules{$hat}}, " ${qualifier}change_profile,\n",);
} else {
push (@{$output_rules{$hat}}, " change_profile -> $rules[1],\n",);
push (@{$output_rules{$hat}}, " ${qualifier}change_profile -> $rules[1],\n",);
}
} elsif (@rules == 3) {
push (@{$output_rules{$hat}}, " change_profile $rules[1] -> $rules[2],\n",);
push (@{$output_rules{$hat}}, " ${qualifier}change_profile $rules[1] -> $rules[2],\n",);
} elsif (@rules == 4) {
push (@{$output_rules{$hat}}, " change_profile $rules[1] $rules[2] -> $rules[3],\n",);
push (@{$output_rules{$hat}}, " ${qualifier}change_profile $rules[1] $rules[2] -> $rules[3],\n",);
} else {
(!$nowarn) && print STDERR "Warning: invalid change_profile description '$rule', ignored\n";
}
}
sub gen_hat($) {
my $rule = shift;
sub gen_hat($@) {
my ($rule, $qualifier) = @_;
my @rules = split (/:/, $rule);
if (@rules != 2) {
(!$nowarn) && print STDERR "Warning: invalid hat description '$rule', ignored\n";
} else {
$hat = $rules[1];
# give every profile/hat access to change_hat
@{$output_rules{$hat}} = ( " /proc/*/attr/current w,\n",);
@{$output_rules{$hat}} = ( " ${qualifier}/proc/*/attr/current w,\n",);
}
}
@@ -398,39 +403,47 @@ sub gen_from_args() {
}
for my $rule (@ARGV) {
my $qualifier = "";
if ($rule =~ /^qual=([^:]*):(.*)/) {
# Strip qualifiers from rule to pass as separate argument
$qualifier = "$1 ";
$rule = $2;
$qualifier =~ s/,/ /g;
}
#($fn, @rules) = split (/:/, $rule);
if ($rule =~ /^(tcp|udp)/) {
# netdomain rules
gen_netdomain($rule);
gen_netdomain($rule, $qualifier);
} elsif ($rule =~ /^network:/) {
gen_network($rule);
gen_network($rule, $qualifier);
} elsif ($rule =~ /^unix:/) {
gen_unix($rule);
gen_unix($rule, $qualifier);
} elsif ($rule =~ /^cap:/) {
gen_cap($rule);
gen_cap($rule, $qualifier);
} elsif ($rule =~ /^ptrace:/) {
gen_ptrace($rule);
gen_ptrace($rule, $qualifier);
} elsif ($rule =~ /^signal:/) {
gen_signal($rule);
gen_signal($rule, $qualifier);
} elsif ($rule =~ /^mount:/) {
gen_mount($rule);
gen_mount($rule, $qualifier);
} elsif ($rule =~ /^remount:/) {
gen_remount($rule);
gen_remount($rule, $qualifier);
} elsif ($rule =~ /^umount:/) {
gen_umount($rule);
gen_umount($rule, $qualifier);
} elsif ($rule =~ /^pivot_root:/) {
gen_pivot_root($rule);
gen_pivot_root($rule, $qualifier);
} elsif ($rule =~ /^flag:/) {
gen_flag($rule);
} elsif ($rule =~ /^hat:/) {
gen_hat($rule);
gen_hat($rule, $qualifier);
} elsif ($rule =~ /^change_profile:/) {
gen_change_profile($rule);
gen_change_profile($rule, $qualifier);
} elsif ($rule =~ /^addimage:/) {
gen_addimage($rule);
$addimage = 1;
} else {
gen_file($rule);
gen_file($rule, $qualifier);
}
}

View File

@@ -14,27 +14,163 @@
#include <sys/stat.h>
#include <sys/mount.h>
#include <string.h>
#include <stdlib.h>
struct mnt_keyword_table {
const char *keyword;
unsigned long set;
unsigned long clear;
};
static struct mnt_keyword_table mnt_opts_table[] = {
{ "rw", 0, MS_RDONLY }, /* read-write */
{ "ro", MS_RDONLY, 0 }, /* read-only */
{ "exec", 0, MS_NOEXEC }, /* permit execution of binaries */
{ "noexec", MS_NOEXEC, 0 }, /* don't execute binaries */
{ "suid", 0, MS_NOSUID }, /* honor suid executables */
{ "nosuid", MS_NOSUID, 0 }, /* don't honor suid executables */
{ "dev", 0, MS_NODEV }, /* interpret device files */
{ "nodev", MS_NODEV, 0 }, /* don't interpret devices */
{ "async", 0, MS_SYNCHRONOUS }, /* asynchronous I/O */
{ "sync", MS_SYNCHRONOUS, 0 }, /* synchronous I/O */
{ "loud", 0, MS_SILENT }, /* print out messages. */
{ "silent", MS_SILENT, 0 }, /* be quiet */
{ "nomand", 0, MS_MANDLOCK }, /* forbid mandatory locks on this FS */
{ "mand", MS_MANDLOCK, 0 }, /* allow mandatory locks on this FS */
{ "atime", 0, MS_NOATIME }, /* update access time */
{ "noatime", MS_NOATIME, 0 }, /* do not update access time */
{ "noiversion", 0, MS_I_VERSION }, /* don't update inode I_version time */
{ "iversion", MS_I_VERSION, 0 }, /* update inode I_version time */
{ "diratime", 0, MS_NODIRATIME }, /* update dir access times */
{ "nodiratime", MS_NODIRATIME, 0 }, /* do not update dir access times */
{ "nostrictatime", 0, MS_STRICTATIME }, /* kernel default atime */
{ "strictatime", MS_STRICTATIME, 0 }, /* strict atime semantics */
/* MS_LAZYTIME added in 4.0 kernel */
#ifdef MS_LAZYTIME
{ "nolazytime", 0, MS_LAZYTIME },
{ "lazytime", MS_LAZYTIME, 0 }, /* update {a,m,c}time on the in-memory inode only */
#endif
{ "acl", MS_POSIXACL, 0 },
{ "noacl", 0, MS_POSIXACL },
{ "norelatime", 0, MS_RELATIME },
{ "relatime", MS_RELATIME, 0 },
{ "dirsync", MS_DIRSYNC, 0 }, /* synchronous directory modifications */
{ "nodirsync", 0, MS_DIRSYNC },
/* MS_NOSYMFOLLOW added in 5.10 kernel */
#ifdef MS_NOSYMFOLLOW
{ "nosymfollow", MS_NOSYMFOLLOW, 0 },
{ "symfollow", 0, MS_NOSYMFOLLOW },
#endif
{ "bind", MS_BIND, 0 }, /* remount part of the tree elsewhere */
{ "rbind", MS_BIND | MS_REC, 0 }, /* idem, plus mounted subtrees */
{ "unbindable", MS_UNBINDABLE, 0 }, /* unbindable */
{ "runbindable", MS_UNBINDABLE | MS_REC, 0 },
{ "private", MS_PRIVATE, 0 }, /* private */
{ "rprivate", MS_PRIVATE | MS_REC, 0 },
{ "slave", MS_SLAVE, 0 }, /* slave */
{ "rslave", MS_SLAVE | MS_REC, 0 },
{ "shared", MS_SHARED, 0 }, /* shared */
{ "rshared", MS_SHARED | MS_REC, 0 },
{ "move", MS_MOVE, 0 },
{ "remount", MS_REMOUNT, 0 },
};
const unsigned int mnt_opts_table_size =
sizeof(mnt_opts_table) / sizeof(struct mnt_keyword_table);
unsigned long get_mnt_opt_bit(char *key)
{
for (unsigned int i = 0; i < mnt_opts_table_size; i++) {
if (strcmp(mnt_opts_table[i].keyword, key) == 0) {
return mnt_opts_table[i].set;
}
}
fprintf(stderr, "FAIL: invalid option\n");
exit(1);
}
static void usage(char *prog_name)
{
fprintf(stderr, "Usage: %s mount|umount <source> <target> [options]\n", prog_name);
fprintf(stderr, "Options are:\n");
fprintf(stderr, "-o flags sent to the mount syscall\n");
fprintf(stderr, "-d data sent to the mount syscall\n");
exit(1);
}
int main(int argc, char *argv[])
{
if (argc != 4) {
fprintf(stderr, "usage: %s [mount|umount] loopdev mountpoint\n",
argv[0]);
return 1;
char *options = NULL;
char *data = NULL;
int index;
int c;
char *op, *source, *target, *token;
unsigned long flags = 0;
while ((c = getopt (argc, argv, "o:d:h")) != -1) {
switch (c)
{
case 'o':
options = optarg;
break;
case 'd':
data = optarg;
break;
case 'h':
usage(argv[0]);
break;
default:
break;
}
}
if (strcmp(argv[1], "mount") == 0) {
if (mount(argv[2], argv[3], "ext2", 0xc0ed0000 | MS_NODEV, NULL ) == -1) {
index = optind;
if (argc - optind < 3) {
fprintf(stderr, "FAIL: missing positional arguments\n");
usage(argv[0]);
}
op = argv[index++];
source = argv[index++];
target = argv[index++];
if (options) {
token = strtok(options, ",");
while (token) {
flags |= get_mnt_opt_bit(token);
token = strtok(NULL, ",");
}
}
if (strcmp(op, "mount") == 0) {
if (mount(source, target, "ext2", flags, data) == -1) {
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
argv[2], argv[3],
strerror(errno));
source, target, strerror(errno));
return errno;
}
} else if (strcmp(argv[1], "umount") == 0) {
if (umount(argv[3]) == -1) {
} else if (strcmp(op, "umount") == 0) {
if (umount(target) == -1) {
fprintf(stderr, "FAIL: umount %s failed - %s\n",
argv[3],
strerror(errno));
target, strerror(errno));
return errno;
}
} else {

View File

@@ -28,9 +28,11 @@ bin=$pwd
mount_file=$tmpdir/mountfile
mount_point=$tmpdir/mountpoint
mount_point2=$tmpdir/mountpoint2
mount_bad=$tmpdir/mountbad
loop_device="unset"
fstype="ext2"
root_was_shared="no"
setup_mnt() {
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
@@ -41,6 +43,10 @@ remove_mnt() {
if [ $? -eq 0 ] ; then
/bin/umount -t${fstype} ${mount_point}
fi
mountpoint -q "${mount_point2}"
if [ $? -eq 0 ] ; then
/bin/umount -t${fstype} ${mount_point2}
fi
mountpoint -q "${mount_bad}"
if [ $? -eq 0 ] ; then
/bin/umount -t${fstype} ${mount_bad}
@@ -53,12 +59,16 @@ mount_cleanup() {
then
/sbin/losetup -d ${loop_device} &> /dev/null
fi
if [ "${root_was_shared}" = "yes" ] ; then
mount --make-shared /
fi
}
do_onexit="mount_cleanup"
dd if=/dev/zero of=${mount_file} bs=1024 count=512 2> /dev/null
/sbin/mkfs -t${fstype} -F ${mount_file} > /dev/null 2> /dev/null
/bin/mkdir ${mount_point}
/bin/mkdir ${mount_point2}
/bin/mkdir ${mount_bad}
# in a modular udev world, the devices won't exist until the loopback
@@ -71,6 +81,195 @@ fi
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
# systemd mounts / and everything under it MS_SHARED which does
# not work with "move", so attempt to detect it, and remount /
# MS_PRIVATE temporarily. snippet from pivot_root.sh
FINDMNT=/bin/findmnt
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
if [ "$(${FINDMNT} -no PROPAGATION /)" == "shared" ] ; then
root_was_shared="yes"
fi
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
# no findmnt or findmnt doesn't know the PROPAGATION column,
# but init is systemd so assume rootfs is shared
root_was_shared="yes"
fi
if [ "${root_was_shared}" = "yes" ] ; then
mount --make-private /
fi
options=(
# default and non-default options
"rw,ro"
"exec,noexec"
"suid,nosuid"
"dev,nodev"
"async,sync"
"loud,silent"
"nomand,mand"
"atime,noatime"
"noiversion,iversion"
"diratime,nodiratime"
"nostrictatime,strictatime"
"norelatime,relatime"
"nodirsync,dirsync"
"noacl,acl"
)
# Options added in newer kernels
new_options=(
"nolazytime,lazytime"
"symfollow,nosymfollow"
)
prop_options=(
"unbindable"
"runbindable"
"private"
"rprivate"
"slave"
"rslave"
"shared"
"rshared"
)
combinations=()
setup_all_combinations() {
n=${#options[@]}
for (( i = 1; i < (1 << n); i++ )); do
list=()
for (( j = 0; j < n; j++ )); do
if (( (1 << j) & i )); then
current_options="${options[j]}"
nondefault=${current_options#*,}
list+=("$nondefault")
fi
done
combination=$(IFS=,; printf "%s" "${list[*]}")
combinations+=($combination)
done
}
run_all_combinations_test() {
for combination in "${combinations[@]}"; do
if [ "$(parser_supports "mount options=($combination),")" = "true" ] ; then
genprofile cap:sys_admin "mount:options=($combination)"
runchecktest "MOUNT (confined cap mount combination pass test $combination)" pass mount ${loop_device} ${mount_point} -o $combination
remove_mnt
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($combination)"
runchecktest "MOUNT (confined cap mount combination deny test $combination)" fail mount ${loop_device} ${mount_point} -o $combination
remove_mnt
else
echo " not supported by parser - skipping mount option=($combination),"
fi
genprofile cap:sys_admin "mount:options=(rw)"
runchecktest "MOUNT (confined cap mount combination fail test $combination)" fail mount ${loop_device} ${mount_point} -o $combination
remove_mnt
done
}
test_nonfs_options() {
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
echo " not supported by parser - skipping mount options=($1),"
return
fi
genprofile cap:sys_admin "mount:options=($1)"
runchecktest "MOUNT (confined cap mount $1)" pass mount ${loop_device} ${mount_point} -o $1
remove_mnt
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
runchecktest "MOUNT (confined cap mount deny $1)" fail mount ${loop_device} ${mount_point} -o $1
remove_mnt
genprofile cap:sys_admin "mount:options=($1)"
runchecktest "MOUNT (confined cap mount bad option $2)" fail mount ${loop_device} ${mount_point} -o $2
remove_mnt
}
test_dir_options() {
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
echo " not supported by parser - skipping mount option=($1),"
return
fi
genprofile cap:sys_admin "mount:ALL"
runchecktest "MOUNT (confined cap mount dir setup $1)" pass mount ${loop_device} ${mount_point}
genprofile cap:sys_admin "mount:options=($1)"
runchecktest "MOUNT (confined cap mount dir $1)" pass mount ${mount_point} ${mount_point2} -o $1
remove_mnt
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
runchecktest "MOUNT (confined cap mount dir setup 2 $1)" pass mount ${loop_device} ${mount_point}
runchecktest "MOUNT (confined cap mount dir deny $1)" fail mount ${mount_point} ${mount_point2} -o $1
remove_mnt
}
test_propagation_options() {
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
echo " not supported by parser - skipping mount option=($1),"
return
fi
genprofile cap:sys_admin "mount:ALL"
runchecktest "MOUNT (confined cap mount propagation setup $1)" pass mount ${loop_device} ${mount_point}
genprofile cap:sys_admin "mount:options=($1)"
runchecktest "MOUNT (confined cap mount propagation $1)" pass mount none ${mount_point} -o $1
remove_mnt
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
runchecktest "MOUNT (confined cap mount propagation deny setup 2 $1)" pass mount ${loop_device} ${mount_point}
runchecktest "MOUNT (confined cap mount propagation deny $1)" fail mount none ${mount_point} -o $1
remove_mnt
}
test_remount() {
# setup by mounting first
genprofile cap:sys_admin "mount:ALL"
runchecktest "MOUNT (confined cap mount remount setup)" pass mount ${loop_device} ${mount_point}
genprofile cap:sys_admin "mount:options=(remount)"
runchecktest "MOUNT (confined cap mount remount option)" pass mount ${loop_device} ${mount_point} -o remount
genprofile cap:sys_admin "remount:ALL"
runchecktest "MOUNT (confined cap mount remount)" pass mount ${loop_device} ${mount_point} -o remount
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=(remount)"
runchecktest "MOUNT (confined cap mount remount deny option)" fail mount ${loop_device} ${mount_point} -o remount
genprofile cap:sys_admin "qual=deny:remount:ALL"
runchecktest "MOUNT (confined cap mount remount deny)" fail mount ${loop_device} ${mount_point} -o remount
# TODO: add test for remount options
remove_mnt
}
test_options() {
for i in "${options[@]}"; do
default="${i%,*}"
nondefault="${i#*,}"
test_nonfs_options $default $nondefault
test_nonfs_options $nondefault $default
done
for i in "bind" "rbind" "move"; do
test_dir_options $i
done
for i in "${prop_options[@]}"; do
test_propagation_options $i
done
test_remount
# the following combinations tests take a long time to complete
# setup_all_combinations
# run_all_combinations_test
}
# TEST 1. Make sure can mount and umount unconfined
runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point}
@@ -80,6 +279,43 @@ setup_mnt
runchecktest "UMOUNT (unconfined)" pass umount ${loop_device} ${mount_point}
remove_mnt
# Check mount options that may not be available on this kernel
for i in "${new_options[@]}"; do
default="${i%,*}"
if "$bin/mount" mount ${loop_device} ${mount_point} -o $default > /dev/null 2>&1; then
remove_mnt
options+=($i)
else
echo " not supported by kernel - skipping mount options=($i),"
fi
done
for i in "${options[@]}"; do
default="${i%,*}"
nondefault="${i#*,}"
runchecktest "MOUNT (unconfined mount $default)" pass mount ${loop_device} ${mount_point} -o $default
remove_mnt
runchecktest "MOUNT (unconfined mount $nondefault)" pass mount ${loop_device} ${mount_point} -o $nondefault
remove_mnt
done
for i in "bind" "rbind" "move"; do
runchecktest "MOUNT (unconfined mount setup $i)" pass mount ${loop_device} ${mount_point}
runchecktest "MOUNT (unconfined mount $i)" pass mount ${mount_point} ${mount_point2} -o $i
remove_mnt
done
for i in "${prop_options[@]}"; do
runchecktest "MOUNT (unconfined mount dir setup $i)" pass mount ${loop_device} ${mount_point}
runchecktest "MOUNT (unconfined mount dir $i)" pass mount none ${mount_point} -o $i
remove_mnt
done
runchecktest "MOUNT (unconfined mount remount setup)" pass mount ${loop_device} ${mount_point}
runchecktest "MOUNT (unconfined mount remount)" pass mount ${loop_device} ${mount_point} -o remount
remove_mnt
# TEST A2. confine MOUNT no perms
genprofile
runchecktest "MOUNT (confined no perm)" fail mount ${loop_device} ${mount_point}
@@ -91,6 +327,7 @@ remove_mnt
if [ "$(kernel_features mount)" != "true" -o "$(parser_supports 'mount,')" != "true" ] ; then
echo " mount rules not supported, using capability check ..."
genprofile capability:sys_admin
runchecktest "MOUNT (confined cap)" pass mount ${loop_device} ${mount_point}
remove_mnt
@@ -157,6 +394,7 @@ else
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
remove_mnt
test_options
fi
#need tests for move mount, remount, bind mount, chroot
#need tests for chroot

View File

@@ -38,7 +38,7 @@ badchild=r
# Add genprofile params that are common to all hats here
common=""
if [ "$(kernel_features signal)" == "true" -a "$(parser_supports 'signal,')" == "true" ] ; then
if [ "$(kernel_features signal)" = "true" -a "$(parser_supports 'signal,')" = "true" ] ; then
# Allow send/receive of all signals
common="${common} signal:ALL"
fi

View File

@@ -44,7 +44,7 @@ do_test()
shift 4
desc="ONEXEC $desc ($prof -> $target_prof)"
if [ "$target_prof" == "nochange" ] ; then
if [ "$target_prof" = "nochange" ] ; then
runchecktest "$desc" $res -l "$prof" -- "$@"
else
runchecktest "$desc" $res -O "$target_prof" -l "$prof" -L "$target_prof" -- "$@"

View File

@@ -50,7 +50,7 @@ do_onexit="pivot_root_cleanup"
# MS_PRIVATE temporarily.
FINDMNT=/bin/findmnt
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
if [ "$(${FINDMNT} -no PROPAGATION /)" == "shared" ] ; then
if [ "$(${FINDMNT} -no PROPAGATION /)" = "shared" ] ; then
root_was_shared="yes"
fi
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then

View File

@@ -86,6 +86,19 @@ requires_kernel_features()
fi
}
requires_any_of_kernel_features()
{
while [ $# -gt 0 ]; do
local res=$(kernel_features "$1")
if [ "$res" = "true" ] ; then
return 0;
fi
shift
done
echo "$res. Skipping tests ..."
exit 0
}
# requires_namespace_interface() - exit if namespace interface is not available
requires_namespace_interface()
{

View File

@@ -55,7 +55,7 @@ runchecktest "test 2 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 2 -hc prog" pass -h -c -n 100 $helper ${bin_true}
if [ "$(kernel_features ptrace)" == "true" -a "$(parser_supports 'ptrace,')" == "true" ] ; then
if [ "$(kernel_features ptrace)" = "true" -a "$(parser_supports 'ptrace,')" = "true" ] ; then
. $bin/ptrace_v6.inc
else
. $bin/ptrace_v5.inc

View File

@@ -93,7 +93,7 @@ querytest()
runchecktest "$desc" "$pf" "$expect" "$label" "$perms" $*
}
if [ "$(kernel_features dbus)" == "true" ]; then
if [ "$(kernel_features dbus)" = "true" ]; then
# Check querying of a label that the kernel doesn't know about
# aa_query_label() should return an error
expect anything
@@ -217,7 +217,7 @@ fi
genqueryprofile "file,"
expect allow
perms file exec,write,read,append,create,delete,setattr,getattr,chmod,chown,link,linksubset,lock,exec_mmap
if [ "$(kernel_features query/label/multi_transaction)" == "true" ] ; then
if [ "$(kernel_features query/label/multi_transaction)" = "true" ] ; then
querytest "QUERY file (all base perms #1)" pass /anything
querytest "QUERY file (all base perms #2)" pass /everything
else

View File

@@ -37,7 +37,7 @@ af_unix_create_label=""
af_unix_inherit=""
aa_enabled="/sys/module/apparmor/parameters/enabled:r"
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
if [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
# AppArmor requires that the process inheriting the sock file
# descriptors have send,receive perms in its profile
af_unix_create="unix:(create,getopt)"

View File

@@ -29,7 +29,7 @@ bin=$pwd
# check if we can run the test at all
fstype=$(stat -f --format '%T' "${tmpdir}")
if [ "${fstype}" == "tmpfs" ] ; then
if [ "${fstype}" = "tmpfs" ] ; then
echo "ERROR: tmpdir '${tmpdir}' is of type tmpfs; can't mount a swapfile on it" 1>&2
echo "ERROR: skipping swap tests" 1>&2
num_testfailures=1

View File

@@ -27,7 +27,9 @@ okperm=rw
badperm=w
af_unix=""
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
if [ "$(kernel_features network_v8)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
af_unix="unix:create"
elif [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
af_unix="unix:create"
fi
@@ -137,7 +139,7 @@ runchecktest "fd passing; confined -> confined (no perm)" fail $file $socket $fd
sleep 1
rm -f ${socket}
if [ "$(kernel_features policy/network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ] ; then
if [ "$(kernel_features policy/network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ] ; then
# FAIL - confined client, no access to the socket file
genprofile $file:$okperm $af_unix $socket:rw $fd_client:px -- image=$fd_client $file:$okperm $af_unix

View File

@@ -29,7 +29,7 @@ bin=$pwd
. $bin/prologue.inc
requires_kernel_features policy/versions/v6
#af_mask for downgrade test af_unix for full test
requires_kernel_features network/af_mask
requires_any_of_kernel_features network/af_mask network_v8/af_mask
settest unix_socket
@@ -43,9 +43,9 @@ message=4a0c83d87aaa7afa2baab5df3ee4df630f0046d5bfb7a3080c550b721f401b3b\
okserver=w
badserver1=r
badserver2=
if [ "$(kernel_features policy/versions/v7)" == "true" ] ; then
if [ "$(kernel_features policy/versions/v7)" = "true" ] ; then
okserver=rw
badserver2=w
# badserver2=w
fi
# af_unix support requires 'unix create' to call socket()
@@ -54,9 +54,16 @@ fi
# af_unix support requires 'unix getattr' to call getsockname()
af_unix_okserver=
af_unix_okclient=
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ] ; then
if ( [ "$(kernel_features network_v8/af_unix)" = "true" ] ||
[ "$(kernel_features network/af_unix)" = "true" ] ) &&
[ "$(parser_supports 'unix,')" = "true" ] ; then
af_unix_okserver="create,setopt"
af_unix_okclient="create,getopt,setopt,getattr"
elif [ "$(kernel_features network_v8)" = "true" ] ; then
# af_unix_okserver="create,setopt"
# af_unix_okclient="create,getopt,setopt,getattr"
af_unix_okserver="create"
af_unix_okclient="create"
fi
okclient=rw
@@ -88,7 +95,7 @@ testsocktype()
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1373176
# get resolved
local ex_result="pass"
if [ "${socktype}" == "dgram" ] ; then
if [ "${socktype}" = "dgram" ] ; then
ex_result="xpass"
fi

View File

@@ -72,20 +72,14 @@ if args.json:
aaui.set_json_mode()
profiling = args.program
profiledir = args.dir
apparmor.init_aa()
apparmor.init_aa(profiledir=args.dir)
apparmor.set_logfile(args.file)
aa_mountpoint = apparmor.check_for_apparmor()
if not aa_mountpoint:
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
if profiledir:
apparmor.profile_dir = apparmor.get_full_path(profiledir)
if not os.path.isdir(apparmor.profile_dir):
raise apparmor.AppArmorException(_("%s is not a directory.") %profiledir)
program = None
#if os.path.exists(apparmor.which(profiling.strip())):
if os.path.exists(profiling):

Some files were not shown because too many files have changed in this diff Show More