2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-01 23:05:11 +00:00

Compare commits

...

145 Commits

Author SHA1 Message Date
John Johansen
8d9a061a45 Prepare for 4.1.0~beta3 release
- bump version

Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 02:47:26 -08:00
John Johansen
94ea0f00b1 Merge parser: convert uint to unsigned int
As reported in https://gitlab.com/apparmor/apparmor/-/merge_requests/1475
uint requires the inclusion of sys/types.h for use in musl libc.
Including that would be fine but since it is only used for the
cast for the owner type comparison, just convert to use a more
standard type.

Reported-by: @fossd <fossdd@pwned.life>
Signed-off-by: John Johansen <john.johansen@canonical.com>

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

(cherry picked from commit cd8b75abc0)
2025-01-09 02:46:06 -08:00
John Johansen
99e919c288 parser: convert uint to unsigned int
As reported in https://gitlab.com/apparmor/apparmor/-/merge_requests/1475
uint requires the inclusion of sys/types.h for use in musl libc.
Including that would be fine but since it is only used for the
cast for the owner type comparison, just convert to use a more
standard type.

Reported-by: @fossd <fossdd@pwned.life>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ff03702fde)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 02:46:06 -08:00
John Johansen
d805b5c3f8 Merge cupsd: Add /etc/paperspecs and convert to @etc_ro/rw
I had this message in my log

```
Dez 30 08:14:46 kernel: audit: type=1400 audit(1735542886.787:307): apparmor="DENIED" operation="open" class="file" profile="/usr/sbin/cupsd" name="/etc/paperspecs" pid=317509 comm="cupsd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
```

If the second commit is bad, I can drop it.

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

(cherry picked from commit e5a960a685)
2025-01-09 02:26:24 -08:00
Jörg Sommer
2aa7fe4659 cupsd: convert profile to @etc_ro/rw
While cups itself writes to /etc the others require only read-only access
and might therefore live in /usr/etc.

(cherry picked from commit c3af6228fd)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 02:26:24 -08:00
Jörg Sommer
c456101ebb cupsd: Add /etc/paperspecs read access
Cups uses libpaper which accesses /etc/paperspecs.

ce42216e2e/lib/libpaper.c.in.in (L419)
(cherry picked from commit 97d7fa3f5f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 02:26:24 -08:00
John Johansen
9875ba19ef Merge Allow write access to /run/user/*/dconf/user
Gtk applications like Firefox request write access to the file
`/run/user/1000/dconf/user`. The code in `dconf_shm_open` opens the file
with `O_RDWR | O_CREAT`.

4057f8c84f/shm/dconf-shm.c (L68)

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

(cherry picked from commit 0eca26c6c2)
2025-01-09 02:26:07 -08:00
Jörg Sommer
ab15e29654 Allow write access to /run/user/*/dconf/user
Gtk applications like Firefox request write access to the file
`/run/user/1000/dconf/user`. The code in `dconf_shm_open` opens the file
with `O_RDWR | O_CREAT`.

4057f8c84f/shm/dconf-shm.c (L68)
(cherry picked from commit 318fb30446)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 02:26:07 -08:00
John Johansen
320a2a5155 Merge parser: fix priority for file rules.
Fix priority for file rules, and the ability to dump the dfa at different stages, and update and fix the equality tests.

This in particular adds the ability to better debug the equality tests. Instead of just piping the parser output into the hash it creates a tmp dir and drops the binary files there so they can be manually examined. It adds new options particularly the -r option making so the tests will exit on first failure to make it easier to isolate and examine a failure.

Eg.
```
./equality.sh -r -d -v
Equality Tests:
................................................................................................................................................................................................................................
Binary inequality 'priority=-1'x'priority=-1' change_hat rules automatically inserted
FAIL: Hash values match
parser: ./../apparmor_parser -QKSq --features-file=./features_files/features.all
known-good (ee4f926922ecd341f1389a79dd155879) == profile-under-test (ee4f926922ecd341f1389a79dd155879) for the following profiles:
known-good         /t { priority=-1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { priority=-1 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}
profile-under-test /t { priority=-1 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { priority=-1 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}

  files retained in "/tmp/eq.3240859-deHu10/"
```

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

(cherry picked from commit 40e9b2a961)
2025-01-09 01:44:18 -08:00
John Johansen
00dc6794f5 parser: equality tests: convert to using sha256sum for the hashes
There is a general industry wide effort to move off of md5 and even
sha1 (see recent kernel changes). While in this particular use case it
doesn't make a difference (besides slightly lowering the chance of a
collision) switch to sha256sum to make sure our code doesn't depend on
tools that are deprecated and there is an effort to remove.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 027b508da8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
958a77a2db parser: equality tests: fix r carve out tests
Similar to the deny x permission tests, the tests that test carving
out r permissions need to be updated to be conditional on what
priority is being used on the rule.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit bf7b80c478)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
b4aa2cfde4 parser: equality tests: update deny x perm carve out test
With priority rules, deny does not carve out permissions from the
higher priority rule. Technically it doesn't from lower priority either
as it completely overrides them, but that case already results in
an inequality so does not cause the tests to fail.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 25f16b239d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
86273b746a parser: equality tests: fix cx specified profile transition
cx rules using a specified profile transition, may be emulated by
using px and a hierarchical profile name. That is

  cx -> b

may be transformed into

  px -> profile//b

which will generate an xtable entry of

  profile//b

which means the previous patch using

  pivot_root -> b,

to reliably add b to the xtable will not cover this case.

transition to using two pivot_root rules to provide the xtable entries
  pivot_root /a -> b,
  pivot_root /c -> /t//b,

