2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-05 00:35:13 +00:00

Compare commits

...

39 Commits

Author SHA1 Message Date
John Johansen
5b2be1da84 Merge libapparmor: fix feature matching for aa_feature_supports
The feature matching done in aa_feature_supports calls walk_one to
traverse the features string. This function is supposed to match on
the feature and return, but it matches the feature based on the length
of the feature to check. If the feature to check shorter, then it
would return as if the feature was not present - which was the case
for the following example:

feature_file contains (shortened for example purposes):

```
network_v9 {af_unix {yes
}
}
network_v8 {af_inet {yes
}
}
network {af_unix {yes
}
}
```

if the feature to be checked was simply "network", then walk_one would
return that the feature was not present.

Fix this by restarting the matching if there was not a full match at
the end of the feaure to check.

Fixes: https://bugs.launchpad.net/apparmor/+bug/2105986

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1608
Approved-by: Ryan Lee <rlee287@yahoo.com>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 69355d41f7)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2025-04-03 16:55:22 -03:00
Christian Boltz
9272bf77e0 Merge [2.13 cherry-pick] 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: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1391
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>
2024-10-21 19:29:46 +00:00
John Johansen
506c98e752 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: Georgia Garcia <georgia.garcia@canonical.com>
2024-10-21 15:54:12 -03:00
Georgia Garcia
d3a6965a5f 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>
(cherry picked from commit 95c419dc45)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-08-26 09:44:22 -03:00
John Johansen
811fe99e4a Merge abstractions/base: allow reading of fips_enabled
Commonly used by applications to determine if Linux is running in
FIPS mode. As we already allow access to FIPS specific library files
as part of base, allow this there as well.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1286
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit e787f4d69d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-08-07 00:40:46 -07:00
Ryan Lee
804c854544 Fix SWIG prototype declaration of aa_getpeercon_raw
Unsigned int vs int probably wouldn't have caused issues, but just in case

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 91bac34afd)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-08-06 17:30:12 -03:00
Ryan Lee
55d8c58bc1 Explicitly initialize component in test_walk_one
This removes the assumption that the stack is zeroed and silences the corresponding compiler warning

Signed-off-by: Ryan Lee <ryan.lee@canonical.com>
(cherry picked from commit 552d9d9f7a)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-08-06 17:30:08 -03:00
John Johansen
0824954b57 Merge parser: fix Normalizatin infinite loop
Expression simplification can get into an infinite loop due to eps
pairs hiding behind and alternation that can't be caught by
normalize_eps() (which exists in the first place to stop a similar
loop).

The loop in question happens in AltNode::normalize when a subtree has
the following structure.

1. elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                   alt
                   /\
                  /  \
                 /    \
               eps    alt
                      /\
                     /  \
                    /    \
                  alt    eps
                  /\
                 /  \
                /    \
               eps   eps

2. if (normalize_eps(dir)) results in

                   alt
                   /\
                  /  \
                 /    \
               alt    eps
               /\
              /  \
             /    \
           alt    eps
           /\
          /  \
         /    \
       eps   eps

3. elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                   alt
                   /\
                  /  \
                 /    \
               alt    alt
              /\        /\
             /  \      /  \
            /    \    /    \
          eps    eps eps   eps

4. elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                   alt
                   /\
                  /  \
                 /    \
               eps    alt
                      /\
                     /  \
                    /    \
                  eps    alt
                         /\
                        /  \
                       /    \
                     eps   eps

5. if (normalize_eps(dir)) results in

                  alt
                   /\
                  /  \
                 /    \
                alt   eps
                /\
               /  \
              /    \
            eps    alt
                    /\
                   /  \
                  /    \
                 eps   eps

6. elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                  alt
                   /\
                  /  \
                 /    \
                eps   alt
                       /\
                      /  \
                     /    \
                    alt  eps
                    /\
                   /  \
                  /    \
                eps   eps

back to beginning of cycle

Fix this by detecting the creation of an eps_pair in rotate_node(),
that pair can be immediately eliminated by simplifying the tree in that
step.

In the above cycle the pair creation is caught at step 3 resulting
in

3. elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                   alt
                   /\
                  /  \
                 /    \
               alt    eps
               /\
              /  \
             /    \
           eps    eps

4.  elseif (child[dir]->is_type(ALT_NODE)) rotate_node too

                   alt
                   /\
                  /  \
                 /    \
               eps   alt
                      /\
                     /  \
                    /    \
                  eps    eps

which gets reduced to

                   alt
                   /\
                  /  \
                 /    \
               eps   eps

breaking the normalization loop. The degenerate alt node will be caught
in turn when its parent is dealt with.

This needs to be backported to all releases

Closes: https://gitlab.com/apparmor/apparmor/-/issues/398
Fixes: 846cee506 ("Split out parsing and expression trees from regexp.y")
Reported-by: Christian Boltz <apparmor@cboltz.de>
Signed-off-by: John Johansen <john.johansen@canonical.com>

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

(cherry picked from commit a6691ca53e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-06-14 13:23:32 -07:00
John Johansen
023335d37c Merge gitlab-ci.yml: set fixed version on pipeline for 2.13
In order to maintain compatibility with Python 2 in AppArmor 2.13, set
the pipeline to use a version of ubuntu which supports Python 2.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1225
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2024-05-02 18:43:32 +00:00
Georgia Garcia
18effc5b96 gitlab-ci.yml: set fixed version on pipeline for 2.13
In order to maintain compatibility with Python 2 in AppArmor 2.13, set
the pipeline to use a version of ubuntu which supports Python 2.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/388
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-05-02 14:01:00 -03:00
Christian Boltz
48bc355b91 Merge abstractions/openssl: allow version specific engdef & engines paths
Some openssl distributions use version specific engdef and engines paths
to support multi-version installations.

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

Signed-off-by: David Disseldorp <ddiss@suse.de>

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


(cherry picked from commit 2577fbf077)

2b8cf1be abstractions/openssl: allow version specific engdef & engines paths
2024-02-07 08:50:44 +00:00
Georgia Garcia
ae409fce93 Prepare for AppArmor 2.13.11 release
- update version file

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2024-02-02 19:48:54 -03:00
John Johansen
d51b102c3a Merge Prevent ANSI terminal injection in aa-unconfined
/proc/$pid/cmdline can be changed by an application, therefore escape it
before printing.

The program name in /proc/$pid/exe can also contain any characters
(except \0 and shashes) and needs escaping.

Note: repr() wraps the string into single quotes, which we have to
remove to avoid changing the output format.

The test program from issue 364 now gets displayed as

    28443 /path/to/issue364 (/\x1b]0;X\x07) not confined

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