the paths /a and /c are irrelavent as long as they don't have an
overlap with the generic globbing expression in the test, Two table
entries will be generated. We guarantee no overlap by converting the

  /** to /f**

Also the xtable reserving rules are moved to the end of the profile so
the table order can be reliably created. A follow on MR around xtable
improvements should add reliability to xtable order.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 369029dc07)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
6a26d1f58c parser: equality tests: fix equality failure due to xtable
exec rules that specify an specific target profile generate an entry
in the xtable. The test entries containing " -> b" are an example of
this.

Currently the parser allocates the xtable entry before priorities are
applied in the backend, or minimization is done. Further more the
parser does not ref count the xtable entry to know what it is no
longer referenced.

The equality tests generate rules that are designed to completely
override and remove a lower priority rule, and remove it. Eg.

  /t { priority=1 /* ux, /f px -> b, }

and then compares the generated profile to the functionaly equivalent
profile eg.

  /t { priority=1 /* ux, }

To verify the overridden rule has been completely removed.
Unfortunately the compilation is not removing the unused xtable entry
for the specified transition, causing the equality comparison to fail.

Ideally the parser should be fixed so unused xtable entries are removed,
but that should be done in a different MR, and have its own test.

To fix the current tests, and another rule that adds an xtable entry
to the same target that can not be overriden by the x rule using
pivot_root. The parser will dedup the xtable entry resulting in the
known and test profile both having the same xtable. So the test will
pass and meet the original goal of verifying the x rule being overriden
and eliminated.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 84650beb2f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
17d3545d07 parser: equality tests: rework and add debug features
Failed equality tests can be hard to debug. The profiles aren't always
enough to figure out what is going on. Add several options that will
help in debugging, and developing new tests.

Add switches and arg parsing.

Add the ability to run tests individually

Add a -r flag to allow retaining the test and output
similar to the regression tests, so the exact output from the
tests can be examined.

Add a -d flag to dump dfa build information.

Allow overriding the parser, features, and description for a given
test run.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit cca842b897)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
640c3dde26 parser: equality tests: wrap test run in function
In preparation for some additional abilities wrap the current tests in
a function.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 05ddc61246)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
380a5c8a72 parser: equality tests: consitently dump error output to stderr
printf of failure/error info should be going to stderr. Unfortunately
the test has a mix of 2>&1 and 1>&2. Having a mix is just wrong, we
could standardize on either but since the info is error info 1>&2
seems to be the better choice.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 31e60baab2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
f26f577742 parser: equality tests: fix failing overlapping x rule tests
The test was passing because the file priority was always zero bug
resulting in the priority rule always being correctly combined
with the specific match x rule, instead of overriding it.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 57c57f198c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
2700e58755 parser: equality tests: fix change_hat priority test
The test was passing because the file priority always being zero bug,
the supplied rule always had the same priority as the implied
rule. Resulting in binary_equality always passing even though the
specified priority should have resulted in a failure.

Fix this by checking if the priorities are equal to the implied
rule other wise it should result in an inequality.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 4b410b67f1)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
427a895288 parser: equality tests: output parser, config and features info
When there is a failure output the exact call info used to invoke the
parser. To facilitate manually recreating the test.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit d275dfdd42)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
dc0a9dc599 parser: equality tests: convert xequality tests to equality
With the file priority fix the xequality (expected equal but known
failure) tests are now passing. So convert them to regular equality
tests.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit fcee32a37e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
74219b34dc parser: add some new dfa dump options.
The dfa goes through several stages during the build. Allow dumping it
at the various stages instead of only at the end.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 5d2a38e816)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
5aaa45e4ce parser: fix priority for file rules.
File rules could drop priority info when rule matched a rule
that was the same except for having different priority. For now
fix this by treating them as a different rule.

The priority was also be dropped when add_prefix was used to
add the priority during the parse resulting in file rules always
getting a default priority of 0.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 9d5b86bc9d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:44:18 -08:00
John Johansen
0c02c8afe1 Merge Allow python cache under the @{HOME}/.cache/ dir
Starting with Python 3.8, you can use the PYTHONPYCACHEPREFIX environment
variable to define a cache directory for Python [1]. I think most people would set
this dir to @{HOME}/.cache/python/ , so the python abstraction should allow
writing to this location.

[1]: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPYCACHEPREFIX

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

(cherry picked from commit 8c799f4eec)
2025-01-09 01:43:42 -08:00
Mikhail Morfikov
70ed8d6f38 Allow python cache under the @{HOME}/.cache/ dir
Starting with Python 3.8, you can use the PYTHONPYCACHEPREFIX environment
variable to define a cache directory for Python [1]. I think most people would set
this dir to @{HOME}/.cache/python/ , so the python abstraction should allow
writing to this location.

[1]: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPYCACHEPREFIX

(cherry picked from commit 03b5a29b05)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:43:42 -08:00
John Johansen
5751614928 Merge regression tests: make loop device size more generous
Depending on the system, copying echo to the loop device fails because the echo binary is too large.
Especially on systems that have echo be just a symlink to coreutils (e.g. busybox) (as opposed to echo being its own binary) 16k is just not enough.
2M seems fine on my system, but this might need yet a higher value depending on what coreutils other people actually run.

The crash in question:
```
cp: error writing '/tmp/sdtest.3937422-31490-Bxvi6g/mount_target/echo': No space left on device
Fatal Error (file_unbindable_mount): Unexpected shell error. Run with -x to debug
rm: cannot remove '/tmp/sdtest.3937422-31490-Bxvi6g/mount_target': Device or resource busy
```

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

(cherry picked from commit 8e431ebcd9)
2025-01-09 01:43:11 -08:00
Grimmauld
73842b54f7 regression tests: make loop device size more generous
Depending on the system, copying echo to the loop device fails because the echo binary is too large.
Especially on systems that have echo be just a symlink to coreutils (e.g. busybox) 16k is just not enough.
2M seems fine on my system, but this might need yet a higher value depending on what coreutils other people actually run.
The actual loop device needs to be larger to properly fit the allocated file size. Testing shows 4M is sufficient, but this is basically arbitrary.

(cherry picked from commit 1cc2a3bd86)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:43:11 -08:00
John Johansen
54f1cf8dca Merge Write a regression test for mediating file access in private mounts
This test, as is, emits an execname warning which is due to a bug in the `prologue.inc` infrastructure (see !1450 for a fix to this issue).

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit ba60bfff85)
2025-01-09 01:42:41 -08:00
Ryan Lee
2de3b84de2 Shellcheck fix pass over file_unbindable_mount test
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit fa58d3611a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:41 -08:00
Ryan Lee
9fc848be81 Add file_unbindable_mount to regression task.yaml
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit c768a7dc79)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:41 -08:00
Ryan Lee
fefbf514f7 Add file_unbindable_mount to regression test Makefile
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 049b35dff0)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:41 -08:00
Ryan Lee
ae0c588acb Write a regression test for mediating file access in unbindable mounts
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit f249c6d58f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:41 -08:00
John Johansen
0af8c5e26f Merge aa-status: fix json generation
- previously, aa-status --json --show profiles would return non-standard json
- adding the --pretty flag would crash completely
- closes #470

Things done:
- removed trailing ", " in json generation
- generate json seperator (", ") for each new json field
  (profiles/processes) after the header if json is enabled

Tested on NixOS and apparmor 4.0.3 base, but should work on any version the patch applies on.

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

(cherry picked from commit c489631770)
2025-01-09 01:42:18 -08:00
Grimmauld
f4deae6759 aa-status: fix json output with --count flag
(cherry picked from commit 9967ba9873)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:18 -08:00
Grimmauld
0691cfcf3c aa-status: fix json generation
- previously, aa-status --json --show profiles would return non-standard json
- adding the --pretty flag would crash completely
- closes #470

Things done:
- removed trailing ", " in json generation
- generate json seperator (", ") for each new json field
  (profiles/processes) after the header if json is enabled

Tested on NixOS and apparmor 4.0.3 base, but should work on any version the patch applies on.

(cherry picked from commit 4f006a660c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:18 -08:00
John Johansen
760ddaeb80 Merge fixes on the testing infrastructure
This MR is meant to resolve warnings such as "Warning: execname '/home/username/Documents/apparmor/tests/regression/apparmor/file_unbindable_mount': no such file or directory" when running tests like the one in the current version of !1448.

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

(cherry picked from commit 59957aa1d8)
2025-01-09 01:42:03 -08:00
Georgia Garcia
4e46df38cf tests: fix profile name when wrapper is specified
When settest was called with two parameters, one for the test name and
the other for the test wrapper/binary, the profile created with
genprofile would show the test name, causing an error if the file
didn't exist.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit b4adff2ce0)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:03 -08:00
Georgia Garcia
e9858c0c43 tests: add option to append a profile to a profile already generated
Some of the tests using the --stdin option of mkprofile.pl are adding
more than one profile at a time. Whenever a profile is created in the
test, its name is added to the file profile.names so the test
infrastructure can tell if the profile is loaded or removed when
appropriately. The issue is that the name of the second profile
created by --stdin is not added, so these checks are not applied.

This patch adds the option of appending a second profile (not rules).
The option --append was used instead of a short -A because the short
options are arguments of mkprofile.pl, which --append is not.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 0307619ed9)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:03 -08:00
Georgia Garcia
0e59b99623 tests: remove outdated restriction on image name specification
Due to how the tests were implemented in the past, permissions could
be passed along with the image name, and the permission part would be
discarded. The issue is that permissions are usually separated by ':',
but namespaces also contain ':', which would cause a conflict.

Since permissions are no longer passed as part of the image name,
remove that description so profile names in namespaces can be
supported.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 9cc40e2dca)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:42:03 -08:00
John Johansen
9a2f0ff702 Merge profiles: transmission-gtk needs attach_disconnected
From LP: #2085377, when using ip netns to torrent traffic through a
VPN, attach_disconnected is needed by the policy because ip netns sets
up a mount namespace.

Fixes: https://bugs.launchpad.net/bugs/2085377
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

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

(cherry picked from commit 50f260df51)
2025-01-09 01:41:36 -08:00
Georgia Garcia
c153a6916f profiles: transmission-gtk needs attach_disconnected
From LP: #2085377, when using ip netns to torrent traffic through a
VPN, attach_disconnected is needed by the policy because ip netns sets
up a mount namespace.

Fixes: https://bugs.launchpad.net/bugs/2085377
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit f9edc7d4c1)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:41:35 -08:00
John Johansen
2316ad42d4 Merge Allow make-* flags with remount operations
While the mount syscall documentation disallows this, the kernel silently
ignores make-* flags when doing a remount, and real applications were
passing this conflicting set of flags. Because changing the kernel to
reject this combination would break userspace, we should allow them
instead.

For an example: see https://bugs.launchpad.net/apparmor/+bug/2091424.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit 3ed5adb665)
2025-01-09 01:41:22 -08:00
Ryan Lee
e46ca918a2 Add a regression test for allowing rprivate with conflicting options
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 83270fcf68)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:41:22 -08:00
Ryan Lee
610d383de2 Allow make-* flags with remount operations
While the mount syscall documentation disallows this, the kernel silently
ignores make-* flags when doing a remount, and real applications were
passing this conflicting set of flags. Because changing the kernel to
reject this combination would break userspace, we should allow them
instead.

For an example: see https://bugs.launchpad.net/apparmor/+bug/2091424.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 52babe8054)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:41:22 -08:00
John Johansen
5ae6f202f8 Merge Add separator between mount flags in dump_flags
The previous code would concatenate all of them together without spacing.
While dump_flags and the corresponding operator<< function aren't currently used,
this will help for when dump_flags is used to debug parser problems.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1465
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit 67ee5f8b39)
2025-01-09 01:40:41 -08:00
Ryan Lee
d96d69a60c Add separator between mount flags in dump_flags
The previous code would concatenate all of them together without spacing.
While dump_flags and the corresponding operator<< function aren't currently used,
this will help for when dump_flags is used to debug parser problems.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 96718ea4d1)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:40:41 -08:00
John Johansen
164526d16a Merge Update fs type comment in swap regression test
As per https://gitlab.com/apparmor/apparmor/-/merge_requests/1463#note_2259888640: this really should have been a part of !1463, except that cboltz only pointed this out after the MR was already merged. Better late than never, nevertheless.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit f2c398405b)
2025-01-09 01:39:20 -08:00
Ryan Lee
5267a7eb14 Update fs type comment in swap regression test
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 5cd3362a81)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:39:20 -08:00
John Johansen
fd24c230c9 Merge Fix swap regression test on btrfs
As per !1462 it turns out that the swap regression test on btrfs also needs special casing in order to work properly. This is an analogous patch to check for btrfs.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1463
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit 6d7b5df947)
2025-01-09 01:39:00 -08:00
Ryan Lee
14933dc768 Fix swap regression test on btrfs
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 90c7af69c5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:39:00 -08:00
John Johansen
9bf91bbe40 Merge fix swap test on zfs file system
Swap on ZFS is *weird*. Getting it working needs some special casing, see e.g. https://askubuntu.com/questions/1198903/can-not-use-swap-file-on-zfs-files-with-holes

Currently, the swap regression test fails on my system (with /tmp in zfs):
```bash
tests/regression/apparmor ❯ ./swap.sh
Error: swap failed. Test 'SWAPON (unconfined)' was expected to 'pass'. Reason for failure 'FAIL: swapon /tmp/sdtest.872368-19048-kN4FN2/swapfile failed - Invalid argument'
Error: swap failed. Test 'SWAPOFF (unconfined)' was expected to 'pass'. Reason for failure 'FAIL: swapoff /tmp/sdtest.872368-19048-kN4FN2/swapfile failed - Invalid argument'
swapon: /tmp/sdtest.872368-19048-kN4FN2/swapfile: skipping - it appears to have holes.
Fatal Error (swap): Unexpected shell error. Run with -x to debug
```

However, just doing a file mount does make the test work on zfs, similar to how it is done with tmpfs. This means we don't need any special-casing for zfs beyond what is already there for working around (similar) tmpfs limitations.

Also, while researching this, it is possible a similar patch is needed for btrfs, but i currently don't have an easy way to test that.
This is non-breaking for anyone *not* using zfs, and it is currently broken with zfs anyways.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1462
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit e8f1ac4791)
2025-01-09 01:38:43 -08:00
Grimmauld
8597b04aac fix swap test on zfs file system
(cherry picked from commit 9a1b538298)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:38:43 -08:00
John Johansen
28537ff8ec Merge limit buildpath.py setuptools version check to the relevant bits
previously, this check would fail if the setuptools version would contain non-integers.
On my system, that is the case: `setuptools.__version__` is `'75.1.0.post0'`
I believe it is entirely fair to just check the relevant bits and refuse  to continue if those can not be checked properly.
Having some extra slug on the version should not immediately cause issues (e.g. the `post0` here, or slugs like `beta`, `alpha` and the likes).
Probably only very few systems are running setuptools with weird version info, but supporting this is a simple one-line change i figured i might as well MR.

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

(cherry picked from commit b3de4ef022)
2025-01-09 01:38:28 -08:00
Grimmauld
f90a041921 limit buildpath.py setuptools version check to the relevant bits
previously, this check would fail if the setuptools version would contain non-integers.
On my system, that is the case: `setuptools.__version__` is `'75.1.0.post0'`
I believe it is entirely fair to just check the relevant bits and refuse  to continue if those can not be checked properly.
But haviong something extra on the version should not immediately cause issues (e.g. the `post0` here, or slugs like `beta`, `alpha` and the likes).
Probably only very few systems are running setuptools with weird version info, but supporting this doesn't cost much, i believe.

(cherry picked from commit 3302ae98e4)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:38:27 -08:00
John Johansen
ae0d1aafda Merge postfix-smtp profile fix
Allow locking for /var/spool/postfix/pid/unix.relay.

Example log entry: `type=AVC msg=audit(1733851239.685:8882): apparmor="DENIED" operation="file_lock" profile="postfix-smtp" name="/var/spool/postfix/pid/unix.relay" pid=14222 comm="smtp" requested_mask="k" denied_mask="k" fsuid=91 ouid=0FSUID="postfix" OUID="root"`

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1459
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit 8a6eb170e1)
2025-01-09 01:37:32 -08:00
pyllyukko
403b3cad10 postfix-smtp profile fix
Allow locking for /var/spool/postfix/pid/unix.relay.

(cherry picked from commit 76dcf46d4f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:37:32 -08:00
John Johansen
851f6013f6 Merge Use MS_SYNCHRONOUS instead of MS_SYNC
MS_SYNC is a flag for msync(2) while MS_SYNCHRONOUS is a flag for mount(2).
The header used to define MS_SYNC but IMO this is confusing since that's an
unrelated flag.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

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

(cherry picked from commit 60f1b55ab5)
2025-01-09 01:36:14 -08:00
Zygmunt Krynicki
0838496c32 Use MS_SYNCHRONOUS instead of MS_SYNC
MS_SYNC is a flag for msync(2) while MS_SYNCHRONOUS is a flag for mount(2).
The header used to define MS_SYNC but IMO this is confusing since that's an
unrelated flag.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit d164e877f5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:36:14 -08:00
John Johansen
191f01b749 Merge Allow spread to use locally-provided kernel
By placing a bzImage into the top level of the AppArmor git repository one can
instruct spread and image-garden to use that image instead of booting
traditionally with an EFI / full disk image pair.

In addition, make error handling in qemu more robust, so failures are both
surfaced and do not cause endless attempts to allocate.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

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

(cherry picked from commit 239ae21b69)
2025-01-09 01:35:52 -08:00
Zygmunt Krynicki
788d29aacb Allow spread to use locally-provided kernel
By placing a bzImage into the top level of the AppArmor git repository one can
instruct spread and image-garden to use that image instead of booting
traditionally with an EFI / full disk image pair.

In addition, make error handling in qemu more robust, so failures are both
surfaced and do not cause endless attempts to allocate.

Please update image-garden to at least 5a00ead9964df6463e19432ae50e7760fc6da755

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 7031b5aeee)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:35:52 -08:00
John Johansen
1b70d1e9c2 Merge tests: add regression tests for snapd mount-control
The test adds a very small and simple smoke test that shows that a mount rule
with both fstype and options allows mounts to be performed on a real running
kernel.

The test is structured in a way that should make it easy to extend with new
variants (flags, fstype) in the future.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1445
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit 11d121409d)
2025-01-09 01:35:27 -08:00
Zygmunt Krynicki
00a5c07db5 tests: add regression tests for snapd mount-control
The test adds a very small and simple smoke test that shows that a mount rule
with both fstype and options allows mounts to be performed on a real running
kernel.

The test is structured in a way that should make it easy to extend with new
variants (flags, fstype) in the future.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 1f60021979)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:35:27 -08:00
John Johansen
6876448a24 Merge Allow running tests with spread
Spread is a full-system, or integration test suite runner initially developed
to test snapd. Over time it has spread to other projects where it provides a
structured way to organize, run and debug complex full-system interactions.
Spread is documented on https://github.com/canonical/spread and is used in
production since late 2016.

Spread has a notion of backends which are responsible for allocating and
discarding test machines. For the purpose of running AppArmor regression tests,
I've combined spread with my own tool, image garden. The tool provides
off-the-shelf images, constructed on-the-fly from freely available images, and
makes them easily available to spread.

The reason for doing it this way is so that using non-free cloud systems is not
required and anyone can repeat the test process locally, on their own computer.
Vanilla spread is somewhat limited to x86-64 systems but the way I've used it
here makes it equally possible to test x86_64 *and* aarch64 systems. I've done
most of the development on an ARM single-board-computer running on my desk.

Spread requires a top-level spread.yaml file and a collection of task.yaml
files that describe individual tasks (for us, those are just tests). Tasks have
no implied dependency except that to reach a given task, spread will run all
the _prepare_ statements leading to that task, starting from the project, test
suite and then task. With proper care one can then run a specific individual
test with a one-line command, for example:

```
spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
```

This will prepare a fresh ubuntu-cloud-24.04 system (matching the CPU
architecture of the host), copy the project tree into the test machine, install
all the build dependencies, build all the parts of apparmor and then run one
specific variant of the regression test, namely the at_secure program.
Importantly the same test can also run on, say debian-cloud-13 (Debian Trixie),
but also, if you have a Google cloud account, on Google Compute Engine or in
one of the other backends either built into spread or available as a fork of
spread or as a helper for ad-hoc backend. Spread can also create more than one
worker per system and distribute the tests to all of the available instances.
In no way are we locking ourselves out of the ability to run our test suite on
our target of choice.

Spread has other useful switches, such as:
- `-reuse` for keeping machines around until discarded with -discard
- `-resend` for re-sending updated copy of the project (useful for -reuse)
- `-debug` for starting an interactive shell on any failure
- `-shell` for starting an interactive shell instead of the `execute` phase

This first patch contains just the spread elements, assuming that both spread
and image-garden are externally installed. A GitLab continuous integration
installing everything required and running a subset of tests will follow
shortly.

I've expanded the initial selection of systems to allow running all the tests
on several versions of Ubuntu, Debian and openSUSE, mainly as a sanity check
but also to showcase how practical spread is at covering real-world systems.

A number of tests are currently failing:

    - garden:debian-cloud-12:tests/regression/apparmor:attach_disconnected
    - garden:debian-cloud-12:tests/regression/apparmor:deleted
    - garden:debian-cloud-12:tests/regression/apparmor:unix_fd_server
    - garden:debian-cloud-12:tests/regression/apparmor:unix_socket_pathname
    - garden:debian-cloud-13:tests/regression/apparmor:attach_disconnected
    - garden:debian-cloud-13:tests/regression/apparmor:deleted
    - garden:debian-cloud-13:tests/regression/apparmor:unix_fd_server
    - garden:debian-cloud-13:tests/regression/apparmor:unix_socket_pathname
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:attach_disconnected
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:deleted
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:e2e
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:unix_fd_server
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:unix_socket_pathname
    - garden:opensuse-cloud-15.6:tests/regression/apparmor:xattrs_profile

In addition, only on openSUSE, I've skipped the entire test suite of the utils
directory, as it requires python3 ttk themes, which I cannot find in packaged
form.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1432
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit d9304c7653)
2025-01-09 01:31:39 -08:00
Zygmunt Krynicki
297cd44aff Document spread tests in README.md
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit d27377a62f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:31:39 -08:00
Zygmunt Krynicki
32da740f1b Third iteration of spread support
- Tests defined in utils/test are now described by a task.yaml in the same
  directory and can run concurrently across many machines.
- Tests for utils/ are now executed on openSUSE Tumbleweed since ttk themes is
  no longer a hard dependency in master.
- Tests no longer run on openSUSE Leap 15.6 due to the age of default
  Python (3.6) and gcc/g++. The tight integration with SWIG which does
  not seem to support other Python versions very well. Perl hard-codes
  old GCC for extension modules. The upcoming openSUSE Leap 16 should be
  a viable target. In the meantime we can still test everything through
  rolling-release Tumbleweed.
- Formatting of YAML files is now more uniform, at four spaces per tab.
- The run-spread.sh script is now in the root of the tree. The script allows
  running all spread tests sequentially on one system, while collecting logs
  and artifacts for convenient analysis after the fact.
- All systems are adjusted to run _four_ workers in parallel with _two_ virtual
  cores each and equipped with 1.5GB of virtual memory. This aims to best
  utilize the capacity of a typical CI worker with two to four cores and about
  8GB of available memory.
- Failing tests are marked as such, so that as a whole the entire spread suite
  can pass and be useful at catching regressions.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 1df91e2c8c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:31:39 -08:00
Zygmunt Krynicki
b24f0bbfa8 Second iteration of spread support
Compared to v1 the following improvements have been made:

- The cost of installing packages have been shifted from each startup to image
  preparation phase, thanks to the integration of custom cloud-init profiles
  into image-garden. This has dramatic impact on iteration time while also
  entirely removing requirement to be online to run once a prepared image is
  available.

- Support for running on Google Compute Engine has been removed since it would
  not be able to use cloud-init the same way would currently only complicate
  setup.

- The number of workers have been tuned for local iteration, aiming for
  comfortable work with 16GB of memory on the host. Once CI/CD pipeline
  support is introduced I will add a dedicated entry so that resources are
  utilized well both locally and when running in CI.

- The set of regression tests listed in tests/regression/apparmor/task.yaml is
  now cross-checked so introduction of a new test to the makefile there is
  automatically flagged and causes spread to fail with a clear message.

- The task tests/unit/utils has been improved to generate profiles. Thanks to
  Christian Boltz for explaining this relationship between tests.

- A number of comments have been improved and cleaned up for readability,
  accuracy and sometimes better grammar.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit c95ac4d350)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:31:39 -08:00
Zygmunt Krynicki
5a4ddbeaeb Allow running tests with spread
Spread is a full-system, or integration test suite runner initially developed
to test snapd. Over time it has spread to other projects where it provides a
structured way to organize, run and debug complex full-system interactions.
Spread is documented on https://github.com/canonical/spread and is used in
production since late 2016.

Spread has a notion of backends which are responsible for allocating and
discarding test machines. For the purpose of running AppArmor regression tests,
I've combined spread with my own tool, image garden. The tool provides
off-the-shelf images, constructed on-the-fly from freely available images, and
makes them easily available to spread.

The reason for doing it this way is so that using non-free cloud systems is not
required and anyone can repeat the test process locally, on their own computer.
Vanilla spread is somewhat limited to x86-64 systems but the way I've used it
here makes it equally possible to test x86_64 *and* aarch64 systems. I've done
most of the development on an ARM single-board-computer running on my desk.

Spread requires a top-level spread.yaml file and a collection of task.yaml
files that describe individual tasks (for us, those are just tests). Tasks have
no implied dependency except that to reach a given task, spread will run all
the _prepare_ statements leading to that task, starting from the project, test
suite and then task. With proper care one can then run a specific individual
test with a one-line command, for example:

```
spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
```

This will prepare a fresh ubuntu-cloud-24.04 system (matching the CPU
architecture of the host), copy the project tree into the test machine, install
all the build dependencies, build all the parts of apparmor and then run one
specific variant of the regression test, namely the at_secure program.
Importantly the same test can also run on, say debian-cloud-13 (Debian Trixie),
but also, if you have a Google cloud account, on Google Compute Engine or in
one of the other backends either built into spread or available as a fork of
spread or as a helper for ad-hoc backend. Spread can also create more than one
worker per system and distribute the tests to all of the available instances.
In no way are we locking ourselves out of the ability to run our test suite on
our target of choice.

Spread has other useful switches, such as:
- `-reuse` for keeping machines around until discarded with -discard
- `-resend` for re-sending updated copy of the project (useful for -reuse)
- `-debug` for starting an interactive shell on any failure
- `-shell` for starting an interactive shell instead of the `execute` phase

This first patch contains just the spread elements, assuming that both spread
and image-garden are externally installed. A GitLab continuous integration
installing everything required and running a subset of tests will follow
shortly.

I've expanded the initial selection of systems to allow running all the tests
on several versions of Ubuntu, Debian and openSUSE, mainly as a sanity check
but also to showcase how practical spread is at covering real-world systems.

A number of systems and tests are currently failing:

- garden:debian-cloud-12:tests/regression/apparmor:attach_disconnected
- garden:debian-cloud-12:tests/regression/apparmor:deleted
- garden:debian-cloud-12:tests/regression/apparmor:unix_fd_server
- garden:debian-cloud-12:tests/regression/apparmor:unix_socket_pathname
- garden:debian-cloud-13:tests/regression/apparmor:attach_disconnected
- garden:debian-cloud-13:tests/regression/apparmor:deleted
- garden:debian-cloud-13:tests/regression/apparmor:unix_fd_server
- garden:debian-cloud-13:tests/regression/apparmor:unix_socket_pathname
- garden:opensuse-cloud-15.6:tests/regression/apparmor:attach_disconnected
- garden:opensuse-cloud-15.6:tests/regression/apparmor:deleted
- garden:opensuse-cloud-15.6:tests/regression/apparmor:e2e
- garden:opensuse-cloud-15.6:tests/regression/apparmor:unix_fd_server
- garden:opensuse-cloud-15.6:tests/regression/apparmor:unix_socket_pathname
- garden:opensuse-cloud-15.6:tests/regression/apparmor:xattrs_profile
- garden:opensuse-cloud-tumbleweed:tests/regression/apparmor:attach_disconnected
- garden:opensuse-cloud-tumbleweed:tests/regression/apparmor:deleted
- garden:opensuse-cloud-tumbleweed:tests/regression/apparmor:unix_fd_server
- garden:opensuse-cloud-tumbleweed:tests/regression/apparmor:unix_socket_pathname
- garden:ubuntu-cloud-22.04:tests/regression/apparmor:attach_disconnected

In addition, only on openSUSE, I've skipped the entire test suite of the utils
directory, as it requires python3 ttk themes, which I cannot find in packaged
form.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit cc04181578)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:31:39 -08:00
Zygmunt Krynicki
fd253d1c31 Allow running exactly one test in utils/test
The new check-one-test-% pattern rule allows running individual test scripts.
This allows them to be tested in parallel across many Make worker threads or
across many distinct machines with spread.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 9588b06e0f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:31:39 -08:00
John Johansen
505faeff10 Merge Add explicit test for parser priority-based carveouts
Tests #466 but is marked as expected fail due to that bug not being resolved.

Depends on !1441 which adds the xfail infrastructure to the parser equality testing framework, and should be rebased on top of master once that MR is merged.

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

(cherry picked from commit e1d8bf1888)
2025-01-09 01:30:12 -08:00
Ryan Lee
3d5346b48e parser equality tests: print both profiles upon test failure
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit b925d8acff)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:30:12 -08:00
Ryan Lee
1d9e28df35 Add explicit test for parser priority-based carveouts
These are marked as expected fail due to a bug in the parser's priority
handling.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 7b5f4c0d6f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:30:12 -08:00
John Johansen
9995e36347 Merge parser: equality tests: add the ability have tests that are a known problem
currently the equality tests require the tests to PASS as known equality
or inequality. Add the ability to add tests that are a known problem
and are expected to fail the equality, or inequality test.

This is done by using

   verify_binary_xequality
   verify_binary_xinequality

This allows new tests to be added to document a known issue, without
having to develop the fix for the issue. The use of this facility
is expected to be temporary, so any test marked as xequality or
xinequality will be noisy but not fail the other tests until they
are fixed, at which point they will cause the tests to fail to
force them to be updated to the correct equality or inequality
test.

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

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

(cherry picked from commit 53e322b755)
2025-01-09 01:27:50 -08:00
John Johansen
08aeeedc69 parser: equality tests: add the ability have tests that are a known problem
currently the equality tests require the tests to PASS as known equality
or inequality. Add the ability to add tests that are a known problem
and are expected to fail the equality, or inequality test.

This is done by using

   verify_binary_xequality
   verify_binary_xinequality

This allows new tests to be added to document a known issue, without
having to develop the fix for the issue. The use of this facility
is expected to be temporary, so any test marked as xequality or
xinequality will be noisy but not fail the other tests until they
are fixed, at which point they will cause the tests to fail to
force them to be updated to the correct equality or inequality
test.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit b81ea65c1c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:27:50 -08:00
John Johansen
d426129baf Merge profiles: update bwrap profile
Update the bwrap profile so that it will attach to application profiles
if present.

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

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

(cherry picked from commit 662a26d133)
2025-01-09 01:26:51 -08:00
John Johansen
cda7af8561 profiles: update bwrap profile
Update the bwrap profile so that it will attach to application profiles
if present.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 1979af7710)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:26:51 -08:00
John Johansen
f5844dc267 Merge regression tests: Add test to check for DAC permissions to the testsuite
The regression test suite uses root with capabilities restricted in
several tests. This can cause the test suite to fail in weird and
confusing ways.

Add a test to check for DAC permissiosns from / to the testsuite
and abort running the tests with an error message if DAC permissions
are going to cause the test suite to fail.

Currently the test is pretty basic, but is better than nothing.

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

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

(cherry picked from commit c5b17d85ea)
2025-01-09 01:21:11 -08:00
John Johansen
52b83aeac4 regression tests: Add test to check for DAC permissions to the testsuite
The regression test suite uses root with capabilities restricted in
several tests. This can cause the test suite to fail in weird and
confusing ways.

Add a test to check for DAC permissiosns from / to the testsuite
and abort running the tests with an error message if DAC permissions
are going to cause the test suite to fail.

Currently the test is pretty basic, but is better than nothing.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 82e4b4ba00)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:21:11 -08:00
John Johansen
89fd37abbf Merge Assorted fixes for test suite portability
I've been working on improved end-to-end testing of AppArmor on a number
of popular Linux distributions. My first run contains Debian, Ubuntu and openSUSE.

This branch contains three small fixes that, mainly, allow running more tests on
openSUSE Tumbleweed.

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

(cherry picked from commit 6f5cdb7b44)
2025-01-09 01:20:44 -08:00
Zygmunt Krynicki
ffff25e21b On openSUSE 15.6 make fails to find awk
Using this version of make:
```
GNU Make 4.2.1
Built for x86_64-suse-linux-gnu
```
I'm not entirely sure why but the alternative syntax I've used works correctly.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 4caf0aff81)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:44 -08:00
Zygmunt Krynicki
0e7e509ba8 Use larger loop device in mult_mount.sh test
This fixes the test to pass on openSUSE Tumbleweed, where the small size
prevented alloction of an inode for the `lost+found` directory:

```
garden:opensuse-cloud-tumbleweed .../tests/regression/apparmor# mkfs.ext2 -F -m 0 -N 10 /tmp/sdtest.32929-21402-6x826m/image.ext3
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 512 1k blocks and 8 inodes

Allocating group tables: done
Writing inode tables: done
ext2fs_mkdir: Could not allocate inode in ext2 filesystem while creating /lost+found
```

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 32ee85cef8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:44 -08:00
Zygmunt Krynicki
4722ff8e65 Quote trailing backslash in test case
This fixes an error with Python 3.11:

```
test/test-parser-simple-tests.py:420:21: E502 the backslash is redundant between brackets
```

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 92fcdcab9e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:44 -08:00
Zygmunt Krynicki
d88c6d3bca Use command -v rather than which
Which is technically not POSIX and command -v works everywhere. This fixes
building and running the test suite on openSUSE Tumbleweed.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit 4b0adc63f5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:44 -08:00
Zygmunt Krynicki
37ea52db0c parser: quote BISON_MAJOR in case it is empty
On a test system without bison installed, make setup fails with:

  /bin/sh: 1: bison: not found
  /bin/sh: 1: test: -ge: unexpected operator

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
(cherry picked from commit f58fe9cd52)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:44 -08:00
John Johansen
da9c59ab09 Merge regression tests: check for setfattr binary used by xattrs_profile
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit 0828ab67b2)
2025-01-09 01:20:26 -08:00
Ryan Lee
8fde25d828 regression tests: check for setfattr binary used by xattrs_profile
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit b39a535cb9)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-09 01:20:26 -08:00
John Johansen
5aa7d046db Merge Write basic file complain-mode regression tests
The test "Complain mode profile (file exec cx permission entry)" currently will only pass on a Ubuntu Oracular system due to a kernel bugfix patch that has not yet been upstreamed or backported.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit 926929da16)
2025-01-08 23:06:13 -08:00
Ryan Lee
9c3ac976ec Write basic file complain-mode regression tests
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit cb110eaf98)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 23:06:13 -08:00
John Johansen
f433acb219 Merge Dovecot profile: Allow reading of /proc/sys/kernel/core_pattern
See <https://dovecot.org/bugreport.html>

(the link describes how Dovecot requires access to `core_pattern`)

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

(cherry picked from commit 2b45586fa9)
2025-01-08 23:01:29 -08:00
pyllyukko
5ee3c03101 Dovecot profile: Allow reading of /proc/sys/kernel/core_pattern
See <https://dovecot.org/bugreport.html>

(cherry picked from commit 0a5a9c465f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 23:01:29 -08:00
John Johansen
6fdc08a5a5 Merge tests: fix incorrect setfattr call in xattrs_profile
The file was quoted with the following space, making the test broken.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1429
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>

(cherry picked from commit a2d52fedb2)
2025-01-08 23:01:06 -08:00
Zygmunt Krynicki
e931449ffc tests: fix incorrect setfattr call in xattrs_profile
The file was quoted with the following space, making the test broken.

Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
(cherry picked from commit 8c16fb2700)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 23:01:06 -08:00
John Johansen
203b4994e9 Merge Quote some variables in regression test suite to allow for spaces
This is not a complete fix for the spaces issue, but it is the next simple step that can be taken before the more difficult work of finding the remaining bugs in each shell script.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

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

(cherry picked from commit e27b0ad2b6)
2025-01-08 23:00:44 -08:00
Ryan Lee
7b53763f92 Quote some variables in regression test suite to allow for spaces
Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit e7ec01f075)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 23:00:44 -08:00
John Johansen
ddb33d348c Merge parser: fix expr MatchFlag dump
Match Flags convert output to hex but don't restore after outputting
the flag resulting in following numbers being hex encoded. This
results in dumps that can be confusing eg.

rule: \d2  ->  \x2 priority=1001 (0x4/0)< 0x4>

rule: \d7  ->  \a priority=3e9 (0x4/0)< 0x4>

rule: \d10  ->  \n priority=3e9 (0x4/0)< 0x4>

rule: \d9  ->  \t priority=3e9 (0x4/0)< 0x4>

rule: \d14  ->  \xe priority=1001 (0x4/0)< 0x4>

where priority=3e9 is the hex encoded priority 1001.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1419
Approved-by: Maxime Bélair <maxime.belair@canonical.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit 2e77129e15)
2025-01-08 22:59:44 -08:00
John Johansen
8274bff547 parser: fix expr MatchFlag dump
Match Flags convert output to hex but don't restore after outputting
the flag resulting in following numbers being hex encoded. This
results in dumps that can be confusing eg.

rule: \d2  ->  \x2 priority=1001 (0x4/0)< 0x4>

rule: \d7  ->  \a priority=3e9 (0x4/0)< 0x4>

rule: \d10  ->  \n priority=3e9 (0x4/0)< 0x4>

rule: \d9  ->  \t priority=3e9 (0x4/0)< 0x4>

rule: \d14  ->  \xe priority=1001 (0x4/0)< 0x4>

where priority=3e9 is the hex encoded priority 1001.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit a31343c5f7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 22:59:44 -08:00
John Johansen
b17750163b Merge Partial fix for regression tests if parent directory contains spaces
Most `tests/regression/apparmor/*.sh` scripts contain

    . $bin/prologue.inc

This will explode if one of the parent directories contains a space.

Minimized reproducer:

```
# cat test.sh
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
echo "pwd: $bin"
. $bin/prologue.inc
# ./test.sh
pwd: /tmp/foo bar
./test.sh: line 9: /tmp/foo: No such file or directory
```

Notice that test.sh tries to source `/tmp/foo` instead of `/tmp/foo bar/prologue.inc`.

The fix is to quote the prologue.inc path:

    . "$bin/prologue.inc"

While on it, also fix other uses of $bin - directly and indirectly - by quoting them.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1418
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit a422d2ea17)
2025-01-08 22:58:38 -08:00
Christian Boltz
9c229d1452 Quote indirect uses of $bin and ${bin}
... to avoid issues with spaces in a parent directory's name.

"Indirect uses" means usage of $bin via another variable, for example
`foo=$bin/whatever`

(cherry picked from commit 55db4af979)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 22:58:38 -08:00
Christian Boltz
702f2863a4 Quote all uses of $bin and ${bin}
... to avoid issues with spaces in a parent directory's name.

(cherry picked from commit 22cf88b7c7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 22:58:38 -08:00
Christian Boltz
989bf0b3ed Fix sourcing prologue.inc if parent directory contains spaces
Most `tests/regression/apparmor/*.sh` scripts contain

    . $bin/prologue.inc

This will explode if one of the parent directories contains a space.

Minimized reproducer:

```
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
echo "pwd: $bin"
. $bin/prologue.inc
pwd: /tmp/foo bar
./test.sh: line 9: /tmp/foo: No such file or directory
```

Notice that test.sh tries to source `/tmp/foo` instead of `/tmp/foo bar/prologue.inc`.

The fix - as done in this commit - is to quote the prologue.inc path:

    . "$bin/prologue.inc"

(cherry picked from commit e1972eb22f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 22:58:38 -08:00
John Johansen
9b1d0ea3d8 Merge parser: improve libapparmor_re build and dump info
Fix libapparmor_re/Makefile so it works correctly with rebuilds and
improve state machine dump information, to aid with debugging of
permission handling during the compile.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1410
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 015b41aeb4)
2025-01-08 12:24:33 -08:00
John Johansen
a577d92c7b parser: add the abilitiy to dump the permissions table
Instead of encoding permissions in the accept and accept2 tables
extended perms uses a permissions table and accept becomes an index
into the table.

Add the ability to dump the permissions table so that it can be
compared and debugged.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 45964d34e7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 12:22:58 -08:00
John Johansen
a16aff8e20 parser: add the accept2 table entry to the chfa dump
The chfa dump is missing information about the accept2 entry. The
accept2 information is necessary to help with debugging state machine
builds as accept2 is used to store quiet and audit information in the
old format or conditional information in the extended perms format.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 00dedf10ad)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 12:22:45 -08:00
John Johansen
4099bf6574 parser: fix and cleanup libapparmor_re/Makefile
The Makefile is missing some of its .h depenedncies causing compiles
to either fail or worse result in bad builds when rebuilding in an
already built tree.

Move the header dependencies into a variable and use it for each
target. While some targets don't need every include as a dependency
and this will result in unnecessary rebuilds in some cases, it makes
the Makefile cleaner, easier to maintain and makes sure a dependency
isn't accidentally missed.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 7cc7f47424)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 12:22:28 -08:00
John Johansen
a102e9dc55 Merge parser: fix mapping of AA_CONT_MATCH for policydb compat entries
The mapping of AA_CONT_MATCH was being dropped resulting in the
tcp tests failing because they would only match up to the first conditional
match check in the layout.

Bug: https://gitlab.com/apparmor/apparmor/-/issues/462
Fixes: e29f5ce5f ("parser: if extended perms are supported by the kernel build a permstable")
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1409
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit f24fc4841f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 11:44:22 -08:00
John Johansen
7c1eff3867 Prepare for 4.1.0~beta2 release
- bump version

Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
d69d4d3ddf Merge parser: bug fix do not change auditing information when applying deny
The parser recently changed how/where deny information is applied.
commit 1fa45b7c1 ("parser: dfa minimization prepare for extended
permissions") removed the implicit filtering of explicit denies during
the minimization pass. The implicit clear allowed the explicit
information to be carried into the minimization pass and merged with
implicit denies. The end result being a minimized dfa with the explicit
deny information available to be applied post minimization, and
then dropped later at permission encoding in the accept entries.

Extended permission however enable carrying explicit deny information
into the kernel to fix certain bugs like complain mode not being
able to distinguish between implicit and explicit deny rules (ie.
deny rules get ignored in complain mode). However keeping explicit
deny information when unnecessary result in a larger state machine
than necessary and slower compiles.

commit 179c1c1ba ("parser: fix minimization check for filtering_deny")
Moved the explicit apply_and_clear_deny() pass to before minimization
to restore mnimization's ability to create a minimized dfa with
explicit and implicit deny information merged but this also cleared
the explicit deny information that used to be carried through
minimization. This meant that when the deny information was applied
post minimization it resulted in the audit and quiet information
being cleared.

This resulted in the query_label tests failing as they are checking
for the expected audit infomation in the permissions.

Fixes: 179c1c1ba ("parser: fix minimization check for filtering_deny")
Bug: https://gitlab.com/apparmor/apparmor/-/issues/461
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1408
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit eb365b374d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
5c04b791d2 Merge aa-mergeprof: prevent backtrace if file not found
If a user specifies a non-existing file to merge into the profiles
(`aa-mergeprof /file/not/found`), this results in a backtrace showing an
AppArmorBug because that file unsurprisingly doesn't end up in the
active_profiles filelist.

Handle this more gracefully by adding a read_error_fatal parameter to
read_profile() that, if set, forwards the exception. With that,
aa-mergeprof doesn't try to list the profiles in this non-existing file.

Note that all other callers of read_profile() continue to ignore read
errors, because aborting just because a single file in /etc/apparmor.d/
(for example a broken symlink) isn't readable would be a bad idea.

This bug was introduced in 4e09f315c3, therefore I propose this patch for 3.0..master

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1403
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 5ebbe788ea)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
be8d85603e Merge php-fpm: widen allowed socket paths
It is common for packaged PHP applications to ship a PHP-FPM
configuration using a scheme of "$app.sock" or or "$app.socket" instead
of using a generic FPM socket.

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1406
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit bfa9147182)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Georgia Garcia
450813869a profiles: update dconf abstraction to use @{etc_ro}
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit cbe8d295a5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 740d7ddae14b69568eaede1b05fe560ae53762df)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
65c41b7fac Merge Misc small fixes to resolve some compiler warnings in regression test suite
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1407
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 14f54f3df2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Georgia Garcia
d19e5e8990 Merge Improvements to Postfix profiles
* Support /usr/libexec/postfix/ path
* Added abstractions/{nameservice,postfix-common} to postfix-postscreen
* Added postfix-tlsproxy, postscreen & spawn to postfix-master
    * Added missing postfix-tlsproxy profile
* Added postscreen cache map (see <https://www.postfix.org/postconf.5.html#postscreen_cache_map>)
* Added /{var/spool/postfix/,}pid/pass.smtpd to postfix-smtpd

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1330
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit f7b5d0e783)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Giampaolo Fresi Roglia
c11ad3e675 abstractions/nameservice: tighten libnss_libvirt file access
(cherry picked from commit 5be4295b5a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Georgia Garcia
de2bb16ad6 Merge Support name resolution via libnss-libvirt
Add support for hostname resolution via libnss-libvirt. This change has been tested against the latest oracular version 10.6.0-1ubuntu3.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1362
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit a522e11129)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Georg Pfuetzenreuter
4f1d2ac549 zgrep: deny passwd access
Bash will try to read the passwd database to find the shell of a user if
$SHELL is not set. This causes zgrep to trigger

```
apparmor="DENIED" operation="open" class="file" profile="zgrep" name="/etc/nsswitch.conf" comm="zgrep" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
apparmor="DENIED" operation="open" class="file" profile="zgrep" name="/etc/passwd" comm="zgrep" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
```

if called in a sanitized environment. As the functionality of zgrep is
not impacted by a limited Bash environment, add deny rules to avoid the
potentially misleading AVC messages.

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
(cherry picked from commit 48483f2ff8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Christian Boltz
cc9f0ed538 ProfileStorage: store correct name
Instead of always storing the name of the main profile, store the child
profile/hat name if we are in a child profile or hat.

As a result, we always get the correct "profile xy" header even for
child profiles when dumping the ProfileStorage object.

Also extend the tests to check that the name gets stored correctly.

(cherry picked from commit cb943e4efc)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Steve Beattie
1b8afda407 .gitignore: add mod_apparmor and pam_apparmor files
... that are generated during `make`

I propose this patch for 3.x..master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1374
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: Steve Beattie <steve+gitlab@nxnw.org>
Merged-by: Steve Beattie <steve+gitlab@nxnw.org>
(cherry picked from commit 3478558904)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Christian Boltz
9aae96356e Merge apparmor.vim: Add missing units for rlimit cpu and rttime
... and allow whitespace between the number and the unit.

I propose this patch for 3.x, 4.0 and master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1336
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit 247bdd5deb)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
b5db2361f3 Merge profiles: add support for ArchLinux php-legacy package to php-fpm
ArchLinux ships a secondary PHP package called php-legacy with different
paths. As of now, the php-fpm profile will cover this binary but
inadequately restrict it.

Fixes: #454

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

(cherry picked from commit 3d1a3493af)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
John Johansen
5db4a1e7ca Merge abstractions/nameservice: include nameservice-strict
... and drop all rules it contains from abstractions/nameservice.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1373
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 4fe3e30abc)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2025-01-08 10:58:20 -08:00
Christian Boltz
230a975916 Merge smbd: allow capability chown
This is neeed for "inherit owner = yes" in smb.conf.

From man smb.conf:

    inherit owner (S)

    The ownership of new files and directories is normally governed by
    effective uid of the connected user. This option allows the Samba
    administrator to specify that the ownership for new files and
    directories should be controlled by the ownership of the parent
    directory.

Fixes: https://bugzilla.suse.com/show_bug.cgi?id=1234327

I propose this fix for 3.x, 4.x and master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1456
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>


(cherry picked from commit a315d89a2b)

d3050285 smbd: allow capability chown

Co-authored-by: John Johansen <john@jjmx.net>
2024-12-10 12:50:24 +00:00
Christian Boltz
aa3592a57e Merge postfix-showq profile fix
Allow reading queue ID files from /var/spool/postfix/hold/.

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


(cherry picked from commit dfe771602d)

3c2aae3a postfix-showq profile fix

Co-authored-by: Christian Boltz <apparmor@cboltz.de>
2024-12-09 18:56:41 +00:00
Christian Boltz
a9aef6f37b Merge python 3.13 fixes/workarounds
Fixes/workarounds for python 3.13 support.

fail.py: handle missing cgitb - workaround for https://gitlab.com/apparmor/apparmor/-/issues/447

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


(cherry picked from commit 5fb91616e3)

434e34bb fail.py: handle missing cgitb

Co-authored-by: Christian Boltz <apparmor@cboltz.de>
2024-12-05 17:36:32 +00:00
Georgia Garcia
c71c486313 Merge Remove match statements in utils for older Python compatibility
Somehow the use of new match statements slipped by review despite our commitment to supporting older Python versions. Replace them with an unfortunately-needed if-elif chain.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1440
Approved-by: Christian Boltz <apparmor@cboltz.de>
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 36ae21e3fa)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-12-03 10:00:25 -03:00
Christian Boltz
4213dcc586 Merge aa-remove-unknown: fix readability check [upstreaming]
I am upstreaming this patch that is part of the nix package of apparmor for close to a year now.
This fixes the issue at https://github.com/NixOS/nixpkgs/issues/273164 for more distros than just NixOS.
The original merge Request on the nix side patching this was https://github.com/NixOS/nixpkgs/pull/285915.
However, people had issues with gitlab, so this never hit apparmor upstream until now. This does however also mean this patch has seen production and seems to work quite well.

## Original reasoning/message of the patch author:

This check is intended for ensuring that the profiles file can actually
be opened.  The *actual* check is performed by the shell, not the read
utility, which won't even be executed if the input redirection (and
hence the test) fails.

If the test succeeds, though, using `read` here might actually
jeopardize the test result if there are no profiles loaded and the file
is empty.

This commit fixes that case by simply using `true` instead of `read`.

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


(cherry picked from commit 93c7035148)

b4aa00de aa-remove-unknown: fix readability check

Co-authored-by: Christian Boltz <apparmor@cboltz.de>
2024-12-01 16:11:25 +00:00
Christian Boltz
ff7f0ff0ea Merge test-logprof: Increase timeout once more
Builds for risc64 are much slower than on other architectures (4-5
seconds with qemu-user or on Litchi Pi 4A).

Since the timeout is only meant as a safety net, increase it generously,
and hopefully for the last time.

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

I propose this patch for 4.0 and master.

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


(cherry picked from commit 4c32ad8fb7)

508ace45 test-logprof: Increase timeout once more

Co-authored-by: John Johansen <john@jjmx.net>
2024-11-10 16:34:48 +00:00
John Johansen
9da0f6d3db Merge zgrep: allow reading /etc/nsswitch.conf and /etc/passwd
Seen on various VMs, my guess is that bash wants to translate a uid to a
username.

Log events (slightly shortened)

apparmor="DENIED" operation="open" class="file" profile="zgrep" name="/etc/nsswitch.conf" comm="zgrep" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

apparmor="DENIED" operation="open" class="file" profile="zgrep" name="/etc/passwd" comm="zgrep" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

I propose this patch for 3.0..master

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1357
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit ab16377838)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:29:38 -07:00
John Johansen
0c1c186267 Merge Fix memory leak in aare_rules UniquePermsCache
When the find fails but the insertion also fails, we leak the new node
that we generated. Delete the new node in this case to avoid leaking
memory.

The question remains, however, as to whether we should implement `operator==` in addition to `operator<` so that they are consistent with each other and `find` works correctly.

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1399
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 99261bad11)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:26:54 -07:00
Steve Beattie
bfd2a0e014 profiles: transmission-daemon needs attach_disconnected
Systemd's PrivateTmp= in transmission service is causing mount namespaces to be used leading to disconnected paths

[395201.414562] audit: type=1400 audit(1727277774.392:573): apparmor="ALLOWED" operation="sendmsg" class="file" info="Failed name lookup - disconnected path" error=-13 profile="transmission-daemon" name="run/systemd/notify" pid=193060 comm="transmission-da" requested_mask="w" denied_mask="w" fsuid=114 ouid=0

Fixes: https://bugs.launchpad.net/bugs/2083548
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1355
Approved-by: Ryan Lee <rlee287@yahoo.com>
Merged-by: Steve Beattie <steve+gitlab@nxnw.org>
(cherry picked from commit 4d3b094d9e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:24:50 -07:00
Georgia Garcia
c87fb0a8c1 Merge abstraction: add nameservice-strict.
As I have read multiple MR mentioning the `nameservice-strict`. Therefore, I thought it would make sense to directly import it here.

To give some context, this abstraction is probably the most commonly included abstraction (after `base`). In `apparmor.d`, it is used by over 700 profiles (only counting direct import). Therefore, adding new rules can have an important impact over a lot of profiles.

Note: the abstraction is a direct import from https://gitlab.com/roddhjav/apparmor.d. The license is the same, I obviously kept Morfikov copyright line. However, I am not sure either or not the SPDX identifier can be used here.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1368
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Approved-by: Christian Boltz <apparmor@cboltz.de>
Approved-by: Ryan Lee <rlee287@yahoo.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 68376e7fee)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:19:06 -07:00
Georgia Garcia
05debdb2d8 Merge Support name resolution via libnss-libvirt
Add support for hostname resolution via libnss-libvirt. This change has been tested against the latest oracular version 10.6.0-1ubuntu3.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1362
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit a522e11129)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:18:32 -07:00
Christian Boltz
8b06f61bea Merge ping: allow reading /proc/sys/net/ipv6/conf/all/disable_ipv6
Fixes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1082190

I propose this patch for 3.0..master.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1340
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit 4b6df10fe3)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:16:50 -07:00
Christian Boltz
34a706f566 Merge abstractions/mesa: allow ~/.cache/mesa_shader_cache_db/
... which is used by Mesa 24.2.2

Reported by darix.

Fixes: https://bugs.launchpad.net/bugs/2081692

I propose this addition for 3.x, 4.0 and master

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1333
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit 62ff290c02)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:16:30 -07:00
Georgia Garcia
a31cbd07aa profiles: enable php-fpm in /usr/bin and /usr/sbin
To enable the profile in distros that merge sbin into bin.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/421
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 2083994513)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:09:01 -07:00
Akihiro Suda
c4c020cdc0 profiles: slirp4netns: allow pivot_root
`pivot_root` is required for running `slirp4netns --enable-sandbox` inside LXD.
- https://github.com/rootless-containers/slirp4netns/issues/348
- https://github.com/rootless-containers/slirp4netns/blob/v1.3.1/sandbox.c#L101-L234

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
(cherry picked from commit bf5db67284)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-30 02:08:47 -07:00
John Johansen
3c00ed7c85 Merge parser: fix minimization check for filtering deny
commit 1fa45b7c1 ("parser: dfa minimization prepare for extended
permissions") removed implicit filtering of explicit denies in the
minimization pass (the information was ignored in building the set of
final accept states).

The filtering of explicit denies reduces the size of the produced
dfa. Since we need to be smarter about when explicit denies are
kept (eg. during complain mode), and most dfas are limited to 65k
states we currently need to filter explicit deny perms by default.

To compensate commit 2737cb2c2 ("parser: minimization - remove
unnecessary second minimization pass") moved the
apply_and_clear_deny() to before minimization. However its check to
apply removal denials before minimization is broken. Remove minimization
triggering apply_and_clear_deny() and just set the FILTER_DENY flag
by default, until we have better selection of rules/conditions where
explicit deny information should be carried through to the backend.

Fixes: 2737cb2c2 ("parser: minimization - remove unnecessary second minimization pass")
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1397
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit e9d6e0ba14)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:58:49 -07:00
John Johansen
bf8fd8cfac Merge parser: fix integer overflow bug in rule priority comparisons
There is an integer overflow when comparing priorities when cmp is
used because it uses subtraction to find lessthan, equal, and greater
than in one operation.

But INT_MAX and INT_MIN are being used by priorities and this results
in INT_MAX - INT_MIN and INT_MIN - INT_MAX which are both overflows
causing an incorrect comparison result and selection of the wrong
rule permission.

Closes: https://gitlab.com/apparmor/apparmor/-/issues/452
Fixes: e3fca60d1 ("parser: add the ability to specify a priority prefix to rules")
Signed-off-by: John Johansen <john.johansen@canonical.com>

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

(cherry picked from commit a5da9d5b5d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:58:35 -07:00
John Johansen
2ca7d30590 Merge utils: catch TypeError exception for binary logs
When a log like system.journal is passed on to aa-genprof, for
example, the user receives a TypeError exception: in method
'parse_record', argument 1 of type 'char *'

This patch catches that exception and displays a more meaningful
message.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/436
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

Closes #436
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1354
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit cb0f84e101)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:57:50 -07:00
John Johansen
5a39ae82fe Merge Fix ABI break for aa_log_record
Commit 3c825eb001 adds a field called `execpath` to the `aa_log_record` struct. This field was added in the middle of the struct instead of the end, causing an ABI break in libapparmor without a corresponding major version number bump.
Bug report: https://bugs.launchpad.net/apparmor/+bug/2083435
This is fixed by simply moving execpath at the end of the struct.

Signed-off-by: Maxime Bélair <maxime.belair@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1345
Approved-by: Ryan Lee <rlee287@yahoo.com>
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 07fe0e9a1b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:56:24 -07:00
John Johansen
c7ce54bcbf Merge aa-notify: Simplify user interfaces and update man page
aa-notify: Simplify user interfaces and update man page

In notifications, Clicking on "allow" now directly adds the rule without
intermediate window, leading to a smoother UX.
Aligning man page with notify.conf.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1313
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit b5af7d5492)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:55:20 -07:00
John Johansen
2318ba598c Merge utils: fixes when handling owner file rules
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/429
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/430

Closes #429 and #430
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1320
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit 1940b1b7cd)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:55:00 -07:00
John Johansen
3d403fe2a7 Merge parser: add port range support on network policy
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1321
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit ebeb89cbce)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:53:20 -07:00
John Johansen
9074b20a95 Merge utils: ignore peer when parsing logs for non-peer access modes
utils: ignore peer when parsing logs for non-peer access modes

Some access modes (create, setopt, getopt, bind, shutdown, listen,
getattr, setattr) cannot be used with a peer in network rules.

Due to how auditing is implemented in the kernel, the peer information
might be available in the log (as faddr= but not daddr=), which causes
a failure in log parsing.

When parsing the log, check if that's the case and ignore the peer,
avoiding the exception on the NetworkRule constructor.

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

Reported-by: Evan Caville <evan.caville@canonical.com>

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

Closes #427
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1314
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit ab5f180b08)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:52:21 -07:00
John Johansen
7949339b93 Merge parser: fix rule priority destroying rule permissions for some classes
io_uring and userns mediation are encoding permissions on the class
byte. This is a mistake that should never have been allowed.

With the addition of rule priorities the class byte mediates rule,
that ensure the kernel can determine a class is being mediated is
given the highest priority possible, to ensure class mediation can not
be removed by a deny rule. See
  61b7568e1 ("parser: bug fix mediates_X stub rules.")
for details.

Unfortunately this breaks rule classes that encode permissions on the
class byte, because those rules will always have a lower priority and
the class mediates rule will always be selected over them resulting in
only the class mediates permission being on the rule class state.

Fix this by adding the mediaties class rules for these rule classes
with the lowest priority possible. This means that any rule mediating
the class will wipe out the mediates class rule. So add a new mediates
class rule at the same priority, as the rule being added.

This is a naive implementation and does result in more mediates rules
being added than necessary. The rule class could keep track of the
highest priority rule that had been added, and use that to reduce the
number of mediates rules it adds for the class.

Technically we could also get away with not adding the rules for allow
rules, as the kernel doesn't actually check the encoded permission but
whether the class state is not the trap state. But it is required with
deny rules to ensure the deny rule doesn't result in permissions being
removed from the class, resulting in the kernel thinking it is
unmediated. We also want to ensure that mediation is encoded for other
rule types like prompt, and in the future the kernel could check the
permission so we do want to guarantee that the class state has the
MAY_READ permission on it.

Note: there is another set of classes (file, mqueue, dbus, ...) which
encodes a default rule permission as

  class .* <perm>

this encoding is unfortunate in that it will also add the permission
to the class byte, but also sets up following states with the permission.
thankfully, this accespt anything, including nothing generally isn't
valid in the nothing case (eg. a file without any absolute name). For
this set of classes, the high priority mediates rule just ensures
that the null match case does not have permission.

Fixes: 61b7568e1 parser: bug fix mediates_X stub rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1307
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit b6e9df3495)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:51:48 -07:00
Georgia Garcia
80b6e4ddff Merge libapparmor: make af_protos.h consistent in different archs
af_protos.h is a generated table of the protocols created by looking
for definitions of IPPROTO_* in netinet/in.h. Depending on the
architecture, the order of the table may change when using -dM in the
compiler during the extraction of the defines.

This causes an issue because there is more than one IPPROTO defined
by the value 0: IPPROTO_IP and IPPROTO_HOPOPTS which is a header
extension used by IPv6. So if IPPROTO_HOPOPTS was first in the table,
then protocol=0 in the audit logs would be translated to hopopts.

This caused a failure in arm 32bit:

Output doesn't match expected data:
--- ./test_multi/testcase_unix_01.out	2024-08-15 01:47:53.000000000 +0000
+++ ./test_multi/out/testcase_unix_01.out	2024-08-15 23:42:10.187416392 +0000
@@ -12,7 +12,7 @@
 Peer Addr: @test_abstract_socket
 Network family: unix
 Socket type: stream
-Protocol: ip
+Protocol: hopopts
 Class: net
 Epoch: 1711454639
 Audit subid: 322

By the time protocol is resolved in grammar.y, we don't have have
access to the net family to check if it's inet6. Instead of making
protocol dependent on the net family, make the order of the
af_protos.h table consistent between architectures using -dD.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1309
Approved-by: John Johansen <john@jjmx.net>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit 0ec0e2b035)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:51:23 -07:00
John Johansen
d824adcf93 Merge utils: change os.mkdir to self.mkpath to create intermediary dirs
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1306
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 4c8a27457e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-10-28 04:50:24 -07:00
214 changed files with 2876 additions and 931 deletions

25
.gitignore vendored
View File

@@ -11,6 +11,17 @@ binutils/aa-status
binutils/aa-status.8
binutils/cJSON.o
binutils/po/*.mo
changehat/mod_apparmor/.libs
changehat/mod_apparmor/mod_apparmor.8
changehat/mod_apparmor/mod_apparmor.8.html
changehat/mod_apparmor/mod_apparmor.la
changehat/mod_apparmor/mod_apparmor.lo
changehat/mod_apparmor/mod_apparmor.slo
changehat/mod_apparmor/mod_apparmor.so
changehat/mod_apparmor/pod2htmd.tmp
changehat/pam_apparmor/get_options.o
changehat/pam_apparmor/pam_apparmor.o
changehat/pam_apparmor/pam_apparmor.so
parser/po/*.mo
parser/af_names.h
parser/cap_names.h
@@ -169,7 +180,6 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
libraries/libapparmor/testsuite/test_multi/out
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
changehat/mod_apparmor/.libs
utils/*.8
utils/*.8.html
utils/*.5
@@ -209,6 +219,7 @@ tests/regression/apparmor/chgrp
tests/regression/apparmor/chmod
tests/regression/apparmor/chown
tests/regression/apparmor/clone
tests/regression/apparmor/complain
tests/regression/apparmor/dbus_eavesdrop
tests/regression/apparmor/dbus_message
tests/regression/apparmor/dbus_service
@@ -284,3 +295,15 @@ tests/regression/apparmor/xattrs_profile
tests/regression/apparmor/coredump
**/__pycache__/
*.orig
# Patterns related to spread integration tests
*.img
*.iso
*.lock
*.log
*.qcow2
*.run
.spread-reuse.yaml
.spread-reuse.*.yaml
spread-artifacts/
spread-logs/