I propose this patch for 2.13..master

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

(cherry picked from commit e63c1e3a76)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-01-30 01:51:35 -08:00
John Johansen
75c7c5d16a Merge doc(fix): Fix wrong syntax for profile stacking
Add missing change_profile entry required for the example

Signed-off-by: Mostafa Emami <mustafaemami@gmail.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1141
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 3e28d0a254)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-01-30 01:49:18 -08:00
John Johansen
fcfb865cc7 Merge manpages: Add ENOPROTOOPT error in aa_getcon() manpage
The call aa_getpeercon() can return ENOPROTOOPT error in some cases, specifically when the kernel lacks 'fine grained unix mediation'. Currently, this capability isn't available in upstream kernels, but only in patched ones (for example, the regular Ubuntu kernels). Unfortunately, the manpage lacks this info. This patch fixes this.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/366
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1143
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit b03abbd75f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-01-30 01:49:08 -08:00
Georgia Garcia
1110197897 Merge parser: Deprecation warning should not have been backported
Outputing the deprecation warning is a change in behavior that is not
a bug fix.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ca7f79174e)
Signed-off-by: Rodrigo Figueiredo Zaiden <rodrigo.zaiden@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1129
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-12-05 16:46:00 +00:00
Rodrigo Figueiredo Zaiden
6b3eb5f255 parser: Deprecation warning should not have been backported
Outputing the deprecation warning is a change in behavior that is not
a bug fix.

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit ca7f79174e)
Signed-off-by: Rodrigo Figueiredo Zaiden <rodrigo.zaiden@canonical.com>
2023-12-05 10:55:50 -03:00
John Johansen
636739fec3 Merge fix subprofile name in profile serialization
Given the following profile:

profile foo {
  profile bar {
    profile baz {
    }
  }
}

The parser would correctly serialize the "foo" profile and the
"foo//bar" profile, but it would incorrectly name "bar//baz" when it
should be "foo//bar//baz". This would cause issues loading the profile
in certain kernels causing a "parent does not exist" error.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1127
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit eb6fa02251)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-12-04 01:11:55 -08:00
John Johansen
3c6d767e6e Merge profiles: remove @{etc_ro} variable which is not available on 2.13
The variable @{etc_ro} was cherry-picked from a commit from a later
apparmor version, but it is not available on 2.13. Therefore it should
be replaced by the actual string.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1122
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-11-09 14:18:57 +00:00
Georgia Garcia
c29b50587c profiles: remove @{etc_ro} variable which is not available on 2.13
The variable @{etc_ro} was cherry-picked from a commit from a later
apparmor version, but it is not available on 2.13. Therefore it should
be replaced by the actual string.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-11-09 12:27:30 +02:00
John Johansen
e1660df874 Merge tests: fix regression tests to run on kernels that only have network_v8
upstream kernels only have network_v8 unfortunately the tcp tests were
only being run against kernels that had network (which is v7). Kernels
that support both (Ubuntu) would be tested against v8, so v8 has been
tested but pure upstream kernels were failing to be tested correctly.

This patch will only make sure one of the supported verserions are
tested. This is determined by the parser which prefers v8. In the
future the tests need to be extended to run the tests against all
kernel supported versions.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1120
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit dcc719c69c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-11-08 06:26:56 -08:00
John Johansen
d90649ab4b Merge Allow reading /etc/authselect/nsswitch.conf
On systems with authselect installed, /etc/nsswitch.conf is a symlink to
/etc/authselect/nsswitch.conf.

Fixes: https://gitlab.com/apparmor/apparmor-profiles/-/issues/13

I propose this patch for 3.0..master.

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

(cherry picked from commit 54915dabc4)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-11-02 20:25:01 -07:00
John Johansen
3319313189 Merge ubuntu-browsers.d/kde: fix plasma-browser-integration
Out of the box the KDE plasma-browser-integration package does not work
after a user installed the corresponding Firefox extension: The browser
can't start the native host binary. The same is probably true for
Chromium.

This was originally reported to KDE at https://bugs.kde.org/show_bug.cgi?id=397399

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1115
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 1e7f63415a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-11-02 19:54:06 -07:00
John Johansen
1b300f5896 Merge [2.13..3.1] Ignore ´//null-` peers in signal and ptrace events
Ideally we'd update them to the chosen exec target - but until this is
implemented, it doesn't make sense to ask about adding a //null-* peer
to a profile.

This commit is a manual backport of 41df2ca366 /
https://gitlab.com/apparmor/apparmor/-/merge_requests/1090
(with indentation changed to match the 3.1 branch)

I propose this patch for 2.13..3.1

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


(cherry picked from commit 719251cac2)

7301aae2 Ignore ´//null-` peers in signal and ptrace events
2023-09-15 16:27:34 +00:00
Georgia Garcia
ed6bc062fc Merge tests/regression/apparmor/capabilities.sh: fail iopl/ioperm with lockdown
In MR #1063 the tests/regression/apparmor/syscall.sh script was updated to
account for kernel lockdown, but the capabilities.sh script also exercises these
system calls so this also needs to be updated as well.

Also required to fix issue #226.

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

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


(cherry picked from commit 3b832dd313)