68
.image-garden.mk Normal file
View File

@@ -0,0 +1,68 @@
# This file is read by image-garden when spread is allocating test machines.
# All the package installation happens through cloud-init profiles defined
# below.
# This is the cloud-init user-data profile for all Debian systems. Note that it
# is an extension of the default profile necessary for operation of
# image-garden.
define DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE
$(CLOUD_INIT_USER_DATA_TEMPLATE)
packages:
- attr
- autoconf
- autoconf-archive
- automake
- bison
- build-essential
- dejagnu
- flake8
- flex
- gettext
- libdbus-1-dev
- libtool
- liburing-dev
- pkg-config
- python3-all-dev
- python3-gi
- python3-notify2
- python3-psutil
- python3-setuptools
- python3-tk
- python3-ttkthemes
- swig
endef
# Ubuntu shares cloud-init profile with Debian.
UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE=$(DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE)
# This is the cloud-init user-data profile for openSUSE Tumbleweed.
define OPENSUSE_tumbleweed_CLOUD_INIT_USER_DATA_TEMPLATE
$(CLOUD_INIT_USER_DATA_TEMPLATE)
packages:
- attr
- autoconf
- autoconf-archive
- automake
- bison
- dbus-1-devel
- dejagnu
- flex
- gcc
- gcc-c++
- gettext
- gobject-introspection
- libtool
- liburing2-devel
- make
- pkg-config
- python3-flake8
- python3-notify2
- python3-psutil
- python3-setuptools
- python3-setuptools
- python3-tk
- python311
- python3-devel
- python311-devel
- swig
endef