eafae0dd tests/regression/apparmor/capabilities.sh: fail iopl/ioperm with lockdown
2023-07-10 13:10:03 +00:00
John Johansen
46e1b36318 Merge tests/regression/apparmor/syscall.sh: fail iopl/ioperm with lockdown
When kernel lockdown is enabled the ioperm and iopl tests will fail regardless
since lockdown prevents these syscalls before AppArmor has a chance to mediate
them. So workaround this by detecting when lockdown is enabled and expect the
tests to fail in that case.

Fixes issue #226.

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

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

(cherry picked from commit 7393aaac21)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-07-03 23:56:38 -07:00
John Johansen
97765f27d6 Merge abstractions/fonts: allow writing to fontconfig user cache files
Apologies for the second push; this change is made with the understanding that the abstraction is not intended to be solely read-only.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1059
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 5b7e637872)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-30 18:11:17 -07:00
John Johansen
22f3146627 Merge abstractions/fonts: allow locking fontconfig user cache files
Got this after allowing `rw` access to `~/.cache/fontconfig/**`:

`Jun 20 00:41:26 testvm kernel: [3280307.358614] audit: type=1400 audit(1687236086.210:127519): apparmor="DENIED" operation="file_lock" profile="firefox" name="/home/username/.cache/fontconfig/a41116dafaf8b233ac2c61cb73f2ea5f-le64.cache-7" pid=1758224 comm="firefox" requested_mask="k" denied_mask="k" fsuid=1002 ouid=1002`

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1057
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 162aa447d2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-30 10:53:22 -07:00
John Johansen
ac2dd196a6 Merge abstactions/kde: allow reading global Debian KDE settings
New denials detected on Debian Sid:

```
type=AVC msg=audit(1687372581.246:738): apparmor="DENIED" operation="open" class="file" profile="qtox" name="/usr/share/desktop-base/kf5-settings/kdeglobals" pid=17988 comm="qtox" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="vincas" OUID="root"
```

Debian package `desktop-base` contains some global KDE settings files:

```
$ dpkg -L desktop-base | fgrep kf5
/usr/share/desktop-base/kf5-settings
/usr/share/desktop-base/kf5-settings/baloofilerc
/usr/share/desktop-base/kf5-settings/kdeglobals
/usr/share/desktop-base/kf5-settings/kscreenlockerrc
```

Add file rules to allow reading global KDE settings.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1056
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 1ff74fed4b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-30 00:05:39 -07:00
John Johansen
b1d7dcab24 Prepare for AppArmor 2.13.10 release
- update version file

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

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-21 14:08:55 -07:00
John Johansen
9525238bb0 Merge fix mount regression in 2.13
Mount has regressed in two ways. That are affecting snapd confinement,
since landing the mount fixes for CVE-2016-1585 in 3.1.4 and the fix
for the mount change type regression in 3.1.5

    Bug Reports:

    https://bugs.launchpad.net/apparmor/+bug/2023814

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

Issue 1: Denial of Mount
    ```
    [ 808.531909] audit: type=1400 audit(1686759578.010:158): apparmor="DENIED" operation="mount" class="mount" info="failed mntpnt match" error=-13 profile="snap-update-ns.test-snapd-lp-1803535" name="/tmp/.snap/etc/" pid=14529 comm="5" srcname="/etc/" flags="rw, rbind"
    ```

when the profile contains a rule that should match
    ```
    mount options=(rw, rbind) "/etc/" -> "/tmp/.snap/etc/",
    ```

Issue 2: change_type failure.
Denial of Mount in log
    ```
    type=AVC msg=audit(1686977968.399:763): apparmor="DENIED" operation="mount" class="mount" info="failed flags match" error=-13 profile="snap-update-ns.authy" name="/var/cache/fontconfig/" pid=26702 comm="5" srcname="/var/lib/snapd/hostfs/var/cache/fontconfig/" flags="rw, bind"
    ...
    ```

    snapd error
    ```
    - Run configure hook of "chromium" snap if present (run hook "configure":
    -----
    update.go:85: cannot change mount namespace according to change mount (/var/lib/snapd/hostfs/usr/share/doc /usr/share/doc none bind,ro 0 0): permission denied
    update.go:85: cannot change mount namespace according to change mount (/var/lib/snapd/hostfs/usr/share/fonts /usr/share/fonts none bind,ro 0 0): permission denied
    update.go:85: cannot change mount namespace according to change mount (/var/snap/cups/common/run /var/cups none bind,rw 0 0): permission denied
    cannot update snap namespace: cannot create writable mimic over "/snap/chromium/2475": permission denied
    snap-update-ns failed with code 1
    ```

and NO mount rules in the profiles.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1054
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-06-21 01:31:55 -07:00
John Johansen
51d33c1a23 parser: fix rule flag generation change_mount type rules
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1048
made it so rules like

  mount slave /snap/bin/** -> /**,

  mount /snap/bin/** -> /**,

would get passed into change_mount_type rule generation when they
shouldn't have been. This would result in two different errors.

1. If kernel mount flags were present on the rule. The error would
   be caught causing an error to be returned, causing profile compilation
   to fail.

2. If the rule did not contain explicit flags then rule would generate
   change_mount_type permissions based on souly the mount point. And
   the implied set of flags. However this is incorrect as it should
   not generate change_mount permissions for this type of rule. Not
   only does it ignore the source/device type condition but it
   generates permissions that were never intended.

   When used in combination with a deny prefix this overly broad
   rule can result in almost all mount rules being denied, as the
   denial takes priority over the allow mount rules.

Fixes: https://bugs.launchpad.net/apparmor/+bug/2023814
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1211989
Fixes: 9d3f8c6cc ("parser: fix parsing of source as mount point for propagation type flags")
Fixes: MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1048

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 86d193e183)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-21 01:31:31 -07:00
John Johansen
b3881198ba Merge abstractions/base: Add transparent hugepage support
Found in testing a slimmed-down `usr.sbin.sshd` profile:
```
Jun  8 21:09:38 testvm kernel: [   54.847014] audit: type=1400 audit(1686272978.009:68): apparmor="DENIED" operation="open" profile="/usr/sbin/sshd" name="/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" pid=1035 comm="sshd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
```
Not sure what glibc/system call uses this, but it seems pretty broadly applicable, and read access is presumably harmless. [THP reference](https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1050
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit ad3750058d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-09 01:51:00 -07:00
John Johansen
629467b74e Merge abstractions/authentication: Add GSSAPI mechanism modules config
Found in testing a slimmed-down `usr.sbin.sshd` profile:
```
Jun  8 21:09:37 testvm kernel: [   54.770501] audit: type=1400 audit(1686272977.933:67): apparmor="DENIED" operation="open" profile="/usr/sbin/sshd" name="/etc/gss/mech.d/" pid=1036 comm="sshd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
```
([Reference](https://web.mit.edu/kerberos/krb5-1.21/doc/admin/host_config.html#gssapi-mechanism-modules) for  GSSAPI mechanism modules)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1049
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit b41fcdce16)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-09 01:50:31 -07:00
John Johansen
2292c7baeb Prepare for AppArmor 2.13.9 release
- update version file

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-08 23:09:32 -07:00
John Johansen
44a7f6eca9 Fix build failure in df4ed537e allow reading of /etc/ld-musl-*.path
2.13 does not support warn flags

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-08 22:50:43 -07:00
John Johansen
df4ed537eb Merge profiles: allow reading of /etc/ld-musl-*.path
/etc/ld-musl-*.path is required to perform dynamic linking on musl libc.
The wildcard is to match all CPU architectures, like x86_64.

type=AVC msg=audit(1686087677.497:67): apparmor="DENIED" operation="open" class="file" profile="syslog-ng" name="/etc/ld-musl-x86_64.path" pid=25866 comm="syslog-ng" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

Closes #333

Signed-off-by: Nikita Romaniuk <kelvium@yahoo.com>

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

(cherry picked from commit 6e0d776f65)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-08 19:05:23 -07:00
John Johansen
e839782f7e Merge parser: fix parsing of source as mount point for propagation type flags
Before 300889c3a, mount rules would compile policy when using source
as mount point for rules that contain propagation type flags, such as
unbindable, runbindable, private, rprivate, slave, rslave, shared, and
rshared. Even though it compiled, the rule generated would not work as
expected.

This commit fixes both issues. It allows the usage of source as mount
point for the specified flags, albeit with a deprecation warning, and
it correctly generates the mount rule.

The policy fails to load when both source and mount point are
specified, keeping the original behavior (reference
parser/tst/simple_tests/mount/bad_opt_10.sd for example).

Fixes: https://bugs.launchpad.net/bugs/1648245
Fixes: https://bugs.launchpad.net/bugs/2023025

It should be backported to versions 2.13, 3.0, 3.1.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1048
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 1e0d7bcbb7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-06-08 18:55:40 -07:00
Georgia Garcia
f016792d09 Merge profiles: add lock file permission to snap browsers
When opening snap browsers with evince using the snap_browsers
abstraction, we get the following AppArmor denials which prevent the
browsers from opening

audit: type=1400 audit(1685996894.479:225): apparmor="DENIED" operation="open" class="file" profile="/usr/bin/evince//snap_browsers" name="/var/lib/snapd/inhibit/firefox.lock" pid=13282 comm="snap" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

audit: type=1400 audit(1685997517.142:259): apparmor="DENIED" operation="file_lock" class="file" profile="/usr/bin/evince//snap_browsers" name="/var/lib/snapd/inhibit/firefox.lock" pid=14200 comm="snap" requested_mask="k" denied_mask="k" fsuid=1000 ouid=0

This MR should be cherry-picked into 2.13, 3.0, 3.1

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


(cherry picked from commit a00ece5b6e)

daec4bc8 profiles: add lock file permission to snap browsers
2023-06-06 11:15:06 +00:00
54 changed files with 422 additions and 41 deletions

View File

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

View File

@@ -1 +1 @@
2.13.8
2.13.11

View File

@@ -116,6 +116,14 @@ The specified I<file/task> does not exist or is not visible.
The confinement data is too large to fit in the supplied buffer.
=item B<ENOPROTOOPT>
The kernel doesn't support the SO_PEERLABEL option in sockets. This happens
mainly when the kernel lacks 'fine grained unix mediation' support. It also
can happen on LSM stacking kernels where another LSM has claimed this
interface and decides to return this error, although this is really a
corner case.
=back
=head1 NOTES

View File

@@ -109,12 +109,12 @@ To immediately stack a profile named "profile_a", as performed with
aa_stack_profile("profile_a"), the equivalent of this shell command can be
used:
$ echo -n "stackprofile profile_a" > /proc/self/attr/current
$ echo -n "stack profile_a" > /proc/self/attr/current
To stack a profile named "profile_a" at the next exec, as performed with
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
$ echo -n "stackexec profile_a" > /proc/self/attr/exec
$ echo -n "stack profile_a" > /proc/self/attr/exec
These raw AppArmor filesystem operations must only be used when using
libapparmor is not a viable option.
@@ -184,6 +184,7 @@ with apparmor_parser(8):
/etc/passwd r,
# Needed for aa_stack_profile()
change-profile -> &i_cant_be_trusted_anymore,
/usr/lib/libapparmor*.so* mr,
/proc/[0-9]*/attr/current w,
}

View File

@@ -43,7 +43,7 @@ scanner.h: scanner.l
scanner.c: scanner.l
af_protos.h:
echo '#include <netinet/in.h>' | $(CC) -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) -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

@@ -375,6 +375,10 @@ static bool walk_one(const char **str, const struct component *component,
i = 0;
cur++;
/* Partial match, continue to search */
if (i == component->len && !isbrace_space_or_nul(*cur))
i = 0;
}
/* Return false if a full match was not found */

View File