View File

@@ -197,6 +197,33 @@ usage and how to update and add tests. Below is a quick overview of their
location and how to run them.
Using spread with local virtual machines
----------------------------------------
It may be convenient to use the spread tool to provision and run the test suite
in an ephemeral virtual machine. This allows testing in isolation from the
host, as well as testing across different commonly used distributions and their
real kernels.
```sh
sudo apt install git golang whois ovmf genisoimage qemu-utils qemu-system
go install github.com/snapcore/spread/cmd/spread@latest
git clone https://gitlab.com/zygoon/image-garden
make -C image-garden
sudo make -C image-garden install
image-garden make ubuntu-cloud-24.10.x86_64.run
cd $APPARMOR_PATH
git clean -xdf
~/go/bin/spread -artifacts ./spread-artifacts -v ubuntu-cloud-24.10
# or ~/go/bin/spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
```
Running the `run_spread.sh` script, with `spread` on `PATH` will run all the
tests across several supported systems (Debian, Ubuntu and openSUSE).
If you include a `bzImage` file in the root of the repository then that kernel
will be used in the integration test. Please look at `spread.yaml` for details.
Regression tests
----------------
For details on structure and adding tests, see

View File

@@ -488,7 +488,7 @@ static int filter_processes(struct process *processes,
*
* Return: 0 on success, else shell error code
*/
static int simple_filtered_count(FILE *outf, filters_t *filters,
static int simple_filtered_count(FILE *outf, filters_t *filters, bool json,
struct profile *profiles, size_t nprofiles)
{
struct profile *filtered = NULL;
@@ -497,7 +497,13 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
ret = filter_profiles(profiles, nprofiles, filters,
&filtered, &nfiltered);
fprintf(outf, "%zd\n", nfiltered);
if (!json) {
fprintf(outf, "%zd\n", nfiltered);
} else {
fprintf(outf, "\"profile_count\": %zd", nfiltered);
}
free_profiles(filtered, nfiltered);
return ret;
@@ -512,7 +518,7 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
*
* Return: 0 on success, else shell error code
*/
static int simple_filtered_process_count(FILE *outf, filters_t *filters,
static int simple_filtered_process_count(FILE *outf, filters_t *filters, bool json,
struct process *processes, size_t nprocesses) {
struct process *filtered = NULL;
size_t nfiltered;
@@ -520,7 +526,12 @@ static int simple_filtered_process_count(FILE *outf, filters_t *filters,
ret = filter_processes(processes, nprocesses, filters, &filtered,
&nfiltered);
fprintf(outf, "%zd\n", nfiltered);
if (!json) {
fprintf(outf, "%zd\n", nfiltered);
} else {
fprintf(outf, "\"process_count\": %zd", nfiltered);
}
free_processes(filtered, nfiltered);
return ret;
@@ -539,7 +550,12 @@ static int compare_processes_by_executable(const void *a, const void *b) {
static void json_header(FILE *outf)
{
fprintf(outf, "{\"version\": \"%s\", ", aa_status_json_version);
fprintf(outf, "{\"version\": \"%s\"", aa_status_json_version);
}
static void json_seperator(FILE *outf)
{
fprintf(outf, ", ");
}
static void json_footer(FILE *outf)
@@ -607,7 +623,7 @@ static int detailed_profiles(FILE *outf, filters_t *filters, bool json,
free_profiles(filtered, nfiltered);
}
if (json)
fprintf(outf, "}, ");
fprintf(outf, "}");
return AA_EXIT_ENABLED;
}
@@ -700,7 +716,7 @@ static int detailed_processes(FILE *outf, filters_t *filters, bool json,
fprintf(outf, "]");
}
fprintf(outf, "}\n");
fprintf(outf, "}");
}
exit:
@@ -1028,8 +1044,10 @@ int main(int argc, char **argv)
if (opt_json)
json_header(outf);
if (opt_show & SHOW_PROFILES) {
if (opt_json)
json_seperator(outf);
if (opt_count) {
ret = simple_filtered_count(outf, &filters,
ret = simple_filtered_count(outf, &filters, opt_json,
profiles, nprofiles);
} else {
ret = detailed_profiles(outf, &filters, opt_json,
@@ -1040,6 +1058,9 @@ int main(int argc, char **argv)
}
if (opt_show & SHOW_PROCESSES) {
if (opt_json)
json_seperator(outf);
struct process *processes = NULL;
size_t nprocesses = 0;
@@ -1047,7 +1068,7 @@ int main(int argc, char **argv)
if (ret != 0) {
eprintf("Failed to get processes: %d....\n", ret);
} else if (opt_count) {
ret = simple_filtered_process_count(outf, &filters,
ret = simple_filtered_process_count(outf, &filters, opt_json,
processes, nprocesses);
} else {
ret = detailed_processes(outf, &filters, opt_json,

View File

@@ -35,10 +35,7 @@ VERSION=$(shell cat $(COMMONDIR)/Version)
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
map = $(foreach a,$(2),$(call $(1),$(a)))
AWK:=$(shell which awk)
ifndef AWK
$(error awk utility required for build but not available)
endif
AWK?=$(or $(shell command -v awk),$(error awk utility required for build but not available))
define nl

View File

@@ -1 +1 @@
4.1.0~beta1
4.1.0~beta3

View File

@@ -149,8 +149,6 @@ typedef struct
char *net_foreign_addr;
unsigned long net_foreign_port;
char *execpath;
char *dbus_bus;
char *dbus_path;
char *dbus_interface;
@@ -167,6 +165,7 @@ typedef struct
char *net_addr;
char *peer_addr;
char *execpath;
} aa_log_record;
/**

View File

@@ -52,7 +52,7 @@ scanner.h: scanner.l
scanner.c: scanner.l
af_protos.h:
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dM - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dD - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h

View File

@@ -7,7 +7,7 @@ import sysconfig
import setuptools
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
if tuple(map(int, setuptools.__version__.split(".")[:2])) >= (62, 1):
identifier = sys.implementation.cache_tag
else:
identifier = "%d.%d" % sys.version_info[:2]

View File

@@ -0,0 +1 @@
[ 310.308737] audit: type=1400 audit(1724847289.985:631): apparmor="ALLOWED" operation="getsockname" class="net" profile="/usr/bin/wg" pid=15374 comm="wg" laddr=::ffff:127.0.0.1 lport=53131 faddr=::ffff:127.0.0.1 fport=51821 saddr=::ffff:127.0.0.1 src=53131 family="inet6" sock_type="dgram" protocol=17 requested="getattr" denied="getattr"

View File

@@ -0,0 +1,20 @@
START
File: testcase_network_12.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1724847289.985:631
Operation: getsockname
Mask: getattr
Denied Mask: getattr
Profile: /usr/bin/wg
Command: wg
PID: 15374
Network family: inet6
Socket type: dgram
Protocol: udp
Local addr: ::ffff:127.0.0.1
Foreign addr: ::ffff:127.0.0.1
Local port: 53131
Foreign port: 51821
Class: net
Epoch: 1724847289
Audit subid: 631

View File

@@ -0,0 +1,4 @@
/usr/bin/wg {
network (getattr) inet6 dgram ip=::ffff:127.0.0.1 port=53131,
}

View File

@@ -38,7 +38,7 @@ MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 aa-teardown.8 apparmor_xattrs
# parse.error=verbose supported from 3.0 so just test on that
# TODO move to autoconf
BISON_MAJOR:=$(shell bison --version | awk '/^bison/ { print ($$NF) }' | awk -F. '{print $$1 }')
USE_PARSE_ERROR:=$(shell test ${BISON_MAJOR} -ge 3 && echo true)
USE_PARSE_ERROR:=$(shell test "${BISON_MAJOR}" -ge 3 && echo true)
YACC := bison
YFLAGS := -d

View File

@@ -175,7 +175,7 @@ B<NETWORK PEER EXPR> = 'peer' '=' '(' ( I<NETWORK IP COND> | I<NETWORK PORT COND
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> )
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> | I<NETWORK PORT> '-' I<NETWORK PORT> )
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
@@ -996,13 +996,14 @@ can be represented by:
network ip=0.0.0.0; #allow INADDR_ANY
The network rules support the specification of local and remote IP
addresses and ports.
addresses, ports, and port ranges.
network ip=127.0.0.1 port=8080,
network peer=(ip=10.139.15.23 port=8081),
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
network port=8080 peer=(port=8081),
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
network ip=127.0.0.1 port=8080-8084,
=head2 Mount Rules

View File

@@ -43,7 +43,11 @@ optflag_table_t dumpflag_table[] = {
{ 1, "dfa-progress", "Dump dfa creation as in progress",
DUMP_DFA_PROGRESS | DUMP_DFA_STATS },
{ 1, "dfa-stats", "Dump dfa creation stats", DUMP_DFA_STATS },
{ 1, "dfa-states", "Dump dfa state diagram", DUMP_DFA_STATES },
{ 1, "dfa-states", "Dump final dfa state information", DUMP_DFA_STATES },
{ 1, "dfa-states-initial", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_INIT },
{ 1, "dfa-states-post-filter", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_FILTER },
{ 1, "dfa-states-post-minimize", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_POST_MINIMIZE },
{ 1, "dfa-states-post-unreachable", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_UNREACHABLE },
{ 1, "dfa-graph", "Dump dfa dot (graphviz) graph", DUMP_DFA_GRAPH },
{ 1, "dfa-minimize", "Dump dfa minimization", DUMP_DFA_MINIMIZE },
{ 1, "dfa-unreachable", "Dump dfa unreachable states",

View File

@@ -175,6 +175,28 @@ static inline int is_merged_x_consistent(int a, int b)
return 1;
}
/* Arbitrary max and minimum priority that userspace can specify,
* internally we handle up to MAX_INTERNAL_PRIORITY and
* MIN_INTERNAL_PRIORITY. Do not ever allow INT_MAX, or INT_MIN
* because cmp uses subtraction and it can cause overflow. Ensure we
* don't over/underflow make internal max/min one more than allowed on
* rules.
*
* see
* note on mediates_priority
*/
#define MIN_POLICY_PRIORITY (-1000)
#define MAX_POLICY_PRIORITY (1000)
/* internally we need a priority that any policy based rule can override
* and a priority that no policy based rule can override. These are
* used on rules encoding what abi/classes are supported by the
* compiled policy.
*/
#define MIN_INTERNAL_PRIORITY (MIN_POLICY_PRIORITY - 1)
#define MAX_INTERNAL_PRIORITY (MAX_POLICY_PRIORITY + 1)
#endif /* ! _IMMUNIX_H */
/* LocalWords: MMAP

View File

@@ -127,6 +127,13 @@ int io_uring_rule::gen_policy_re(Profile &prof)
audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;
/* add a mediates_io_uring rule for every rule added. It
* needs to be the same priority
*/
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
RULE_ALLOW, AA_MAY_READ, 0,
parseopts))
goto fail;
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
buf = buffer.str(); /* update buf to have label */

View File

@@ -14,6 +14,14 @@ AR ?= ar
CFLAGS ?= -g -Wall -O2 ${EXTRA_CFLAGS} -std=gnu++0x
CXXFLAGS := ${CFLAGS} ${INCLUDE_APPARMOR}
LIB_HDRS = aare_rules.h flex-tables.h apparmor_re.h hfa.h chfa.h parse.h \
expr-tree.h policy_compat.h
OTHER_HDRS = ../common_optarg.h ../common_flags.h ../immunix.h \
../policydb.h ../perms.h ../rule.h
HDRS = ${LIB_HDRS} ${OTHER_HDRS}
ARFLAGS=-rcs
BISON := bison
@@ -27,17 +35,17 @@ libapparmor_re.a: parse.o expr-tree.o hfa.o chfa.o aare_rules.o policy_compat.o
expr-tree.o: expr-tree.cc expr-tree.h
hfa.o: hfa.cc apparmor_re.h hfa.h ../immunix.h policy_compat.h
hfa.o: hfa.cc ${HDRS}
aare_rules.o: aare_rules.cc aare_rules.h apparmor_re.h expr-tree.h hfa.h chfa.h parse.h ../immunix.h
aare_rules.o: aare_rules.cc ${HDRS}
chfa.o: chfa.cc chfa.h ../immunix.h
chfa.o: chfa.cc ${HDRS}
policy_compat.o: policy_compat.cc policy_compat.h ../perms.h ../immunix.h
policy_compat.o: policy_compat.cc ${HDRS}
parse.o : parse.cc apparmor_re.h expr-tree.h
parse.o : parse.cc ${HDRS}
parse.cc : parse.y parse.h flex-tables.h ../immunix.h
parse.cc : parse.y ${HDRS}
${BISON} -o $@ $<
clean:

View File

@@ -258,6 +258,9 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
dfa.dump_uniq_perms("dfa");
if (opts.dump & DUMP_DFA_STATES_INIT)
dfa.dump(cerr);
/* since we are building a chfa, use the info about
* whether the chfa supports extended perms to help
* determine whether we clear the deny info.
@@ -265,23 +268,24 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
* information supported by the backed
*/
if (!extended_perms ||
// TODO: we should drop DFA_MINIMIZE check here but doing
// so changes behavior. Do as a separate patch and fixup
// tests, etc.
((opts.control & CONTROL_DFA_FILTER_DENY) &&
(opts.control & CONTROL_DFA_MINIMIZE)))
((opts.control & CONTROL_DFA_FILTER_DENY))) {
dfa.apply_and_clear_deny();
if (opts.dump & DUMP_DFA_STATES_POST_FILTER)
dfa.dump(cerr);
}
if (opts.control & CONTROL_DFA_MINIMIZE) {
dfa.minimize(opts);
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
dfa.dump_uniq_perms("minimized dfa");
if (opts.dump & DUMP_DFA_STATES_POST_MINIMIZE)
dfa.dump(cerr);
}
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE) {
dfa.remove_unreachable(opts);
if (opts.dump & DUMP_DFA_STATES_POST_UNREACHABLE)
dfa.dump(cerr);
}
if (opts.dump & DUMP_DFA_STATES)
dfa.dump(cerr);
@@ -310,7 +314,19 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
//cerr << "Checking extended perms " << extended_perms << "\n";
if (extended_perms) {
//cerr << "creating permstable\n";
dfa.compute_perms_table(perms_table, prompt);
dfa.compute_perms_table(perms_table, prompt);
// TODO: move perms table to a class
if (opts.dump & DUMP_DFA_TRANS_TABLE && perms_table.size()) {
cerr << "Perms Table size: " << perms_table.size() << "\n";
perms_table[0].dump_header(cerr);
for (size_t i = 0; i < perms_table.size(); i++) {
perms_table[i].dump(cerr);
cerr << "accept1: 0x";
cerr << ", accept2: 0x";
cerr << "\n";
}
cerr << "\n";
}
}
chfa = new CHFA(dfa, eq, opts, extended_perms, prompt);
if (opts.dump & DUMP_DFA_TRANS_TABLE)

View File

@@ -90,8 +90,10 @@ public:
else
node = new MatchFlag(priority, perms, audit);
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
if (val.second == false)
if (val.second == false) {
delete node;
return val.first->second;
}
return node;
}
return res->second;

View File

@@ -60,5 +60,9 @@
#define DUMP_RULE_MERGE (1 << 22)
#define DUMP_DFA_STATE32 (1 << 23)
#define DUMP_DFA_FLAGS_TABLE (1 << 24)
#define DUMP_DFA_STATES_INIT (1 << 25)
#define DUMP_DFA_STATES_POST_FILTER (1 << 26)
#define DUMP_DFA_STATES_POST_MINIMIZE (1 << 27)
#define DUMP_DFA_STATES_POST_UNREACHABLE (1 << 28)
#endif /* APPARMOR_RE_H */

View File

@@ -307,11 +307,16 @@ void CHFA::dump(ostream &os)
st.insert(make_pair(i->second, i->first));
}
os << "size=" << default_base.size() << " (accept, default, base): {state} -> {default state}" << "\n";
os << "size=" << default_base.size() << " (accept, accept2, default, base): {state} -> {default state}" << "\n";
for (size_t i = 0; i < default_base.size(); i++) {
os << i << ": ";
os << "(" << accept[i] << ", " << num[default_base[i].first]
<< ", " << default_base[i].second << ")";
os << "(" << accept[i] << ", ";
if (accept2.size() > 0)
os << accept2[i];
else
os << "---, ";
os << num[default_base[i].first] << ", " <<
default_base[i].second << ")";
if (st[i])
os << " " << *st[i];
if (default_base[i].first)

View File

@@ -890,7 +890,7 @@ public:
{
type_flags |= NODE_TYPE_MATCHFLAG;
}
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << '>'; }
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << std::dec << '>'; }
int priority;
perm32_t perms;

View File

@@ -1334,8 +1334,7 @@ void DFA::compute_perms_table(vector <aa_perms> &perms_table, bool prompt)
perms_table.resize(states.size() * mult);
// nonmatching and start need to be 0 and 1 so handle outside of loop
if (filedfa)
compute_perms_table_ent(nonmatching, 0, perms_table, prompt);
compute_perms_table_ent(nonmatching, 0, perms_table, prompt);
compute_perms_table_ent(start, 1, perms_table, prompt);
for (Partition::iterator i = states.begin(); i != states.end(); i++) {

View File

@@ -52,7 +52,7 @@ ostream &operator<<(ostream &os, State &state);
class perms_t {
public:
perms_t(void): priority(INT_MIN), allow(0), deny(0), prompt(0), audit(0), quiet(0), exact(0) { };
perms_t(void): priority(MIN_INTERNAL_PRIORITY), allow(0), deny(0), prompt(0), audit(0), quiet(0), exact(0) { };
bool is_accept(void) { return (allow | deny | prompt | audit | quiet); }
@@ -68,7 +68,7 @@ public:
}
void clear(void) {
priority = INT_MIN;
priority = MIN_INTERNAL_PRIORITY;
allow = deny = prompt = audit = quiet = exact = 0;
}
void clear(int p) {
@@ -131,12 +131,23 @@ public:
*/
}
/* returns true if perm is no longer accept */
int apply_and_clear_deny(void)
{
if (deny) {
allow &= ~deny;
exact &= ~deny;
prompt &= ~deny;
quiet &= deny;
/* don't change audit or quiet based on clearing
* deny at this stage. This was made unique in
* accept_perms, and the info about whether
* we are auditing or quieting based on the explicit
* deny has been discarded and can only be inferred.
* But we know it is correct from accept_perms()
* audit &= deny;
* quiet &= deny;
*/
deny = 0;
return !is_accept();
}
@@ -282,9 +293,9 @@ public:
{
accept1 = perms.allow;
if (prompt && prompt_compat_mode == PROMPT_COMPAT_DEV)
accept2 = PACK_AUDIT_CTL(perms.prompt, perms.quiet & perms.deny);
accept2 = PACK_AUDIT_CTL(perms.prompt, perms.quiet);
else
accept2 = PACK_AUDIT_CTL(perms.audit, perms.quiet & perms.deny);
accept2 = PACK_AUDIT_CTL(perms.audit, perms.quiet);
accept3 = perms.prompt;
}

View File

@@ -182,6 +182,8 @@ struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2,
perms.prompt = dfa_user_allow(accept3);
perms.audit = dfa_user_audit(accept1, accept2);
perms.quiet = dfa_user_quiet(accept1, accept2);
if (accept1 & AA_COMPAT_CONT_MATCH)
perms.allow |= AA_CONT_MATCH;
/*
* This mapping is convulated due to history.

View File

@@ -247,8 +247,8 @@ static struct mnt_keyword_table mnt_opts_table[] = {
{"nodev", MS_NODEV, 0},
{"exec", 0, MS_NOEXEC},
{"noexec", MS_NOEXEC, 0},
{"sync", MS_SYNC, 0},
{"async", 0, MS_SYNC},
{"sync", MS_SYNCHRONOUS, 0},
{"async", 0, MS_SYNCHRONOUS},
{"remount", MS_REMOUNT, 0},
{"mand", MS_MAND, 0},
{"nomand", 0, MS_MAND},
@@ -313,10 +313,16 @@ static struct mnt_keyword_table mnt_conds_table[] = {
static ostream &dump_flags(ostream &os,
pair <unsigned int, unsigned int> flags)
{
bool is_first = true;
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))
(flags.second & mnt_opts_table[i].clear)) {
if (!is_first) {
os << ", ";
}
is_first = false;
os << mnt_opts_table[i].keyword;
}
}
return os;
}

View File

@@ -35,7 +35,7 @@
#define MS_DEV 0
#define MS_NOEXEC (1 << 3)
#define MS_EXEC 0
#define MS_SYNC (1 << 4)
#define MS_SYNCHRONOUS (1 << 4)
#define MS_ASYNC 0
#define MS_REMOUNT (1 << 5)
#define MS_MAND (1 << 6)
@@ -78,7 +78,7 @@
#define MS_RSHARED (MS_SHARED | MS_REC)
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
MS_SYNCHRONOUS | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
MS_NOSYMFOLLOW | \
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
MS_MOVE | MS_VERBOSE | MS_ACL | \
@@ -108,7 +108,13 @@
#define MS_MOVE_FLAGS (MS_MOVE)
#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))
/*
* This allows MS_MAKE_CMDS, by design: while remount and make-* shouldn't be
* used together, real-world applications do use them together, and the Linux
* kernel ignores the make-* flags when doing a remount instead of returning
* EINVAL. See https://bugs.launchpad.net/apparmor/+bug/2091424 for an example.
*/
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~MS_MOVE_FLAGS)
#define MS_NEW_FLAGS (MS_ALL_FLAGS & ~MS_CMDS)
#define MNT_SRC_OPT 1

View File

@@ -352,10 +352,41 @@ bool parse_port_number(const char *port_entry, uint16_t *port) {
return false;
}
bool parse_range(const char *range, uint16_t *from, uint16_t *to)
{
char *range_tmp = strdup(range);
char *dash = strchr(range_tmp, '-');
bool ret = false;
if (dash == NULL)
goto out;
*dash = '\0';
if (parse_port_number(range_tmp, from)) {
if (parse_port_number(dash + 1, to)) {
if (*from > *to) {
goto out;
}
ret = true;
goto out;
}
}
out:
free(range_tmp);
return ret;
}
bool network_rule::parse_port(ip_conds &entry)
{
entry.is_port = true;
return parse_port_number(entry.sport, &entry.port);
if (parse_range(entry.sport, &entry.from_port, &entry.to_port))
return true;
if (parse_port_number(entry.sport, &entry.from_port)) {
/* if range is not used, from and to have the same value */
entry.to_port = entry.from_port;
return true;
}
return false;
}
bool network_rule::parse_address(ip_conds &entry)
@@ -650,23 +681,23 @@ std::list<std::ostringstream> copy_streams_list(std::list<std::ostringstream> &s
return streams_copy;
}
bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd)
bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, uint16_t port, bool is_port, bool is_cmd)
{
std::string buf;
perm32_t cond_perms;
std::list<std::ostringstream> ip_streams;
for (auto &oss : streams) {
if (entry.is_port && !(entry.is_ip && entry.is_none)) {
if (is_port && !(entry.is_ip && entry.is_none)) {
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
if (!is_peer && perms & AA_NET_BIND && port < IPPORT_RESERVED)
oss << "\\x01";
else if (is_peer)
oss << "\\x02";
else
oss << "\\x00";
oss << gen_port_cond(entry.port);
oss << gen_port_cond(port);
} else {
/* port type + port number */
oss << "...";
@@ -690,7 +721,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
cond_perms = map_perms(perms);
if (!is_cmd && (label || is_peer))
cond_perms = (AA_CONT_MATCH << 1);
cond_perms = AA_COMPAT_CONT_MATCH;
for (auto &oss : streams) {
oss << "\\x00"; /* null transition */
@@ -764,68 +795,83 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
}
if (perms & AA_PEER_NET_PERMS) {
for (int peer_port = peer.from_port; peer_port <= peer.to_port; peer_port++) {
std::list<std::ostringstream> streams;
std::ostringstream cmd_buffer;
cmd_buffer << buffer.str();
streams.push_back(std::move(cmd_buffer));
if (!gen_ip_conds(prof, streams, peer, true, peer_port, peer.is_port, false))
return false;
for (auto &oss : streams) {
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
}
for (int local_port = local.from_port; local_port <= local.to_port; local_port++) {
std::list<std::ostringstream> localstreams;
for (auto &oss : streams) {
/* we need to copy streams because each local_port should be an unique entry */
std::ostringstream local_buffer;
local_buffer << oss.str();
localstreams.push_back(std::move(local_buffer));
}
if (!gen_ip_conds(prof, localstreams, local, false, local_port, local.is_port, true))
return false;
}
}
}
for (int local_port = local.from_port; local_port <= local.to_port; local_port++) {
std::list<std::ostringstream> streams;
std::ostringstream cmd_buffer;
std::ostringstream common_buffer;
cmd_buffer << buffer.str();
streams.push_back(std::move(cmd_buffer));
if (!gen_ip_conds(prof, streams, peer, true, false))
common_buffer << buffer.str();
streams.push_back(std::move(common_buffer));
if (!gen_ip_conds(prof, streams, local, false, local_port, local.is_port, false))
return false;
for (auto &oss : streams) {
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
if (perms & AA_NET_LISTEN) {
std::list<std::ostringstream> cmd_streams;
cmd_streams = copy_streams_list(streams);
for (auto &cmd_buffer : streams) {
std::ostringstream listen_buffer;
listen_buffer << cmd_buffer.str();
listen_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
/* length of queue allowed - not used for now */
listen_buffer << "..";
buf = listen_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
}
}
if (perms & AA_NET_OPT) {
std::list<std::ostringstream> cmd_streams;
cmd_streams = copy_streams_list(streams);
if (!gen_ip_conds(prof, streams, local, false, true))
return false;
}
std::list<std::ostringstream> streams;
std::ostringstream common_buffer;
common_buffer << buffer.str();
streams.push_back(std::move(common_buffer));
if (!gen_ip_conds(prof, streams, local, false, false))
return false;
if (perms & AA_NET_LISTEN) {
std::list<std::ostringstream> cmd_streams;
cmd_streams = copy_streams_list(streams);
for (auto &cmd_buffer : streams) {
std::ostringstream listen_buffer;
listen_buffer << cmd_buffer.str();
listen_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
/* length of queue allowed - not used for now */
listen_buffer << "..";
buf = listen_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
}
}
if (perms & AA_NET_OPT) {
std::list<std::ostringstream> cmd_streams;
cmd_streams = copy_streams_list(streams);
for (auto &cmd_buffer : streams) {
std::ostringstream opt_buffer;
opt_buffer << cmd_buffer.str();
opt_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
/* level - not used for now */
opt_buffer << "..";
/* socket mapping - not used for now */
opt_buffer << "..";
buf = opt_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
for (auto &cmd_buffer : streams) {
std::ostringstream opt_buffer;
opt_buffer << cmd_buffer.str();
opt_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
/* level - not used for now */
opt_buffer << "..";
/* socket mapping - not used for now */
opt_buffer << "..";
buf = opt_buffer.str();
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
rule_mode, map_perms(perms),
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
parseopts))
return false;
}
}
}

View File

@@ -130,7 +130,9 @@ public:
bool is_ip = false;
bool is_port = false;
uint16_t port;
uint16_t from_port = 0;
uint16_t to_port = 0;
struct ip_address ip;
bool is_none = false;
@@ -187,7 +189,7 @@ public:
}
};
bool gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd);
bool gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, uint16_t port, bool is_port, bool is_cmd);
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol);
void set_netperm(unsigned int family, unsigned int type, unsigned int protocol);
void update_compat_net(void);

View File

@@ -53,12 +53,6 @@ using namespace std;
*/
extern int parser_token;
/* Arbitrary max and minimum priority that userspace can specify, internally
* we handle up to INT_MAX and INT_MIN. Do not ever allow INT_MAX, see
* note on mediates_priority
*/
#define MAX_PRIORITY 1000
#define MIN_PRIORITY -1000
#define WARN_RULE_NOT_ENFORCED 0x1
#define WARN_RULE_DOWNGRADED 0x2

View File

@@ -110,7 +110,12 @@ FILE *ofile = NULL;
IncludeCache_t *g_includecache;
optflags parseopts = {
.control = (optflags_t)(CONTROL_DFA_TREE_NORMAL | CONTROL_DFA_TREE_SIMPLE | CONTROL_DFA_MINIMIZE | CONTROL_DFA_DIFF_ENCODE | CONTROL_RULE_MERGE),
.control = (optflags_t)(CONTROL_DFA_TREE_NORMAL | CONTROL_DFA_TREE_SIMPLE | CONTROL_DFA_MINIMIZE | CONTROL_DFA_DIFF_ENCODE | CONTROL_RULE_MERGE |
/* TODO: remove when we have better auto
* selection on when/which explicit denies
* to remove
*/
CONTROL_DFA_FILTER_DENY),
.dump = 0,
.warn = DEFAULT_WARNINGS,
.Werror = 0

View File

@@ -54,6 +54,9 @@ static int file_comp(const void *c1, const void *c2)
if ((*e1)->audit != (*e2)->audit)
return (*e1)->audit < (*e2)->audit ? -1 : 1;
if ((*e1)->priority != (*e2)->priority)
return (*e2)->priority - (*e1)->priority;
return strcmp((*e1)->name, (*e2)->name);
}

View File

@@ -1079,6 +1079,8 @@ void debug_cod_entries(struct cod_entry *list)
debug_base_perm_mask(SHIFT_TO_BASE(item->perms, AA_USER_SHIFT));
printf(":");
debug_base_perm_mask(SHIFT_TO_BASE(item->perms, AA_OTHER_SHIFT));
printf(" priority=%d ", item->priority);
if (item->name)
printf("\tName:\t(%s)\n", item->name);
else
@@ -1122,6 +1124,8 @@ bool entry_add_prefix(struct cod_entry *entry, const prefixes &p, const char *&e
else if (p.owner == 2)
entry->perms &= (AA_OTHER_PERMS | AA_SHARED_PERMS);
entry->priority = p.priority;
/* implied audit modifier */
if (p.audit == AUDIT_FORCE && (entry->rule_mode != RULE_DENY))
entry->audit = AUDIT_FORCE;

View File

@@ -1093,9 +1093,21 @@ static const char *deny_file = ".*";
*
* Note: it turns out the above bug does exist for dbus rules in parsers
* that do not support priority, and we don't have a way to fix it.
* We fix it here by capping user specified priority to be < INT_MAX.
* We fix it here by capping user specified priority to be less than
* MAX_INTERNAL_PRIORITY.
*/
static int mediates_priority = INT_MAX;
static int mediates_priority = MAX_INTERNAL_PRIORITY;
/* some rule types unfortunately encoded permissions on the class byte
* to fix the above bug, they need a different solution. The generic
* mediates rule will get encoded at the minimum priority, and then
* for every rule of those classes a mediates rule of the same priority
* will be added. This way the mediates rule never has higher priority,
* which would wipe out the rule permissions encoded on the class state,
* and it is guaranteed to have the same priority as the highest priority
* rule.
*/
static int perms_onclass_mediates_priority = MIN_INTERNAL_PRIORITY;
int process_profile_policydb(Profile *prof)
{
@@ -1112,7 +1124,7 @@ int process_profile_policydb(Profile *prof)
* to be supported
*/
if (features_supports_userns &&
!prof->policy.rules->add_rule(mediates_ns, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_ns, perms_onclass_mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
/* don't add mediated classes to unconfined profiles */
@@ -1148,7 +1160,7 @@ int process_profile_policydb(Profile *prof)
!prof->policy.rules->add_rule(mediates_sysv_mqueue, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
if (features_supports_io_uring &&
!prof->policy.rules->add_rule(mediates_io_uring, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
!prof->policy.rules->add_rule(mediates_io_uring, perms_onclass_mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
goto out;
}

View File

@@ -640,10 +640,10 @@ opt_priority: { $$ = 0; }
yyerror("invalid priority %s", $3);
free($3);
/* see note on mediates_priority */
if (tmp > MAX_PRIORITY)
yyerror("invalid priority %l > %d", tmp, MAX_PRIORITY);
if (tmp < MIN_PRIORITY)
yyerror("invalid priority %l > %d", tmp, MIN_PRIORITY);
if (tmp > MAX_POLICY_PRIORITY)
yyerror("invalid priority %l > %d", tmp, MAX_POLICY_PRIORITY);
if (tmp < MIN_POLICY_PRIORITY)
yyerror("invalid priority %l > %d", tmp, MIN_POLICY_PRIORITY);
$$ = tmp;
}

View File

@@ -24,6 +24,11 @@
* older versions
*/
#include <ostream>
#include <iostream>
using std::ostream;
using std::cerr;
#include <stdint.h>
#include <sys/apparmor.h>
@@ -65,6 +70,9 @@
#define AA_MAY_DELEGATE
#define AA_CONT_MATCH 0x08000000
// TODO: move into a reworked immunix.h that is dependent on perms.h
#define AA_COMPAT_CONT_MATCH (AA_CONT_MATCH << 1)
#define AA_MAY_STACK 0x10000000
#define AA_MAY_ONEXEC 0x20000000 /* either stack or change_profile */
#define AA_MAY_CHANGE_PROFILE 0x40000000
@@ -79,7 +87,7 @@
* - exec type - which determines how the executable name and index are used
* - flags - which modify how the destination name is applied
*/
#define AA_X_INDEX_MASK AA_INDEX_MASK
#define AA_X_INDEX_MASK 0xffffff
#define AA_X_TYPE_MASK 0x0c000000
#define AA_X_NONE AA_INDEX_NONE
@@ -93,7 +101,8 @@
typedef uint32_t perm32_t;
struct aa_perms {
class aa_perms {
public:
perm32_t allow;
perm32_t deny; /* explicit deny, or conflict if allow also set */
@@ -112,6 +121,33 @@ struct aa_perms {
uint32_t xindex;
uint32_t tag; /* tag string index, if present */
uint32_t label; /* label string index, if present */
void dump_header(ostream &os)
{
os << "(allow/deny/prompt//audit/quiet//xindex)\n";
}
void dump(ostream &os)
{
os << std::hex << "(0x" << allow << "/0x" << deny << "/0x"
<< prompt << "//0x" << audit << "/0x" << quiet
<< std::dec << "//";
if (xindex & AA_X_UNSAFE)
os << "unsafe ";
if (xindex & AA_X_TYPE_MASK) {
if (xindex & AA_X_CHILD)
os << "c";
else
os << "p";
}
if (xindex & AA_X_INHERIT)
os << "i";
if (xindex & AA_X_UNCONFINED)
os << "u";
os << (xindex & AA_X_INDEX_MASK);
os << ")";
}
};
#endif /* __AA_PERM_H */

View File

@@ -252,9 +252,9 @@ public:
tmp = (int) rule_mode - (int) rhs.rule_mode;
if (tmp != 0)
return tmp;
if ((uint) owner < (uint) rhs.owner)
if ((unsigned int) owner < (unsigned int) rhs.owner)
return -1;
if ((uint) owner > (uint) rhs.owner)
if ((unsigned int) owner > (unsigned int) rhs.owner)
return 1;
return 0;
}

View File

@@ -28,11 +28,104 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-${_SCRIPTDIR}/../apparmor_parser}"
fails=0
errors=0
verbose="${VERBOSE:-}"
default_features_file="features.all"
features_file=$default_features_file
retain=0
dumpdfa=0
testtype=""
description="Manually run test"
tmpdir=$(mktemp -d /tmp/eq.$$-XXXXXX)
chmod 755 ${tmpdir}
export tmpdir
map_priority()
{
if [ -z "$1" -o "$1" == "priority=0" ] ; then
echo "0";
elif [ "$1" == "priority=-1" ] ; then
echo "-1"
elif [ "$1" == "priority=1" ] ;then
echo "1"
else
echo "unknown priority '$1'"
exit 1
fi
}
priority_eq()
{
local p1=$(map_priority "$1")
local p2=$(map_priority "$2")
if [ $p1 -eq $p2 ] ; then
return 0
fi
return 1
}
priority_lt()
{
local p1=$(map_priority "$1")
local p2=$(map_priority "$2")
if [ $p1 -lt $p2 ] ; then
return 0
fi
return 1
}
priority_gt()
{
local p1=$(map_priority "$1")
local p2=$(map_priority "$2")
if [ $p1 -gt $p2 ] ; then
return 0
fi
return 1
}
hash_binary_policy()
{
printf %s "$1" | ${APPARMOR_PARSER} --features-file "${_SCRIPTDIR}/features_files/features.all" -qS 2>/dev/null| md5sum | cut -d ' ' -f 1
return $?
local hash="parser_failure"
local dump="/dev/null"
local flags="-QKSq"
local rc=0
if [ $dumpdfa -ne 0 ] ; then
flags="$flags -D rule-exprs -D dfa-states"
dump="${tmpdir}/$1.state"
fi
printf %s "$2" | ${APPARMOR_PARSER} --features-file "${_SCRIPTDIR}/features_files/$features_file" ${flags} > "$tmpdir/$1.bin" 2>"$dump"
rc=$?
if [ $rc -eq 0 ] ; then
hash=$(sha256sum "${tmpdir}/$1.bin" | cut -d ' ' -f 1)
rc=$?
fi
printf %s $hash
if [ $retain -eq 0 -a $rc -ne 0 ] ; then
rm ${tmpdir}/*
else
mv "${tmpdir}/$1.bin" "${tmpdir}/$1.bin.$hash"
if [ $dumpdfa -ne 0 ] ; then
mv "${tmpdir}/$1.state" "$tmpdir/$1.state.$hash"
fi
fi
return $rc
}
check_retain()
{
if [ ${retain} -ne 0 ] ; then
printf " files retained in \"%s/\"\n" ${tmpdir} 1>&2
exit $ret
fi
}
# verify_binary - compares the binary policy of multiple profiles
@@ -55,26 +148,28 @@ verify_binary()
shift
shift
if [ "$t" != "equality" ] && [ "$t" != "inequality" ]
if [ "$t" != "equality" ] && [ "$t" != "inequality" ] && \
[ "$t" != "xequality" ] && [ "$t" != "xinequality" ]
then
printf "\nERROR: Unknown test mode:\n%s\n\n" "$t" 1>&2
((errors++))
return $((ret + 1))
fi
rm -f $tmpdir/*
if [ -n "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
if ! good_hash=$(hash_binary_policy "$good_profile")
then
if ! good_hash=$(hash_binary_policy "known" "$good_profile") ; then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nERROR: Error hashing the following \"known-good\" profile:\n%s\n\n" \
"$good_profile" 1>&2
((errors++))
rm -f ${tmpdir}/*
return $((ret + 1))
fi
for profile in "$@"
do
if ! hash=$(hash_binary_policy "$profile")
if ! hash=$(hash_binary_policy "test" "$profile")
then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nERROR: Error hashing the following profile:\n%s\n\n" \
@@ -84,20 +179,52 @@ verify_binary()
elif [ "$t" == "equality" ] && [ "$hash" != "$good_hash" ]
then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nFAIL: Hash values do not match\n" 2>&1
printf "known-good (%s) != profile-under-test (%s) for the following profile:\n%s\n\n" \
"$good_hash" "$hash" "$profile" 1>&2
printf "\nFAIL: Hash values do not match\n" 1>&2
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
printf "known-good (%s) != profile-under-test (%s) for the following profiles:\nknown-good %s\nprofile-under-test %s\n\n" \
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
((fails++))
((ret++))
check_retain
elif [ "$t" == "xequality" ] && [ "$hash" == "$good_hash" ]
then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nunexpected PASS: equality test with known problem, Hash values match\n" 1>&2
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
printf "known-good (%s) == profile-under-test (%s) for the following profile:\nknown-good %s\nprofile-under-test %s\n\n" \
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
((fails++))
((ret++))
check_retain
elif [ "$t" == "xequality" ] && [ "$hash" != "$good_hash" ]
then
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
elif [ "$t" == "inequality" ] && [ "$hash" == "$good_hash" ]
then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nFAIL: Hash values match\n" 2>&1
printf "known-good (%s) == profile-under-test (%s) for the following profile:\n%s\n\n" \
"$good_hash" "$hash" "$profile" 1>&2
printf "\nFAIL: Hash values match\n" 1>&2
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
printf "known-good (%s) == profile-under-test (%s) for the following profiles:\nknown-good %s\nprofile-under-test %s\n\n" \
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
((fails++))
((ret++))
check_retain
elif [ "$t" == "xinequality" ] && [ "$hash" != "$good_hash" ]
then
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
printf "\nunexpected PASS: inequality test with known problem, Hash values do not match\n" 1>&2
printf "parser: %s -QKSq --features-file %s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
printf "known-good (%s) != profile-under-test (%s) for the following profile:\nknown-good %s\nprofile-under-test %s\n\n" \
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
((fails++))
((ret++))
check_retain
elif [ "$t" == "xinequality" ] && [ "$hash" == "$good_hash" ]
then
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
fi
rm -f ${tmpdir}/test*
done
if [ $ret -eq 0 ]
@@ -117,11 +244,56 @@ verify_binary_equality()
verify_binary "equality" "$@"
}
# test we want to be equal but is currently a known problem
verify_binary_xequality()
{
verify_binary "xequality" "$@"
}
verify_binary_inequality()
{
verify_binary "inequality" "$@"
}
# test we want to be not equal but is currently a know problem
verify_binary_xinequality()
{
verify_binary "xinequality" "$@"
}
# kernel_features - test whether path(s) are present
# $@: feature path(s) to test
# Returns: 0 and outputs "true" if all paths exist
# 1 and error message if features dir is not available
# 2 and error message if path does not exist
kernel_features()
{
features_dir="/sys/kernel/security/apparmor/features/"
if [ ! -e "$features_dir" ] ; then
echo "Kernel feature masks not supported."
return 1;
fi
for f in $@ ; do
if [ ! -e "$features_dir/$f" ] ; then
# check if feature is in file
feature=$(basename "$features_dir/$f")
file=$(dirname "$features_dir/$f")
if [ -f $file ]; then
if ! grep -q $feature $file; then
echo "Required feature '$f' not available."
return 2;
fi
else
echo "Required feature '$f' not available."
return 3;
fi
fi
done
echo "true"
return 0;
}
##########################################################################
### wrapper fn, should be indented but isn't to reduce wrap
@@ -129,7 +301,7 @@ verify_set()
{
local p1="$1"
local p2="$2"
echo -e "\n equality $e of '$p1' vs '$p2'\n"
[ -n "${verbose}" ] && echo -e "\n equality $e of '$p1' vs '$p2'\n"
verify_binary_equality "'$p1'x'$p2' dbus send" \
"/t { $p1 dbus send, }" \
@@ -477,37 +649,86 @@ do
"pix -> b" "Pix -> b" "cux -> b" "Cux -> b" \
"cix -> b" "Cix -> b"
do
if [ "$perm1" == "$perm2" ] ; then
# Fixme: have to do special handling for -> b, as this
# creates an entry in the transition table. However
# priority rules can make it so the reference to the
# transition table is removed, but the parser still keeps
# the tranition. This can lead to a situation where the
# test dfa with a "-> b" transition is functionally equivalent
# but will fail equality comparison.
# fix this by adding two none overlapping x rules to add
# xtable entries
# /c -> /t//b, for cx rules being converted to px -> /t//b
# /a -> b, for px rules
# the rules must come last guarantee xtable order
if [ "$perm1" == "$perm2" ] || priority_gt "$p1" "" ; then
verify_binary_equality "'$p1'x'$p2' Exec perm \"${perm1}\" - most specific match: same as glob" \
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
"/t { $p2 /* ${perm1}, }"
"/t { $p1 /f* ${perm1}, /f ${perm2}, /a px -> b, /c px -> /t//b, }" \
"/t { $p2 /f* ${perm1}, /a px -> b, /c px -> /t//b, }"
else
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs \"${perm2}\" - most specific match: different from glob" \
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
"/t { $p2 /* ${perm1}, }"
"/t { $p1 /f* ${perm1}, /f ${perm2}, /a px -> b, /c px -> /t//b, }" \
"/t { $p2 /f* ${perm1}, /a px -> b, /c px -> /t//b, }"
fi
done
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
"/t { $p2 /* ${perm1}, }"
if priority_gt "$p1" "" ; then
# priority stops permission carve out
verify_binary_equality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
"/t { $p2 /* ${perm1}, }"
else
# deny rule carves out some of the match
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
"/t { $p2 /* ${perm1}, }"
fi
done
#Test deny carves out permission
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
if priority_gt "$p1" "" ; then
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[abc] r, }"
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[ac] r, }"
#this one may not be true in the future depending on if the compiled profile
#is explicitly including deny permissions for dynamic composition
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
"/t { $p2 /foo/[abc] r, }"
elif priority_eq "$p1" "" ; then
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[abc] r, }"
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[ac] r, }"
#this one may not be true in the future depending on if the compiled profile
#is explicitly including deny permissions for dynamic composition
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
"/t { $p2 /foo/[abc] r, }"
else
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[abc] r, }"
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
"/t { $p2 /foo/[ac] r, }"
#this one may not be true in the future depending on if the compiled profile
#is explicitly including deny permissions for dynamic composition
verify_binary_inequality "'$p1'x'$p2' Deny of ungranted perm" \
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
"/t { $p2 /foo/[abc] r, }"
fi
verify_binary_equality "'$p1'x'$p2' change_profile == change_profile -> **" \
"/t { $p1 change_profile, }" \
@@ -587,9 +808,25 @@ verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc
# the "write" permission in the second profile and the test will fail.
# If the parser is adding the change_hat proc attr rules then the
# rules should merge and be equivalent.
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
#
# if priorities are different then the implied rule priority then the
# implied rule will completely override or completely be overriden.
# (the change_hat implied rule has a priority of 0)
# because of the difference in 'a' vs 'w' permission the two rules should
# only be equal when the append rule has the same priority as the implied
# rule (allowing them to combine) AND the other rule is not overridden by
# the implied rule, or both being overridden by the implied rule
# the implied rule
if { priority_lt "$p1" "" && priority_lt "$p2" "" ; } ||
{ priority_eq "$p1" "" && ! priority_lt "$p2" "" ; }; then
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
else
verify_binary_inequality "'$p1'x'$p2' change_hat rules automatically inserted"\
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
fi
# verify slash filtering for unix socket address paths.
# see https://bugs.launchpad.net/apparmor/+bug/1856738
@@ -677,7 +914,7 @@ verify_binary_equality "'$p1'x'$p2' mount specific deny doesn't affect non-overl
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
then
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 1>&2
exit $((fails + errors))
fi
@@ -758,12 +995,14 @@ verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
}
printf "Equality Tests:\n"
run_tests()
{
printf "Equality Tests:\n"
#rules that don't support priority
#rules that don't support priority
# verify rlimit data conversions
verify_binary_equality "set rlimit rttime <= 12 weeks" \
# verify rlimit data conversions
verify_binary_equality "set rlimit rttime <= 12 weeks" \
"/t { set rlimit rttime <= 12 weeks, }" \
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
@@ -773,7 +1012,7 @@ verify_binary_equality "set rlimit rttime <= 12 weeks" \
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
verify_binary_equality "set rlimit cpu <= 42 weeks" \
verify_binary_equality "set rlimit cpu <= 42 weeks" \
"/t { set rlimit cpu <= 42 weeks, }" \
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
@@ -781,39 +1020,209 @@ verify_binary_equality "set rlimit cpu <= 42 weeks" \
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
verify_binary_equality "set rlimit memlock <= 2GB" \
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)) , }"
# verify combinations of different priority levels
# for single rule comparisons, rules should keep same expected result
# even when the priorities are different.
# different priorities within a profile comparison resulting in
# different permission could affected expected results
priorities="none 0 1 -1"
for pri1 in $priorities ; do
if [ "$pri1" = "none" ] ; then
priority1=""
else
priority1="priority=$pri1"
fi
for pri2 in $priorities ; do
if [ "$pri2" = "none" ] ; then
priority2=""
run_port_range=$(kernel_features network_v8/af_inet)
if [ "$run_port_range" != "true" ]; then
echo -e "\nSkipping network af_inet tests. $run_port_range\n"
else
priority2="priority=$pri2"
# network port range
# select features file that contains netv8 af_inet
features_file="features.af_inet"
verify_binary_equality "network port range" \
"/t { network port=3456-3460, }" \
"/t { network port=3456, \
network port=3457, \
network port=3458, \
network port=3459, \
network port=3460, }"
verify_binary_equality "network peer port range" \
"/t { network peer=(port=3456-3460), }" \
"/t { network peer=(port=3456), \
network peer=(port=3457), \
network peer=(port=3458), \
network peer=(port=3459), \
network peer=(port=3460), }"
verify_binary_inequality "network port range allows more than single port" \
"/t { network port=3456-3460, }" \
"/t { network port=3456, }"
verify_binary_inequality "network peer port range allows more than single port" \
"/t { network peer=(port=3456-3460), }" \
"/t { network peer=(port=3456), }"
# return to default
features_file=$default_features_file
fi
verify_set "$priority1" "$priority2"
done
# Equality tests that set explicit priority level
# TODO: priority handling for file paths is currently broken
# This test is not actually correct due to two subtle
# interactions: - /* is special-cased to expand to /[^/\x00]+
# with at least one character - Quieting of [^a] in the DFA is
# different and cannot be manually fixed
#verify_binary_xequality "file rule carveout regex vs priority" \
# "/t { deny /[^a]* rwxlk, /a r, }" \
# "/t { priority=-1 deny /* rwxlk, /a r, }" \
# Not grouping all three together because parser correctly handles
# the equivalence of carveout regex and default audit deny
verify_binary_equality "file rule carveout regex vs priority (audit)" \
"/t { audit deny /[^a]* rwxlk, /a r, }" \
"/t { priority=-1 audit deny /* rwxlk, /a r, }"
verify_binary_equality "file rule default audit deny vs audit priority carveout" \
"/t { /a r, }" \
"/t { priority=-1 audit deny /* rwxlk, /a r, }"
# verify combinations of different priority levels
# for single rule comparisons, rules should keep same expected result
# even when the priorities are different.
# different priorities within a profile comparison resulting in
# different permission could affected expected results
priorities="none 0 1 -1"
for pri1 in $priorities ; do
if [ "$pri1" = "none" ] ; then
priority1=""
else
priority1="priority=$pri1"
fi
for pri2 in $priorities ; do
if [ "$pri2" = "none" ] ; then
priority2=""
else
priority2="priority=$pri2"
fi
verify_set "$priority1" "$priority2"
done
done
[ -z "${verbose}" ] && printf "\n"
printf "PASS\n"
exit 0
}
usage()
{
local progname="$0"
local rc="$1"
local msg="usage: ${progname} [Options]
Run the equality tests if no options given, otherwise run as directed
by the options.
Options:
-h, --help display this help
-e base args run an equality test on the following args
-n base args run an inequality test on the following args
-xequality run a known proble equality test
-xinequality run a known proble inequality test
-r on failure retain failed test output and abort
-d include dfa dumps with failed test output
-f arg features file to use
-p arg parser to invoke
--description description to print with test
-v verbose
examples:
$ equality.sh
...
$ equality.sh -r
....
inary equality 'priority=1'x'' Exec perm \"ux\" - most specific match: same as glob
FAIL: Hash values do not match
parser: ../apparmor_parser --config-file=./parser.conf --features-file=./features_files/features.all
known-good (0344cd377ccb239aba4cce768b818010961d68091d8c7fae72c755cfcb48d4a2) != profile-under-test (33fdf4575322a036c2acb75f93a7154179036f1189ef68ab9f1ae98e7f865780) for the following profiles:
known-good /t { priority=1 /* ux, /f px -> b, }
profile-under-test /t { /* ux, }
$ equality.sh -e \"/t { priority=1 /* Px -> b, /f Px, }\" \"/t { /* Px, }\"
$ equality.sh -e \"/t { priority=1 /* Px -> b, /f Px, }\" \"/t { /* Px, }\""
echo "$msg"
}
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
-e|--equality)
testtype="equality"
shift # past argument
;;
--xequality)
testtype="xequality"
shift # past argument
;;
-n|--inequality)
testtype="inequality"
shift # past argument
;;
--xinequality)
testtype="xinequality"
shift # past argument
;;
-d|--dfa)
dumpdfa=1
shift # past argument
;;
-r|--retain)
retain=1
shift # past argument
;;
-v|--verbose)
verbos=1
shift # past argument
;;
-f|--feature-file)
features_file="$2"
shift # past argument
shift # past option
;;
--description)
description="$2"
shift # past argument
shift # past option
;;
-p|--parser)
APPARMOR_PARSER="$2"
shift # past argument
shift # past option
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
[ -z "${verbose}" ] && printf "\n"
printf "PASS\n"
exit 0
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [ $# -eq 0 -o -z $testtype] ; then
run_tests "$@"
exit $?
fi
for profile in "$@" ; do
verify_binary "$testtype" "$description" "$known" "$profile"
done

View File

@@ -0,0 +1,117 @@
capability {0xffffff
}
caps {extended {yes
}
mask {chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read perfmon bpf checkpoint_restore
}
}
dbus {mask {acquire send receive
}
}
domain {attach_conditions {xattr {yes
}
}
change_hat {yes
}
change_hatv {yes
}
change_onexec {yes
}
change_profile {yes
}
computed_longest_left {yes
}
disconnected.path {yes
}
fix_binfmt_elf_mmap {yes
}
interruptible {yes
}
kill.signal {yes
}
post_nnp_subset {yes
}
stack {yes
}
unconfined_allowed_children {yes
}
version {1.2
}
}
file {mask {create read write exec append mmap_exec link lock
}
}
io_uring {mask {sqpoll override_creds
}
}
ipc {posix_mqueue {create read write open delete setattr getattr
}
}
mount {mask {mount umount pivot_root
}
move_mount {detached
}
}
namespaces {mask {userns_create
}
pivot_root {no
}
profile {yes
}
userns_create {pciu&
}
}
network {af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
}
af_unix {yes
}
}
network_v8 {af_inet {yes
}
af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
}
}
policy {outofband {0x000001
}
permstable32 {allow deny subtree cond kill complain prompt audit quiet hide xindex tag label
}
permstable32_version {0x000003
}
set_load {yes
}
unconfined_restrictions {change_profile {yes
}
io_uring {0
}
userns {1
}
}
versions {v5 {yes
}
v6 {yes
}
v7 {yes
}
v8 {yes
}
v9 {yes
}
}
}
ptrace {mask {read trace
}
}
query {label {data {yes
}
multi_transaction {yes
}
perms {allow deny audit quiet
}
}
}
rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
}
}
signal {mask {hup int quit ill trap abrt bus fpe kill usr1 segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg xcpu xfsz vtalrm prof winch io pwr sys emt lost
}
}

View File

@@ -0,0 +1,7 @@
#
#=Description to rule priority out of low end of range
#=EXRESULT FAIL
#
/usr/bin/foo {
priority=-1001 /usr/bin/foo r,
}

View File

@@ -0,0 +1,7 @@
#
#=Description basic file rule priority outside high end of range.
#=EXRESULT FAIL
#
/usr/bin/foo {
priority=1001 /usr/bin/foo r,
}

View File

@@ -0,0 +1,12 @@
#
#=DESCRIPTION network port range conditional test
#=EXRESULT PASS
#
/usr/bin/foo {
network peer=(port=22-443),
network port=22-443,
network port=22-443 peer=(port=1-100),
network ip=127.0.0.1 port=3456-3457,
network ip=127.0.0.1 port=3456-3457 peer=(ip=127.0.0.2 port=8765-8770),
}

View File

@@ -99,6 +99,14 @@ int userns_rule::gen_policy_re(Profile &prof)
rule_mode, perms,
audit == AUDIT_FORCE ? perms : 0,
parseopts))
goto fail;
/* add a mediates_userns rule for every rule added. It
* needs to be the same priority
*/
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
RULE_ALLOW, AA_MAY_READ, 0,
parseopts))
goto fail;
}

View File

@@ -5,8 +5,9 @@
# permissions for querying dconf settings; granting write access should
# be specified in a specific application's profile.
/etc/dconf/** r,
owner @{run}/user/*/dconf/user r,
@{etc_ro}/dconf/** r,
# TODO: make w conditional when an override is available, so it can be moved to a portal.
owner @{run}/user/*/dconf/user rw,
owner @{HOME}/.config/dconf/user r,
# Include additions to the abstraction

View File

@@ -20,6 +20,12 @@
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
owner @{HOME}/.cache/mesa_shader_cache_db/ rw,
owner @{HOME}/.cache/mesa_shader_cache_db/index rwk,
owner @{HOME}/.cache/mesa_shader_cache_db/part*/ rw,
owner @{HOME}/.cache/mesa_shader_cache_db/part*/mesa_cache.db rwk,
owner @{HOME}/.cache/mesa_shader_cache_db/part*/mesa_cache.idx rwk,
# Fallback location when @{HOME}/.cache is not available
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/ rw,
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/index rw,

View File

@@ -2,6 +2,7 @@
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009-2011 Canonical Ltd.
# Copyright (C) 2011-2024 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
@@ -11,29 +12,11 @@
abi <abi/4.0>,
# Many programs wish to perform nameservice-like operations, such as
# looking up users by name or id, groups by name or id, hosts by name
# or IP, etc. These operations may be performed through files, dns,
# NIS, NIS+, LDAP, hesiod, wins, etc. Allow them all here.
@{etc_ro}/group r,
@{etc_ro}/host.conf r,
@{etc_ro}/hosts r,
@{etc_ro}/nsswitch.conf r,
@{etc_ro}/gai.conf r,
@{etc_ro}/passwd r,
@{etc_ro}/protocols r,
# On systems with authselect installed, /etc/nsswitch.conf is a symlink to /etc/authselect/nsswitch.conf
@{etc_ro}/authselect/nsswitch.conf r,
include <abstractions/nameservice-strict>
# libtirpc (used for NIS/YP login) needs this
@{etc_ro}/netconfig r,
# When using libnss-extrausers, the passwd and group files are merged from
# an alternate path
/var/lib/extrausers/group r,
/var/lib/extrausers/passwd r,
# When using sssd, the passwd and group files are stored in an alternate path
# and the nss plugin also needs to talk to a pipe
/var/lib/sss/mc/group r,
@@ -41,16 +24,13 @@
/var/lib/sss/mc/passwd r,
/var/lib/sss/pipes/nss rw,
@{etc_ro}/resolv.conf r,
# On systems where /etc/resolv.conf is managed programmatically, it is
# a symlink to @{run}/(whatever program is managing it)/resolv.conf.
@{run}/{resolvconf,NetworkManager,systemd/resolve,connman,netconfig}/resolv.conf r,
@{run}/{NetworkManager,connman,netconfig}/resolv.conf r,
@{etc_ro}/resolvconf/run/resolv.conf r,
@{run}/systemd/resolve/stub-resolv.conf r,
/mnt/wsl/resolv.conf r,
@{etc_ro}/samba/lmhosts r,
@{etc_ro}/services r,
# db backend
/var/lib/misc/*.db r,
# The Name Service Cache Daemon can cache lookups, sometimes leading
@@ -60,13 +40,19 @@
/{var/db,var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts} r,
# nscd renames and unlinks files in it's operation that clients will
# have open
@{run}/nscd/db* rmix,
@{run}/nscd/db* mix,
# make libnss-libvirt name resolution work.
/var/lib/libvirt/dnsmasq/* r,
# make libnss-libvirt name resolution work.
/var/lib/libvirt/dnsmasq/ r,
/var/lib/libvirt/dnsmasq/*.status r,
# The nss libraries are sometimes used in addition to PAM; make sure
# they are available
/{usr/,}lib{,32,64}/libnss_*.so* mr,
/{usr/,}lib/@{multiarch}/libnss_*.so* mr,
@{etc_ro}/default/nss r,
# avahi-daemon is used for mdns4 resolution
@{run}/avahi-daemon/socket rw,
@@ -93,9 +79,6 @@
# kerberos
include <abstractions/kerberosclient>
#libnss-systemd
include <abstractions/nss-systemd>
# Also allow lookups for systemd-exec's DynamicUsers via D-Bus
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
dbus send

View File

@@ -0,0 +1,40 @@
# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2019-2022 Mikhail Morfikov
# Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only
# Many programs wish to perform nameservice-like operations, such as looking up
# users by name or id, groups by name or id, hosts by name or IP, etc.
abi <abi/4.0>,
include <abstractions/nss-systemd>
@{etc_ro}/default/nss r,
@{etc_ro}/gai.conf r,
@{etc_ro}/group r,
@{etc_ro}/host.conf r,
@{etc_ro}/hosts r,
@{etc_ro}/nsswitch.conf r,
@{etc_ro}/passwd r,
@{etc_ro}/protocols r,
@{etc_ro}/resolv.conf r,
@{etc_ro}/services r,
# On systems with authselect installed, /etc/nsswitch.conf is a symlink to /etc/authselect/nsswitch.conf
@{etc_ro}/authselect/nsswitch.conf r,
# Alternative location for group & passwd files
/var/lib/extrausers/group r,
/var/lib/extrausers/passwd r,
/var/lib/nscd/group r,
/var/lib/nscd/passwd r,
@{run}/nscd/db* r,
@{run}/resolvconf/resolv.conf r,
@{run}/systemd/resolve/resolv.conf r,
@{run}/systemd/resolve/stub-resolv.conf r,
include if exists <abstractions/nameservice-strict.d>
# vim:syntax=apparmor

View File

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

View File

@@ -45,5 +45,10 @@
owner @{HOME}/.local/lib/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
owner @{HOME}/.local/lib/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/**/ r,
# Starting with Python 3.8, you can use the PYTHONPYCACHEPREFIX environment
# variable to define a cache directory for Python.
owner @{HOME}/.cache/Python/ rw,
owner @{HOME}/.cache/Python/** rw,
# Include additions to the abstraction
include if exists <abstractions/python.d>

View File

@@ -24,6 +24,7 @@ profile ping /{usr/,}bin/{,iputils-}ping {
/{,usr/}bin/{,iputils-}ping mixr,
/etc/modules.conf r,
@{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/bin.ping>

View File

@@ -4,7 +4,7 @@ abi <abi/4.0>,
include <tunables/global>
profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
profile php-fpm /usr/{bin,sbin}/php-fpm* flags=(attach_disconnected) {
# load common libraries and their support files
include <abstractions/base>
# resolve hostnames/usernames
@@ -32,15 +32,15 @@ profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
/var/log/php*-fpm.log rw,
# we need to be able to create all sockets
@{run}/php{,-fpm}/php*-fpm.pid rw,
@{run}/php{,-fpm,-fpm-legacy}/php*-fpm.pid rw,
@{run}/php*-fpm.pid rw,
@{run}/php{,-fpm}/php*-fpm.sock rwlk,
@{run}/php{,-fpm,-fpm-legacy}/*.sock{,et} rwlk,
# LP: #2061113
owner @{run}/systemd/notify w,
# to reload
/usr/sbin/php-fpm* rix,
/usr/{bin,sbin}/php-fpm* rix,
# no idea why php tries to open / read/write
deny / rw,

View File

@@ -7,6 +7,10 @@ include <tunables/global>
profile slirp4netns /usr/bin/slirp4netns flags=(unconfined) {
userns,
# pivot_root is required for running `slirp4netns --enable-sandbox` inside LXD.
# https://github.com/rootless-containers/slirp4netns/issues/348
pivot_root,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/slirp4netns>
}

View File

@@ -5,7 +5,7 @@ abi <abi/4.0>,
include <tunables/global>
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain) {
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain,attach_disconnected) {
# Don't use abstractions/transmission-common here, as the
# access needed is narrower than the user applications
include <abstractions/base>
@@ -47,7 +47,7 @@ profile transmission-cli /usr/bin/transmission-cli flags=(complain) {
include if exists <local/transmission-cli>
}
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain) {
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain,attach_disconnected) {
include <abstractions/transmission-common>
include <abstractions/dbus-session-strict>
include <abstractions/dconf>

View File

@@ -45,6 +45,7 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
/etc/SuSE-release r,
@{PROC}/@{pid}/mounts r,
@{PROC}/sys/fs/suid_dumpable r,
@{PROC}/sys/kernel/core_pattern r,
/usr/bin/doveconf rix,
/usr/lib*/dovecot/anvil mrPx,
/usr/lib*/dovecot/auth mrPx,

View File

@@ -13,6 +13,7 @@ profile smbd /usr/{bin,sbin}/smbd {
include <abstractions/wutmp>
capability audit_write,
capability chown,
capability dac_override,
capability dac_read_search,
capability fowner,

View File

@@ -17,6 +17,8 @@ profile zgrep /usr/bin/{x,}zgrep {
include <abstractions/bash>
/dev/tty rw,
@{etc_ro}/nsswitch.conf r,
/etc/passwd r,
/usr/bin/{ba,da,}sh ix,
/usr/bin/bzip2 Cx -> helper,
/usr/bin/cat ix,
@@ -35,6 +37,9 @@ profile zgrep /usr/bin/{x,}zgrep {
owner /tmp/zgrep* rw,
/usr/bin/zgrep r,
deny /etc/nsswitch.conf r,
deny /etc/passwd r,
include if exists <local/zgrep>
profile helper {

View File

@@ -1,17 +1,12 @@
# This profile allows almost everything and only exists to allow
# bwrap to work on a system with user namespace restrictions
# being enforced.
# bwrap is allowed access to user namespaces and capabilities
# within the user namespace, but its children do not have
# capabilities, blocking bwrap from being able to be used to
# arbitrarily by-pass the user namespace restrictions.
#
# Note: the bwrap child is stacked against the bwrap profile due to
# bwraps use of no-new-privs
# This profile allows almost everything and only exists to allow bwrap
# to work on a system with user namespace restrictions being enforced.
# bwrap is allowed access to user namespaces and capabilities within
# the user namespace, but its children do not have capabilities,
# blocking bwrap from being able to be used to arbitrarily by-pass the
# user namespace restrictions.
# disabled by default as it can break some use cases on a system that
# doesn't have or has disable user namespace restrictions for unconfined
# use aa-enforce to enable it
# Note: the bwrap child is stacked against the bwrap profile due to
# bwraps use of no-new-privs.
abi <abi/4.0>,
@@ -19,9 +14,11 @@ include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
allow capability,
# not allow all, to allow for pix stack
# sadly we have to allow m every where to allow children to work under
# stacking.
# not allow all, to allow for pix stack on systems that don't support
# rule priority.
#
# sadly we have to allow 'm' every where to allow children to work under
# profile stacking atm.
allow file rwlkm /{**,},
allow network,
allow unix,
@@ -34,7 +31,23 @@ profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
allow umount,
allow pivot_root,
allow dbus,
allow px /** -> bwrap//&unpriv_bwrap,
# stacked like this due to no-new-privs restriction
# this will stack a target profile against bwrap and unpriv_bwrap
# Ideally
# - there would be a transition at userns creation first. This would allow
# for the bwrap profile to be tighter, and looser within the user
# ns. bwrap will still have to fairly loose until a transition at
# namespacing in general (not just user ns) is available.
# - there would be an independent second target as fallback
# This would allow for select target profiles to be used, and not
# necessarily stack the unpriv_bwrap in cases where this is desired
#
# the ix works here because stack will apply to ix fallback
# Ideally we would sanitize the environment across a privilege boundry
# (leaving bwarp into application) but flatpak etc use environment glibc
# sanitized environment variables as part of the sandbox setup.
allow pix /** -> &bwrap//&unpriv_bwrap,
# the local include should not be used without understanding the userns
# restriction.
@@ -42,6 +55,7 @@ profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
include if exists <local/bwrap-userns-restrict>
}
# The unpriv_bwrap profile is used to strip capabilities within the userns
profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
# not allow all, to allow for pix stack
allow file rwlkm /{**,},
@@ -57,6 +71,9 @@ profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
allow pivot_root,
allow dbus,
# bwrap profile does stacking against itself this will keep the target
# profile from having elevated privileges in the container.
# If done recursively the stack will remove any duplicate
allow pix /** -> &unpriv_bwrap,
audit deny capability,

View File

@@ -13,12 +13,12 @@
include <tunables/global>
profile postfix-anvil /usr/lib/postfix/{bin/,sbin/,}anvil {
profile postfix-anvil /usr/lib{,exec}/postfix/{bin/,sbin/,}anvil {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}anvil mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}anvil mrix,
/etc/postfix/main.cf r,
/{var/spool/postfix/,}private/anvil rw,

View File

@@ -14,12 +14,12 @@
include <tunables/global>
profile postfix-bounce /usr/lib/postfix/{bin/,sbin/,}bounce {
profile postfix-bounce /usr/lib{,exec}/postfix/{bin/,sbin/,}bounce {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}bounce mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}bounce mrix,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwkl,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,

View File

@@ -14,7 +14,7 @@
include <tunables/global>
profile postfix-cleanup /usr/lib/postfix/{bin/,sbin/,}cleanup {
profile postfix-cleanup /usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
@@ -22,7 +22,7 @@ profile postfix-cleanup /usr/lib/postfix/{bin/,sbin/,}cleanup {
capability net_bind_service,
capability dac_read_search,
/usr/lib/postfix/{bin/,sbin/,}cleanup mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup mrix,
/{var/spool/postfix/,}incoming/[0-9]*.[0-9]* rwl,
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* rwl,

View File

@@ -14,10 +14,10 @@
include <tunables/global>
profile postfix-discard /usr/lib/postfix/{bin/,sbin/,}discard {
profile postfix-discard /usr/lib{,exec}/postfix/{bin/,sbin/,}discard {
include <abstractions/base>
/usr/lib/postfix/{bin/,sbin/,}discard mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}discard mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-discard>

View File

@@ -13,10 +13,10 @@
include <tunables/global>
profile postfix-dnsblog /usr/lib/postfix/{bin/,sbin/,}dnsblog {
profile postfix-dnsblog /usr/lib{,exec}/postfix/{bin/,sbin/,}dnsblog {
include <abstractions/base>
/usr/lib/postfix/{bin/,sbin/,}dnsblog mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}dnsblog mrix,
/var/spool/postfix/private/dnsblog rw,

View File

@@ -14,12 +14,12 @@
include <tunables/global>
profile postfix-error /usr/lib/postfix/{bin/,sbin/,}error {
profile postfix-error /usr/lib{,exec}/postfix/{bin/,sbin/,}error {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}error mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}error mrix,
owner /var/spool/postfix/active/* rwk,
/var/spool/postfix/pid/unix.error rwk,

View File

@@ -14,12 +14,12 @@
include <tunables/global>
profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
profile postfix-flush /usr/lib{,exec}/postfix/{bin/,sbin/,}flush {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}flush mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}flush mrix,
/{var/spool/postfix/,}deferred/ r,
/{var/spool/postfix/,}deferred/[0-9A-F]/[0-9A-F]/* rwl,

View File

@@ -14,12 +14,12 @@
include <tunables/global>
profile postfix-lmtp /usr/lib/postfix/{bin/,sbin/,}lmtp {
profile postfix-lmtp /usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}lmtp mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp mrix,
/var/spool/postfix/active/* rwk,
/var/spool/postfix/pid/unix.lmtp rwk,

View File

@@ -14,7 +14,7 @@
include <tunables/global>
profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
profile postfix-local /usr/lib{,exec}/postfix/{bin/,sbin/,}local {
include <abstractions/base>
include <abstractions/bash>
include <abstractions/nameservice>
@@ -27,7 +27,7 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
/var/mailman/mail/wrapper Px,
/usr/bin/mlmmj-recieve Px,
/usr/lib/postfix/{bin/,sbin/,}local mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}local mrix,
/{usr/,}bin/bash mixr,
/{usr/,}bin/date mixr,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-master /usr/lib/postfix/{bin/,sbin/,}master {
profile postfix-master /usr/lib{,exec}/postfix/{bin/,sbin/,}master {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
@@ -37,25 +37,28 @@ profile postfix-master /usr/lib/postfix/{bin/,sbin/,}master {
/{var/spool/postfix/,}private/tlsmgr rwl,
/{var/spool/postfix/,}public/{cleanup,flush,pickup,postlog,qmgr,showq,tlsmgr} rwl,
/usr/lib/postfix/{bin/,sbin/,}anvil Px,
/usr/lib/postfix/{bin/,sbin/,}bounce Px,
/usr/lib/postfix/{bin/,sbin/,}cleanup Px,
/usr/lib/postfix/{bin/,sbin/,}error Px,
/usr/lib/postfix/{bin/,sbin/,}flush Px,
/usr/lib/postfix/{bin/,sbin/,}local Px,
/usr/lib/postfix/{bin/,sbin/,}lmtp mrPx,
/usr/lib/postfix/{bin/,sbin/,}master mrix,
/usr/lib/postfix/{bin/,sbin/,}nqmgr Px,
/usr/lib/postfix/{bin/,sbin/,}proxymap Px,
/usr/lib/postfix/{bin/,sbin/,}pickup Px,
/usr/lib/postfix/{bin/,sbin/,}pipe Px,
/usr/lib/postfix/{bin/,sbin/,}qmgr Px,
/usr/lib/postfix/{bin/,sbin/,}scache Px,
/usr/lib/postfix/{bin/,sbin/,}showq Px,
/usr/lib/postfix/{bin/,sbin/,}smtp Px,
/usr/lib/postfix/{bin/,sbin/,}smtpd Px,
/usr/lib/postfix/{bin/,sbin/,}tlsmgr Px,
/usr/lib/postfix/{bin/,sbin/,}trivial-rewrite Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}anvil Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}bounce Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}error Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}flush Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}local Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp mrPx,
/usr/lib{,exec}/postfix/{bin/,sbin/,}master mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}pickup Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}pipe Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}postfix-tlsproxy Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}scache Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtp Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}spawn Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite Px,
owner /var/lib/postfix/master.lock rwk,

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-nqmgr /usr/lib/postfix/{bin/,sbin/,}nqmgr {
profile postfix-nqmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}nqmgr mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr mrix,
/{var/spool/postfix/,}active/ r,
/{var/spool/postfix/,}active/[0-9A-F]/ r,

View File

@@ -14,12 +14,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-oqmgr /usr/lib/postfix/{bin/,sbin/,}oqmgr {
profile postfix-oqmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}oqmgr {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}oqmgr mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}oqmgr mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-oqmgr>

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-pickup /usr/lib/postfix/{bin/,sbin/,}pickup {
profile postfix-pickup /usr/lib{,exec}/postfix/{bin/,sbin/,}pickup {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}pickup mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}pickup mrix,
/{var/spool/postfix/,}public/cleanup rw,
/{var/spool/postfix/,}public/pickup r,

View File

@@ -14,12 +14,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-pipe /usr/lib/postfix/{bin/,sbin/,}pipe {
profile postfix-pipe /usr/lib{,exec}/postfix/{bin/,sbin/,}pipe {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}pipe mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}pipe mrix,
/var/spool/postfix/active/* rwk,
/var/spool/postfix/private/bounce w,

View File

@@ -12,10 +12,13 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-postscreen /usr/lib/postfix/{bin/,sbin/,}postscreen {
profile postfix-postscreen /usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}postscreen mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen mrix,
owner /var/lib/postfix/{,__db.}postscreen_cache.db rwk,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-postscreen>

View File

@@ -14,14 +14,14 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-proxymap /usr/lib/postfix/{bin/,sbin/,}proxymap {
profile postfix-proxymap /usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/etc/my.cnf r,
/usr/lib/postfix/{bin/,sbin/,}proxymap mrix,
/{var/spool/postfix/,}private/proxymap rw,
/usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap mrix,
/{var/spool/postfix/,}private/proxymap rw,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-proxymap>

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-qmgr /usr/lib/postfix/{bin/,sbin/,}qmgr {
profile postfix-qmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}qmgr mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr mrix,
/{var/spool/postfix/,}active/ r,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-qmqpd /usr/lib/postfix/{bin/,sbin/,}qmqpd {
profile postfix-qmqpd /usr/lib{,exec}/postfix/{bin/,sbin/,}qmqpd {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}qmqpd mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmqpd mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-qmqpd>

View File

@@ -15,12 +15,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-scache /usr/lib/postfix/{bin/,sbin/,}scache {
profile postfix-scache /usr/lib{,exec}/postfix/{bin/,sbin/,}scache {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}scache mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}scache mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-scache>

View File

@@ -14,12 +14,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
profile postfix-showq /usr/lib{,exec}/postfix/{bin/,sbin/,}showq {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}showq mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq mrix,
/{var/spool/postfix/,}active/ r,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* r,
@@ -38,6 +38,7 @@ profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
/{var/spool/postfix/,}hold/[0-9A-F]/[0-9A-F]/* r,
/{var/spool/postfix/,}hold/[0-9A-F]/[0-9A-F]/ r,
/{var/spool/postfix/,}hold/[0-9A-F]/ r,
/{var/spool/postfix/,}hold/[0-9A-F]* r,
/{var/spool/postfix/,}incoming/ r,
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* r,
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ r,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
profile postfix-smtp /usr/lib{,exec}/postfix/{bin/,sbin/,}smtp {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
@@ -23,7 +23,7 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
capability dac_read_search,
capability net_bind_service,
/usr/lib/postfix/{bin/,sbin/,}smtp mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtp mrix,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
@@ -39,7 +39,7 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
/{var/spool/postfix/,}private/trace w,
/{var/spool/postfix/,}public/flush w,
/{var/spool/postfix/,}pid/unix.smtp rwk,
/{var/spool/postfix/,}pid/unix.relay rw,
/{var/spool/postfix/,}pid/unix.relay rwk,
/etc/postfix/{ssl/,}*.pem r,
/etc/postfix/prng_exch rw,
/usr/share/ssl/certs/ca-bundle.crt r,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
profile postfix-smtpd /usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
@@ -24,7 +24,7 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
capability dac_override,
capability dac_read_search,
/usr/lib/postfix/{bin/,sbin/,}smtpd mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd mrix,
/usr/sbin/postdrop rPx,
/dev/urandom r,
@@ -44,6 +44,7 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
/{var/spool/postfix/,}incoming/* rw,
/{var/spool/postfix/,}pid/inet.* rwk,
/{var/spool/postfix/,}pid/pass.smtpd rwk,
/{var/spool/postfix/,}private/anvil rw,
/{var/spool/postfix/,}private/proxymap rw,
/{var/spool/postfix/,}private/rewrite rw,

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-spawn /usr/lib/postfix/{bin/,sbin/,}spawn {
profile postfix-spawn /usr/lib{,exec}/postfix/{bin/,sbin/,}spawn {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}spawn mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}spawn mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-spawn>

View File

@@ -14,12 +14,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
profile postfix-tlsmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr mrix,
/var/spool/postfix/dev/urandom r,
/{etc,var/lib}/postfix/prng_exch rwk,

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2024 pyllyukko
#
# 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.
#
# ------------------------------------------------------------------
abi <abi/4.0>,
include <tunables/global>
profile postfix-tlsproxy /usr/lib{,exec}/postfix/{bin/,sbin/,}tlsproxy {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
include <abstractions/ssl_keys>
capability dac_read_search,
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsproxy mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-tlsproxy>
}

View File

@@ -14,14 +14,14 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-trivial-rewrite /usr/lib/postfix/{bin/,sbin/,}trivial-rewrite {
profile postfix-trivial-rewrite /usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
capability dac_read_search,
/usr/lib/postfix/{bin/,sbin/,}trivial-rewrite mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite mrix,
/etc/{m,fs}tab r,
/var/spool/postfix/pid/unix.rewrite rw,

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-verify /usr/lib/postfix/{bin/,sbin/,}verify {
profile postfix-verify /usr/lib{,exec}/postfix/{bin/,sbin/,}verify {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}verify mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}verify mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/postfix-verify>

View File

@@ -13,12 +13,12 @@ abi <abi/4.0>,
include <tunables/global>
profile postfix-virtual /usr/lib/postfix/{bin/,sbin/,}virtual {
profile postfix-virtual /usr/lib{,exec}/postfix/{bin/,sbin/,}virtual {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/postfix-common>
/usr/lib/postfix/{bin/,sbin/,}virtual mrix,
/usr/lib{,exec}/postfix/{bin/,sbin/,}virtual mrix,
/var/spool/postfix/active/* rw,
/var/spool/postfix/pid/unix.virtual rw,

View File

@@ -23,28 +23,28 @@ include <tunables/global>
/{usr/,}bin/cat ix,
/usr/bin/foomatic-rip ixr,
/etc/foomatic/** r,
@{etc_ro}/foomatic/** r,
/usr/bin/gs ix,
/usr/lib/ghostscript/** m,
/usr/lib64/ghostscript/** m,
/usr/share/ghostscript/** r,
/etc/ghostscript/** r,
@{etc_ro}/ghostscript/** r,
/dev/lp0 rw,
/dev/tty rw,
/dev/ttyS? w,
/etc/cups rw,
/etc/cups/ r,
/etc/cups/** r,
/etc/cups/certs w,
/etc/cups/certs/* w,
/etc/cups/*.conf* rw,
/etc/cups/ppd rw,
/etc/printcap rw,
/etc/cups/printcap rw,
/etc/cups/ssl rw,
/etc/cups/yes/* rw,
@{etc_rw}/cups rw,
@{etc_rw}/cups/ r,
@{etc_rw}/cups/** r,
@{etc_rw}/cups/certs w,
@{etc_rw}/cups/certs/* w,
@{etc_rw}/cups/*.conf* rw,
@{etc_rw}/cups/ppd rw,
@{etc_rw}/printcap rw,
@{etc_rw}/cups/printcap rw,
@{etc_rw}/cups/ssl rw,
@{etc_rw}/cups/yes/* rw,
@{PROC}/meminfo r,
@{PROC}/sys/dev/parport/** r,
/sys/class/usb r,
@@ -65,6 +65,8 @@ include <tunables/global>
/var/cache/cups/ rw,
/var/cache/cups/** rw,
@{etc_ro}/paperspecs r,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.sbin.cupsd>
}

View File

@@ -24,7 +24,7 @@ include <tunables/global>
/etc/postfix r,
/usr/sbin/postqueue rmix,
/usr/lib/postfix/{bin/,sbin/,}showq Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
/usr/share/icu/[0-9]*.[0-9]*/*.dat r,
/var/spool/postfix r,
/var/spool/postfix/maildrop r,

View File

@@ -46,10 +46,10 @@ include <tunables/global>
/root/dead.letter w,
/root/.forward rw,
/usr/kerberos/lib/lib*.so* mr,
/usr/lib/postfix/{bin/,sbin/,}master Px,
/usr/lib/postfix/{bin/,sbin/,}smtpd Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}master Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd Px,
/usr/lib/postfix r,
/usr/lib/postfix/{bin/,sbin/,}showq Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
/usr/lib/sasl2 r,
/usr/lib/sasl2/* mr,
/usr/lib/sasl r,

View File

@@ -28,8 +28,8 @@ include <tunables/global>
/etc/postfix/postfix-script Px,
@{PROC}/net/if_inet6 r,
/usr/lib/postfix r,
/usr/lib/postfix/{bin/,sbin/,}master Px,
/usr/lib/postfix/{bin/,sbin/,}showq Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}master Px,
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
/usr/sbin/postalias Px,
/usr/sbin/postdrop Px,
/usr/sbin/postqueue Px,

29
run-spread.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh
# Run integration tests with spread sequentially on all the systems, using
# multiple workers per system. This mode is suitable to run on a single
# quad-core CPU with 8GB of RAM and no desktop session.
set -xeu
if test -z "$(command -v spread)"; then
echo "You need to install spread from https://github.com/snapcore/spread with the Go compiler and the command: go install github.com/snapcore/spread/cmd/spread@latest" >&2
exit 1
fi
if test -z "$(command -v image-garden)"; then
echo "You need to install image-garden from https://gitlab.com/zygoon/image-garden: make install prefix=/usr/local" >&2
exit 1
fi
rm -rf spread-logs spread-artifacts
mkdir -p spread-logs
for system in \
opensuse-cloud-tumbleweed \
debian-cloud-12 \
debian-cloud-13 \
ubuntu-cloud-22.04 \
ubuntu-cloud-24.04 \
ubuntu-cloud-24.10; do
if ! spread -artifacts ./spread-artifacts -v "$system" | tee spread-logs/"$system".log; then
echo "Spread exited with code $?" >spread-logs/"$system".failed
fi
done

171
spread.yaml Normal file
View File

@@ -0,0 +1,171 @@
project: apparmor
backends:
garden:
# The garden backend relies on https://gitlab.com/zygoon/image-garden
# TODO: Switch to a released version for better stability.
type: adhoc
allocate: |
# Use just enough RAM to link the parser on a virtual system with
# two cores. Using more cores may easily consume more memory, due
# to make -j$(nproc), used below than a small CI/CD system is
# typically granted. It is better to have more workers than to
# have one big worker with lots of resources.
export QEMU_MEM_OPTION="-m 1536"
export QEMU_SMP_OPTION="-smp 2"
ARCH="$(uname -m)"
# If a locally built kernel image exist then use it for booting.
# Care needs to be taken to make sure the kernel is compatible with
# loadable modules present in the file system.
if [ -f bzImage ]; then
# Create the qcow2/run files before setting custom kernel
# options, so that first boot and initialization happen in a
# standardized manner.
image-garden make "$SPREAD_SYSTEM"."$ARCH".run "$SPREAD_SYSTEM"."$ARCH".qcow2 1>&2
# Pass a simple drive instead of the more elaborate virtio
# configuration that is used by default. Some images may not
# support virtio enough for booting.
export QEMU_STORAGE_OPTION="-drive file=$SPREAD_SYSTEM.$ARCH.qcow2,format=qcow2"
# Refrain from passing EFI firmware to qemu so that we boot a
# kernel directly and bypass both EFI and BIOS.
export QEMU_BOOT_FIRMWARE_OPTION=""
# Pass the kernel and cmdline by hand. At present this is tuned
# to the Ubuntu cloud images that have the rootfs as the first
# partition.
exec image-garden allocate "$SPREAD_SYSTEM"."$ARCH" \
-kernel bzImage \
-append 'root=/dev/sda1 ro console=tty1 console=ttyS0'
fi
# Ask image garden to allocate the system and relay the result back
# to spread as either success of failure.
exec image-garden allocate "$SPREAD_SYSTEM"."$ARCH"
discard: image-garden discard "$SPREAD_SYSTEM_ADDRESS"
systems:
# All systems except for the one Ubuntu system are marked as
# manual. This way we don't accidentally spin up everything when
# someone runs spread without knowing better.
- opensuse-cloud-tumbleweed:
username: opensuse
password: opensuse
workers: 4
manual: true
- debian-cloud-12:
username: debian
password: debian
workers: 4
manual: true
- debian-cloud-13:
username: debian
password: debian
workers: 4
manual: true
- ubuntu-cloud-22.04:
username: ubuntu
password: ubuntu
workers: 4
manual: true
- ubuntu-cloud-24.04:
username: ubuntu
password: ubuntu
workers: 4
manual: true
- ubuntu-cloud-24.10:
username: ubuntu
password: ubuntu
workers: 4
exclude:
- .git
- "*.o"
# Files related to spread and image-garden.
- "*.qcow2"
- "*.iso"
- "*.img"
- "*.log"
- "*.run"
- "*.lock"
- spread-logs
- spread-artifacts
# Locally provided kernel image. See allocate section in system backends,
# this image, if present, is passed directly to qemu.
- bzImage
# Copy the project to this path on the test system.
# This is also available as $SPREAD_PATH.
path: /tmp/apparmor
prepare: |
# Configure libapparmor but only if a makefile is not already present.
# This makes repeated iteration with -reuse much faster, as the chain of
# invocations of make below are efficient if nothing needs to be done.
if [ ! -f "$SPREAD_PATH"/libraries/libapparmor/Makefile ]; then
(
cd $SPREAD_PATH/libraries/libapparmor
sh ./autogen.sh && sh ./configure --prefix=/usr --with-perl --with-python
)
fi
# Build libapparmor.
make -C $SPREAD_PATH/libraries/libapparmor -j"$(nproc)"
# Build apparmor_parser.
make -C $SPREAD_PATH/parser -j"$(nproc)"
# Build binary utilities (aa-exec and firends).
make -C $SPREAD_PATH/binutils -j"$(nproc)"
# Build python utilities.
make -C $SPREAD_PATH/utils -j"$(nproc)"
# In case of failure, include the kernel version in the log.
debug-each: |
uname -a
suites:
utils/:
summary: Unit tests for the Python utilities.
prepare: |
# Generate apparmor profiles that the tests rely on.
make -C "$SPREAD_PATH"/parser/tst gen_xtrans gen_dbus
# Spread does not support programmatically generated test variants.
# Ensure that the list baked into utils/test/task.yaml contains all
# the files matching utils/test/test-*.py
fail=0
for V in $SPREAD_PATH/utils/test/test-*.py; do
Vdash="$(basename "$V" | sed -e 's,^test-,,' -e 's,\.py$,,')"
Vunder="$(basename "$V" | sed -e 's,^test-,,' -e 's,\.py$,,' -e 's,-,_,g')"
if ! grep -xF ' TEST/'"$Vunder"': '"$Vdash" "$SPREAD_PATH"/utils/test/task.yaml; then
echo "utils/test/task.yaml: missing test variant: TEST/$Vunder: $Vdash" >&2
fail=1
fi
done
if [ "$fail" -ne 0 ]; then
echo "exiting due to missing variants listed above" >&2
exit 1
fi
tests/unit/:
summary: Unit tests that do not exercise the kernel layer.
tests/regression/:
summary: Regression tests for parser-kernel interaction.
prepare: |
# Spread does not support programmatically generated test variants.
# Ensure that the list baked into tests/regression/apparmor/task.yaml
# contains all the tests defined in tests/regression/apparmor/Makefile.
echo '$(foreach t,$(TESTS),$(info TEST/$t))' | \
make -n -f "$SPREAD_PATH"/tests/regression/apparmor/Makefile -f /dev/stdin | \
grep -F TEST/ | \
cut -d / -f 2 | \
tee apparmor-regression-tests.txt
fail=0
while read -r V; do
if ! grep -xF ' TEST/'"$V"': 1' "$SPREAD_PATH"/tests/regression/apparmor/task.yaml; then
echo "tests/regression/task.yaml: missing test variant: TEST/$V" >&2
fail=1
fi
done <apparmor-regression-tests.txt
if [ "$fail" -ne 0 ]; then
echo "exiting due to missing variants listed above" >&2
exit 1
fi
# Build all the apparmor regression test programs.
make -C "$SPREAD_PATH"/tests/regression/apparmor -j"$(nproc)"
restore: |
rm -f apparmor-regression-tests.txt
tests/snapd/:
summary: Tests exercising a subset of behavior of snapd

View File

@@ -27,7 +27,7 @@ manually, or build against in-tree libapparmor.${nl}\
endif # LIBAPPARMOR not set
LDLIBS += $(LIBAPPARMOR)
AA_EXEC = $(shell which aa-exec)
AA_EXEC = $(shell command -v aa-exec)
ifeq ($(AA_EXEC),)
AA_EXEC_ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
@@ -67,6 +67,21 @@ system aa-exec by adding USE_SYSTEM=1 to your make command.${nl}\
LDLIBS += -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
endif # USE_SYSTEM
# the test suite is run as root but many of the tests restrict root
# capabilities like dac_override and dac_readsearch so the test
# suite needs recursive other rx perms from / on all dirs not owned by
# root
DIRCHECK_MESSAGE = $(shell ./check_dac_perms.sh)
ifneq ($(strip $(DIRCHECK_MESSAGE)),)
DIR_PERM_ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
The regression test suite at times is run as root but with restricted${nl}\
capabilities. In these situations it needs to be able to still access${nl}\
the test suite files.${nl}\
${DIRCHECK_MESSAGE}${nl}\
************************************************************************${nl})
endif
SYSCTL_INCLUDE="\#include <sys/sysctl.h>"
USE_SYSCTL:=$(shell echo $(SYSCTL_INCLUDE) | cpp -dM >/dev/null 2>/dev/null && echo true)
@@ -90,6 +105,7 @@ SRC=access.c \
chmod.c \
chown.c \
clone.c \
complain.c \
coredump.c \
deleted.c \
environ.c \
@@ -151,8 +167,7 @@ SRC=access.c \
unlink.c \
userns.c \
userns_setns.c \
xattrs.c \
xattrs_profile.c
xattrs.c
#only do the ioperm/iopl tests for x86 derived architectures
ifneq (,$(findstring $(shell uname -i),i386 i486 i586 i686 x86 x86_64))
@@ -165,6 +180,17 @@ ifeq ($(USE_SYSCTL),true)
SRC+=syscall_sysctl.c
endif
# Only do xattrs_profile test if we have the required setfattr binary
ifneq (,$(shell command -v setfattr))
SRC+=xattrs_profile.c
else
$(warning ${nl}\
************************************************************************${nl}\
No setfattr skipping xattrs_profile tests ...${nl}\
Install attr or equivalent package to build and run this test${nl}\
************************************************************************${nl})
endif
#only do dbus if proper libs are installl
ifneq (,$(shell pkg-config --exists dbus-1 && echo TRUE))
SRC+=dbus_eavesdrop.c dbus_message.c dbus_service.c dbus_unrequested_reply.c
@@ -232,6 +258,7 @@ TESTS=aa_exec \
changehat_misc \
chdir \
clone \
complain \
coredump \
deleted \
e2e \
@@ -240,6 +267,7 @@ TESTS=aa_exec \
exec_qual \
fchdir \
fd_inheritance \
file_unbindable_mount \
fork \
i18n \
link \
@@ -279,10 +307,14 @@ TESTS=aa_exec \
unlink\
userns\
xattrs\
xattrs_profile\
longpath \
nfs
# Only do xattrs_profile test if we have the required setfattr binary
ifneq (,$(shell command -v setfattr))
TESTS+=xattrs_profile
endif
#only do dbus if proper libs are installl
ifneq (,$(shell pkg-config --exists dbus-1 && echo TRUE))
TESTS+=dbus_eavesdrop dbus_message dbus_service dbus_unrequested_reply
@@ -304,6 +336,9 @@ libapparmor_check: ; $(LIBAPPARMOR_ERROR_MESSAGE)
aa_exec_check: ; $(AA_EXEC_ERROR_MESSAGE)
dirperm_check: ; $(DIR_PERM_ERROR_MESSAGE)
all: libapparmor_check aa_exec_check $(EXEC) changehat.h uservars.inc
uservars.inc: uservars.inc.source uservars.inc.system
@@ -401,7 +436,7 @@ build-dep:
tests: RISKY_TESTS=
tests: alltests
alltests: all
alltests: all dirperm_check check_dac_perms.sh
@if [ `whoami` = "root" ] ;\
then \
rc=0; \

View File

@@ -19,7 +19,7 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
ns=aa_exec_ns
@@ -31,18 +31,19 @@ genprofile_aa_exec()
mode="(complain) "
fi
fi
genprofile --stdin <<EOF
genprofile image=$1 --stdin <<EOF
$1 ${mode}{
file,
}
EOF
genprofile --append image=:${ns}:${1} --stdin <<EOF
:${ns}:${1} ${mode}{
file,
}
EOF
}
settest aa_exec_profile ${bin}/aa_exec_wrapper.sh
settest aa_exec_profile "${bin}/aa_exec_wrapper.sh"
genprofile_aa_exec "$test" 0
runchecktest "unconfined" pass "$aa_exec" "unconfined"
@@ -81,11 +82,12 @@ genprofile_aa_exec "$test" 0
runchecktest "negative test: bad ns (--namespace=${ns}XXX)" fail "$aa_exec -n ${ns}XXX -p $test" "$test (enforce)"
if [ "$(parser_supports 'all,')" = "true" ]; then
genprofile --stdin <<EOF
genprofile image=$test --stdin <<EOF
$test {
all,
}
EOF
genprofile --append image=:${ns}:${test} --stdin <<EOF
:${ns}:${test} {
all,
}

View File

@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
# cacheloc is the top level directory of cache directories
cacheloc="$tmpdir/cache"

View File

@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
file=$tmpdir/file

View File

@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
settest transition
at_secure=$pwd/at_secure

View File

@@ -17,7 +17,7 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
settest unix_fd_server
disk_img=$tmpdir/disk_img
@@ -28,7 +28,7 @@ file=$tmpdir/file
socket=$tmpdir/unix_fd_test
att_dis_client=$pwd/attach_disconnected
. $bin/mount.inc
. "$bin/mount.inc"
attach_disconnected_cleanup() {
if [ ! -z "$loop_device" ]; then

View File

@@ -27,7 +27,7 @@ pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
. "$bin/prologue.inc"
TESTS="syscall_ptrace syscall_sethostname \
syscall_setdomainname syscall_setpriority syscall_setscheduler \
@@ -139,18 +139,18 @@ for TEST in ${TESTS} ; do
# okay, now check to see if the capability functions from within
# a subprofile.
settest ${testwrapper}
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} ${my_entries}
genprofile "hat:$bin/${TEST}" "addimage:${bin}/${TEST}" ${my_entries}
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}
runchecktest "${TEST} changehat -- no caps" pass "$bin/${TEST}" ${my_arg}
else
runchecktest "${TEST} changehat -- no caps" fail $bin/${TEST} ${my_arg}
runchecktest "${TEST} changehat -- no caps" fail "$bin/${TEST}" ${my_arg}
fi
# all capabilities allowed
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} cap:ALL ${my_entries}
runchecktest "${TEST} changehat -- all caps" ${expected} $bin/${TEST} ${my_arg}
genprofile "hat:$bin/${TEST}" "addimage:${bin}/${TEST}" cap:ALL ${my_entries}
runchecktest "${TEST} changehat -- all caps" ${expected} "$bin/${TEST}" ${my_arg}
for cap in ${CAPABILITIES} ; do
if [ ${expected} = "fail" ]; then
@@ -162,8 +162,8 @@ for TEST in ${TESTS} ; do
else
expected_result=fail
fi
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} cap:${cap} ${my_entries}
runchecktest "${TEST} changehat -- capability ${cap}" ${expected_result} $bin/${TEST} ${my_arg}
genprofile "hat:$bin/${TEST}" "addimage:${bin}/${TEST}" cap:${cap} ${my_entries}
runchecktest "${TEST} changehat -- capability ${cap}" ${expected_result} "$bin/${TEST}" ${my_arg}
done
done

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