@@ -135,7 +135,7 @@ static int do_test_walk_one(const char **str, const struct component *component,
static int test_walk_one(void)
{
struct component c;
struct component c = (struct component) { NULL, 0 };
const char *str;
int rc = 0;

View File

@@ -55,7 +55,7 @@ extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
extern int aa_getcon(char **label, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, socklen_t *len, char **mode);
extern int aa_getpeercon(int fd, char **label, char **mode);
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
int *audit);

View File

@@ -170,6 +170,19 @@ void Node::dump_syntax_tree(ostream &os)
* a b c T
*
*/
static Node *simplify_eps_pair(Node *t)
{
if (dynamic_cast<TwoChildNode *>(t) &&
t->child[0] == &epsnode &&
t->child[1] == &epsnode) {
t->release();
return &epsnode;
}
return t;
}
static void rotate_node(Node *t, int dir)
{
// (a | b) | c -> a | (b | c)
@@ -178,7 +191,9 @@ static void rotate_node(Node *t, int dir)
t->child[dir] = left->child[dir];
left->child[dir] = left->child[!dir];
left->child[!dir] = t->child[!dir];
t->child[!dir] = left;
// check that rotation didn't create (E | E)
t->child[!dir] = simplify_eps_pair(left);
}
/* return False if no work done */
@@ -190,13 +205,7 @@ int TwoChildNode::normalize_eps(int dir)
// Ea -> aE
// Test for E | (E | E) and E . (E . E) which will
// result in an infinite loop
Node *c = child[!dir];
if (dynamic_cast<TwoChildNode *>(c) &&
&epsnode == c->child[dir] &&
&epsnode == c->child[!dir]) {
c->release();
c = &epsnode;
}
Node *c = simplify_eps_pair(child[!dir]);
child[!dir] = child[dir];
child[dir] = c;
return 1;

View File

@@ -831,15 +831,28 @@ int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
std::string optsbuf;
char class_mount_hdr[64];
const char *vec[5];
char *mountpoint = mnt_point;
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
/* change type base rules can not be conditional on device,
* device type or data
/* change type base rules can specify the mount point by using
* the parser token position reserved to device. that's why if
* the mount point is not specified, we use device in its
* place. this is a deprecated behavior.
*
* change type base rules can not be conditional on device
* (source), device type or data
*/
/* rule class single byte header */
mntbuf.assign(class_mount_hdr);
if (!convert_entry(mntbuf, mnt_point))
if (flags && flags != MS_ALL_FLAGS && device && mnt_point) {
PERROR("source and mount point cannot be used at the "
"same time for propagation type flags");
goto fail;
} else if (device && !mnt_point) {
mountpoint = device;
}
if (!convert_entry(mntbuf, mountpoint))
goto fail;
vec[0] = mntbuf.c_str();
/* skip device and type */
@@ -981,7 +994,7 @@ int mnt_rule::gen_flag_rules(Profile &prof, int &count, unsigned int flags,
if (!dev_type && !opts &&
gen_policy_bind_mount(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
if (!device && !dev_type && !opts &&
if ((!device || !mnt_point) && !dev_type && !opts &&
gen_policy_change_mount_type(prof, count, flags, opt_flags) == RULE_ERROR)
return RULE_ERROR;
if (!dev_type && !opts &&
@@ -997,7 +1010,7 @@ int mnt_rule::gen_flag_rules(Profile &prof, int &count, unsigned int flags,
return gen_policy_bind_mount(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) &&
(flags & (MS_MAKE_CMDS))
&& !device && !dev_type && !opts) {
&& (!device || !mnt_point) && !dev_type && !opts) {
return gen_policy_change_mount_type(prof, count, flags, opt_flags);
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
&& !dev_type && !opts) {

View File

@@ -273,7 +273,7 @@ static inline void sd_write_aligned_blob(std::ostringstream &buf, void *b, int b
buf.write((const char *) b, b_size);
}
static void sd_write_strn(std::ostringstream &buf, char *b, int size, const char *name)
static void sd_write_strn(std::ostringstream &buf, const char *b, int size, const char *name)
{
sd_write_name(buf, name);
sd_write8(buf, SD_STRING);
@@ -281,7 +281,7 @@ static void sd_write_strn(std::ostringstream &buf, char *b, int size, const char
buf.write(b, size);
}
static inline void sd_write_string(std::ostringstream &buf, char *b, const char *name)
static inline void sd_write_string(std::ostringstream &buf, const char *b, const char *name)
{
sd_write_strn(buf, b, strlen(b) + 1, name);
}
@@ -378,11 +378,7 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
sd_write_struct(buf, "profile");
if (flattened) {
assert(profile->parent);
autofree char *name = (char *) malloc(3 + strlen(profile->name) + strlen(profile->parent->name));
if (!name)
return;
sprintf(name, "%s//%s", profile->parent->name, profile->name);
sd_write_string(buf, name, NULL);
sd_write_string(buf, profile->get_name(false).c_str(), NULL);
} else {
sd_write_string(buf, profile->name, NULL);
}

View File

@@ -563,6 +563,17 @@ verify_binary_equality "link rules slash filtering" \
@{BAR}=/mnt/
/t { link @{FOO}/foo -> @{BAR}/bar, }" \
# This can potentially fail as ideally it requires a better dfa comparison
# routine as it can generates hormomorphic dfas. The enumeration of the
# dfas dumped will be different, even if the binary is the same
# Note: this test in the future will require -O filter-deny and
# -O minimize and -O remove-unreachable.
verify_binary_equality "mount specific deny doesn't affect non-overlapping" \
"/t { mount options=bind /e/ -> /**, }" \
"/t { audit deny mount /s/** -> /**,
mount options=bind /e/ -> /**, }"
if [ $fails -ne 0 -o $errors -ne 0 ]
then
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(slave) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(rslave) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(unbindable) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(runbindable) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(private) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(rprivate) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(shared) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,6 @@
#
#=Description test we fail make rules with source and mntpnt associated with MR 1054
#=EXRESULT FAIL
/usr/bin/foo {
mount options=(rshared) /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "unbindable" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=unbindable /1,
mount options=(unbindable) /2,
mount options=(rw,unbindable) /3,
mount options in (unbindable) /4,
mount options in (ro,unbindable) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "runbindable" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=runbindable /1,
mount options=(runbindable) /2,
mount options=(rw,runbindable) /3,
mount options in (runbindable) /4,
mount options in (ro,runbindable) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "rprivate" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=rprivate /1,
mount options=(rprivate) /2,
mount options=(rw,rprivate) /3,
mount options in (rprivate) /4,
mount options in (ro,rprivate) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "private" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=private /1,
mount options=(private) /2,
mount options=(rw,private) /3,
mount options in (private) /4,
mount options in (ro,private) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "slave" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=slave /1,
mount options=(slave) /2,
mount options=(rw,slave) /3,
mount options in (slave) /4,
mount options in (ro,slave) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "rslave" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=rslave /1,
mount options=(rslave) /2,
mount options=(rw,rslave) /3,
mount options in (rslave) /4,
mount options in (ro,rslave) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "shared" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=shared /1,
mount options=(shared) /2,
mount options=(rw,shared) /3,
mount options in (shared) /4,
mount options in (ro,shared) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "rshared" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=rshared /1,
mount options=(rshared) /2,
mount options=(rw,rshared) /3,
mount options in (rshared) /4,
mount options in (ro,rshared) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-unbindable" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-unbindable /1,
mount options=(make-unbindable) /2,
mount options=(rw,make-unbindable) /3,
mount options in (make-unbindable) /4,
mount options in (ro,make-unbindable) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-runbindable" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-runbindable /1,
mount options=(make-runbindable) /2,
mount options=(rw,make-runbindable) /3,
mount options in (make-runbindable) /4,
mount options in (ro,make-runbindable) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-private" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-private /1,
mount options=(make-private) /2,
mount options=(rw,make-private) /3,
mount options in (make-private) /4,
mount options in (ro,make-private) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-rprivate" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-rprivate /1,
mount options=(make-rprivate) /2,
mount options=(rw,make-rprivate) /3,
mount options in (make-rprivate) /4,
mount options in (ro,make-rprivate) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-slave" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-slave /1,
mount options=(make-slave) /2,
mount options=(rw,make-slave) /3,
mount options in (make-slave) /4,
mount options in (ro,make-slave) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-shared" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-shared /1,
mount options=(make-shared) /2,
mount options=(rw,make-shared) /3,
mount options in (make-shared) /4,
mount options in (ro,make-shared) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-rslave" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-rslave /1,
mount options=(make-rslave) /2,
mount options=(rw,make-rslave) /3,
mount options in (make-rslave) /4,
mount options in (ro,make-rslave) /5,
}

View File

@@ -0,0 +1,10 @@
#
#=Description basic rules to test the "make-rshared" mount option passing mount point as source (should emit a deprecation warning)
#=EXRESULT PASS
/usr/bin/foo {
mount options=make-rshared /1,
mount options=(make-rshared) /2,
mount options=(rw,make-rshared) /3,
mount options in (make-rshared) /4,
mount options in (ro,make-rshared) /5,
}

View File

@@ -0,0 +1,8 @@
#
#=Description test we can parse rules associated with MR 1054
#=EXRESULT PASS
/usr/bin/foo {
mount options=(slave) /**,
mount options=(slave) -> /**,
mount /snap/bin/** -> /**,
}

View File

@@ -0,0 +1,25 @@
#
#=Description caused an infinite loop in expr normalization
#=EXRESULT PASS
# This test triggers an infinite loop bug in expr normalization
# Note: this test might be able to be reduced more but, each element appears
# to be required to trigger the bug.
# that is the initial var assignment, += with the "comment" at the end
# (which is a separate bug), the expansion in the 2nd variable and then
# the use of the 2nd variable.
# This seems to be due to difference in consistency check between expansion
# at parse time and variable expansion.
# eg. expanding @{exec_path} manually will result in a failure to parse
# see: https://gitlab.com/apparmor/apparmor/-/issues/398
@{var}=*-linux-gnu*
@{var}+=*-suse-linux* #aa:only opensuse
@{exec_path} = /{,@{var}/}t
profile test {
@{exec_path} mr,
}

View File

@@ -30,6 +30,11 @@
/{usr/,}lib/@{multiarch}/security/pam_*.so mr,
/{usr/,}lib/@{multiarch}/security/ r,
# gssapi
/etc/gss/mech r,
/etc/gss/mech.d/ r,
/etc/gss/mech.d/*.conf r,
# kerberos
#include <abstractions/kerberosclient>
# SuSE's pwdutils are different:

View File

@@ -60,6 +60,7 @@
/etc/ld.so.conf r,
/etc/ld.so.conf.d/{,*.conf} r,
/etc/ld.so.preload r,
/etc/ld-musl-*.path r,
/{usr/,}lib{,32,64}/ld{,32,64}-*.so mr,
/{usr/,}lib/@{multiarch}/ld{,32,64}-*.so mr,
/{usr/,}lib/tls/i686/{cmov,nosegneg}/ld-*.so mr,
@@ -88,6 +89,9 @@
# best place -- but many profiles require it, and it is quite harmless.
@{PROC}/sys/kernel/ngroups_max r,
# Used to determine if Linux is running in FIPS mode
@{PROC}/sys/crypto/fips_enabled r,
# glibc's sysconf(3) routine to determine free memory, etc
@{PROC}/meminfo r,
@{PROC}/stat r,
@@ -96,6 +100,9 @@
@{sys}/devices/system/cpu/online r,
@{sys}/devices/system/cpu/possible r,
# transparent hugepage support
@{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size r,
# glibc's *printf protections read the maps file
@{PROC}/@{pid}/{maps,auxv,status} r,

View File

@@ -45,7 +45,7 @@
owner @{HOME}/.local/share/fonts/** r,
owner @{HOME}/.fonts.cache-2 mr,
owner @{HOME}/.{,cache/}fontconfig/ rw,
owner @{HOME}/.{,cache/}fontconfig/** mrl,
owner @{HOME}/.{,cache/}fontconfig/** mrwkl,
owner @{HOME}/.fonts.conf.d/ r,
owner @{HOME}/.fonts.conf.d/** r,
owner @{HOME}/.config/fontconfig/ r,

View File

@@ -25,6 +25,9 @@
/etc/kde4rc r,
/etc/xdg/kdeglobals r,
/etc/xdg/Trolltech.conf r,
/usr/share/desktop-base/kf5-settings/baloofilerc r,
/usr/share/desktop-base/kf5-settings/kdeglobals r,
/usr/share/desktop-base/kf5-settings/kscreenlockerrc r,
/usr/share/knotifications5/*.notifyrc r, # KNotification::sendEvent()
/usr/share/kubuntu-default-settings/kf5-settings/* r,

View File

@@ -21,6 +21,9 @@
/etc/passwd r,
/etc/protocols r,
# On systems with authselect installed, /etc/nsswitch.conf is a symlink to /etc/authselect/nsswitch.conf
/{usr/,}etc/authselect/nsswitch.conf r,
# libtirpc (used for NIS/YP login) needs this
/etc/netconfig r,

View File

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

View File

@@ -38,5 +38,6 @@ profile snap_browsers {
/snap/opera/[0-9]*/meta/{snap.yaml,hooks/} r,
/var/lib/snapd/sequence/{chromium,firefox,opera}.json r,
/var/lib/snapd/inhibit/{chromium,firefox,opera}.lock rk,
# add other browsers here
}

View File

@@ -5,3 +5,6 @@
#include <abstractions/kde>
/usr/bin/kde4-config Cx -> sanitized_helper,
# https://bugs.kde.org/show_bug.cgi?id=397399
/usr/bin/plasma-browser-integration-host Cx -> sanitized_helper,

30
tests/regression/apparmor/capabilities.sh Normal file → Executable file
View File

@@ -49,14 +49,20 @@ CAPABILITIES="chown dac_override dac_read_search fowner fsetid kill \
sys_admin sys_boot sys_nice sys_resource sys_time \
sys_tty_config mknod lease audit_write audit_control"
# lockdown thwarts both ioperm and iopl
notlockeddown=TRUE
if [ -f /sys/kernel/security/lockdown ] && ! grep -q "\[none\]" /sys/kernel/security/lockdown; then
notlockeddown=FALSE
fi
# defines which test+capability pairs should succeed.
syscall_reboot_sys_boot=TRUE
syscall_sethostname_sys_admin=TRUE
syscall_setdomainname_sys_admin=TRUE
syscall_setpriority_sys_nice=TRUE
syscall_setscheduler_sys_nice=TRUE
syscall_ioperm_sys_rawio=TRUE
syscall_iopl_sys_rawio=TRUE
syscall_ioperm_sys_rawio=$notlockeddown
syscall_iopl_sys_rawio=$notlockeddown
syscall_chroot_sys_chroot=TRUE
syscall_mlockall_ipc_lock=TRUE
syscall_sysctl_sys_admin=TRUE
@@ -93,7 +99,13 @@ for TEST in ${TESTS} ; do
settest ${TEST}
# base case, unconfined
runchecktest "${TEST} -- unconfined" pass ${my_arg}
if [ "${TEST}" = "syscall_ioperm" -a "$notlockeddown" = "FALSE" ] ||
[ "${TEST}" = "syscall_iopl" -a "$notlockeddown" = "FALSE" ]; then
expected=fail
else
expected=pass
fi
runchecktest "${TEST} -- unconfined" ${expected} ${my_arg}
# no capabilities allowed
genprofile ${my_entries}
@@ -107,11 +119,13 @@ for TEST in ${TESTS} ; do
# all capabilities allowed
genprofile cap:ALL ${my_entries}
runchecktest "${TEST} -- all caps" pass ${my_arg}
runchecktest "${TEST} -- all caps" ${expected} ${my_arg}
# iterate through each of the capabilities
for cap in ${CAPABILITIES} ; do
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
if [ ${expected} = "fail" ]; then
expected_result=fail
elif [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
expected_result=pass
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
expected_result=pass
@@ -136,10 +150,12 @@ for TEST in ${TESTS} ; do
# all capabilities allowed
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} cap:ALL ${my_entries}
runchecktest "${TEST} changehat -- all caps" pass $bin/${TEST} ${my_arg}
runchecktest "${TEST} changehat -- all caps" ${expected} $bin/${TEST} ${my_arg}
for cap in ${CAPABILITIES} ; do
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
if [ ${expected} = "fail" ]; then
expected_result=fail
elif [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
expected_result=pass
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
expected_result=pass

View File

@@ -218,6 +218,10 @@ test_propagation_options() {
runchecktest "MOUNT (confined cap mount propagation setup $1)" pass mount ${loop_device} ${mount_point}
genprofile cap:sys_admin "mount:options=($1)"
runchecktest "MOUNT (confined cap mount propagation $1)" pass mount none ${mount_point} -o $1
genprofile cap:sys_admin "mount:options=($1):-> ${mount_point}/"
runchecktest "MOUNT (confined cap mount propagation $1 mountpoint)" pass mount none ${mount_point} -o $1
genprofile cap:sys_admin "mount:options=($1):${mount_point}/"
runchecktest "MOUNT (confined cap mount propagation $1 source as mountpoint - deprecated)" pass mount none ${mount_point} -o $1
remove_mnt
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
@@ -394,6 +398,16 @@ else
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
remove_mnt
# MR:https://gitlab.com/apparmor/apparmor/-/merge_requests/1054
# https://bugs.launchpad.net/apparmor/+bug/2023814
# https://bugzilla.opensuse.org/show_bug.cgi?id=1211989
# based on rules from profile in bug that triggered issue
genprofile cap:sys_admin "qual=deny:mount:/snap/bin/:-> /**" \
"mount:options=(rw,bind):-> ${mount_point}/"
runchecktest "MOUNT (confined cap bind mount with deny mount that doesn't overlap)" pass mount ${mount_point2} ${mount_point} -o bind
remove_mnt
test_options
fi

View File

@@ -150,13 +150,19 @@ i386 | i486 | i586 | i686 | x86 | x86_64)
# But don't run them on xen kernels
if [ ! -d /proc/xen ] ; then
# lockdown thwarts both ioperm and iopl
expected=pass
if [ -f /sys/kernel/security/lockdown ] && ! grep -q "\[none\]" /sys/kernel/security/lockdown; then
expected=fail
fi
##
## F. IOPERM
##
settest syscall_ioperm
# TEST F1
runchecktest "IOPERM (no confinement)" pass 0 0x3ff
runchecktest "IOPERM (no confinement)" $expected 0 0x3ff
# TEST F2. ioperm will fail
genprofile
@@ -169,7 +175,7 @@ runchecktest "IOPERM (confinement)" fail 0 0x3ff
settest syscall_iopl
# TEST G1
runchecktest "IOPL (no confinement)" pass 3
runchecktest "IOPL (no confinement)" $expected 3
# TEST G2. iopl will fail
genprofile

View File

@@ -14,8 +14,14 @@ pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
# TODO:
# need to update so we can run the test for ech supported
# need to be able to modify the compile features to choose the
# kernel feature supported
# need to be able to query the parser if it supports the
# kernel feature
. $bin/prologue.inc
requires_kernel_features network
requires_any_of_kernel_features network network_v8
port=34567
ip="127.0.0.1"

View File

@@ -99,6 +99,15 @@ def get_pids_netstat(netstat='netstat'):
return pids
def escape_special_chars(data):
"""escape special characters in program names so that they can't mess up the terminal"""
data = repr(data)
if len(data) > 1 and data.startswith("'") and data.endswith("'"):
return data[1:-1]
else:
return data
pids = set()
if paranoid:
pids = get_all_pids()
@@ -110,6 +119,7 @@ else:
for pid in sorted(map(int, pids)):
try:
prog = os.readlink("/proc/%s/exe" % pid)
prog = escape_special_chars(prog)
except OSError:
continue
attr = None
@@ -127,6 +137,7 @@ for pid in sorted(map(int, pids)):
pname = cmdline.split("\0")[0]
if '/' in pname and pname != prog:
pname = "(%s)" % pname
pname = escape_special_chars(pname)
else:
pname = ""
regex_interpreter = re.compile(r"^(/usr)?/bin/(python|perl|bash|dash|sh)$")
@@ -134,6 +145,7 @@ for pid in sorted(map(int, pids)):
if regex_interpreter.search(prog):
cmdline = re.sub(r"\x00", " ", cmdline)
cmdline = re.sub(r"\s+$", "", cmdline).strip()
cmdline = escape_special_chars(cmdline)
ui.UI_Info(_("%(pid)s %(program)s (%(commandline)s) not confined") % {'pid': pid, 'program': prog, 'commandline': cmdline})
else:
@@ -144,6 +156,7 @@ for pid in sorted(map(int, pids)):
if regex_interpreter.search(prog):
cmdline = re.sub(r"\0", " ", cmdline)
cmdline = re.sub(r"\s+$", "", cmdline).strip()
cmdline = escape_special_chars(cmdline)
ui.UI_Info(_("%(pid)s %(program)s (%(commandline)s) confined by '%(attribute)s'") % {'pid': pid, 'program': prog, 'commandline': cmdline, 'attribute': attr})
else:
if pname and pname[-1] == ')':

View File

@@ -2025,6 +2025,9 @@ def collapse_log():
ptrace = prelog[aamode][profile][hat]['ptrace']
for peer in ptrace.keys():
if '//null-' in peer:
continue # ignore null-* peers
for access in ptrace[peer].keys():
ptrace_event = PtraceRule(access, peer, log_event=True)
if not hat_exists or not is_known_rule(aa[profile][hat], 'ptrace', ptrace_event):
@@ -2032,6 +2035,9 @@ def collapse_log():
sig = prelog[aamode][profile][hat]['signal']
for peer in sig.keys():
if '//null-' in peer:
continue # ignore null-* peers
for access in sig[peer].keys():
for signal in sig[peer][access].keys():
signal_event = SignalRule(access, signal, peer, log_event=True)

View File

@@ -17,6 +17,7 @@ import re
import sys
import time
import LibAppArmor
import apparmor.ui as aaui
from apparmor.common import AppArmorException, AppArmorBug, open_file_read, DebugLogger
from apparmor.aamode import validate_log_mode, log_str_to_mode, hide_log_mode, AA_MAY_EXEC
@@ -95,7 +96,13 @@ class ReadLog:
if sys.version_info < (3, 0):
# parse_record fails with u'foo' style strings hence typecasting to string
msg = str(msg)
event = LibAppArmor.parse_record(msg)
try:
event = LibAppArmor.parse_record(msg)
except TypeError:
aaui.UI_Important(_("WARNING: Cannot process log message, skipping entry. Make sure log is plaintext."))
return None
ev = dict()
ev['resource'] = event.info
ev['active_hat'] = event.active_hat

View File

@@ -107,6 +107,14 @@ exception_not_raised = [
'mount/bad_opt_29.sd',
'mount/bad_opt_30.sd',
'mount/bad_opt_31.sd',
'mount/bad_opt_32.sd',
'mount/bad_opt_35.sd',
'mount/bad_opt_36.sd',
'mount/bad_opt_37.sd',
'mount/bad_opt_38.sd',
'mount/bad_opt_39.sd',
'mount/bad_opt_40.sd',
'mount/bad_opt_41.sd',
'profile/flags/flags_bad10.sd',
'profile/flags/flags_bad11.sd',
'profile/flags/flags_bad12.sd',