2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-02 15:25:27 +00:00

Compare commits

..

35 Commits

Author SHA1 Message Date
John Johansen
5f6e213d23 Prepare for AppArmor 4.0 alpha 2 release
- update version file

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-08-14 14:36:03 -07:00
John Johansen
d717adfc2f Merge parser: make attach_disconnected.path enable attach_disconnected
Currently you need to use attach_disconnected with
attach_disconnected.path=XXX to be able to attach to a different
location than / whic is ugly and redundant.

Make it so attach_disconnected.path implies attach_disconnected.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1084
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: John Johansen <john@jjmx.net>
2023-08-14 21:28:40 +00:00
John Johansen
4a21bd104c parser: make attach_disconnected.path enable attach_disconnected
Currently you need to use attach_disconnected with
attach_disconnected.path=XXX to be able to attach to a different
location than / whic is ugly and redundant.

Make it so attach_disconnected.path implies attach_disconnected.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-08-14 13:28:31 -07:00
John Johansen
f9036d57de Merge document that attach_disconnected.path expexts =PATH
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1083
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-08-14 20:28:26 +00:00
Christian Boltz
c87dd7985f document that attach_disconnected.path expexts =PATH 2023-08-14 22:22:02 +02:00
John Johansen
8eee4de83e Merge parser: add support for attach_disconnected.path
Add support for specifying the path prefix used when attach disconnected
is specified.

TODO: add regression tests

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/661
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-08-14 14:15:25 +00:00
John Johansen
dbb2a1d0bb tests: regression, add basic regression tests
Add a couple basic attach disconnected regression tests

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-08-14 01:42:34 -07:00
John Johansen
b46b2662ff parser: add support for attach_disconnected.path
Add support for specifying the path prefix used when attach disconnected
is specified. The kernel supports prepending a different value than
/ when a path is disconnected. Expose through a profile flag.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-08-14 01:42:28 -07:00
John Johansen
03669ae3df Merge Add aa-logprof test framework
... and a simple test for a single (fake) event for ping.

Notes:
- to let aa-logprof work in the CI environment, we need to skip checking
  for the AppArmor mountpoint. Introduce --no-check-mountpoint for this.
- PYTHONPATH and LD_LIBRARY_PATH need to be explicitely forwarded when
  starting aa-logprof via subprocess.Popen()
- if the test runs with coverage enabled, it will also start aa-logprof
  with coverage (parameters copied from Makefile).

Speaking about coverage - this test adds 4% overall coverage, and 10%
more coverage for apparmor/aa.py.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1082
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-08-14 07:55:31 +00:00
John Johansen
941118c699 Merge profiles: allow for the default dovecot libexecdir
Though many Linux distros choose to pass _/usr/lib_ as the libexecdir while configuring dovecot, such as [Debian](https://sources.debian.org/src/dovecot/1%3A2.3.20%2Bdfsg1-1/debian/rules/#L132) and [Arch](https://gitlab.archlinux.org/archlinux/packaging/packages/dovecot/-/blob/main/PKGBUILD#L76), others like Alpine Linux and Gentoo don't pass anything as libexecdir, allowing it to default to _/usr/libexec_.

Both appear to be valid. From [FHS 3.0, Chapter 4.7](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s07.html):
> Some previous versions of this document did not support _/usr/libexec_, despite it being standard practice in a number of environments. To accomodate this restriction, it became common practice to use _/usr/lib_ instead. Either practice is now acceptable, but each application must choose one way or the other to organize itself.

Allow for the default libexec subdir _/usr/libexec/dovecot_ as well as the more common
_/usr/lib/dovecot_.

Signed-off-by: Peter Levine <plevine457@gmail.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1080
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-08-14 07:54:19 +00:00
Christian Boltz
46debcc493 Add aa-logprof test framework
... and a simple test for a single (fake) event for ping.

Notes:
- to let aa-logprof work in the CI environment, we need to skip checking
  for the AppArmor mountpoint. Introduce --no-check-mountpoint for this.
- PYTHONPATH and LD_LIBRARY_PATH need to be explicitely forwarded when
  starting aa-logprof via subprocess.Popen()
- if the test runs with coverage enabled, it will also start aa-logprof
  with coverage (parameters copied from Makefile).

Speaking about coverage - this test adds 4% overall coverage, and 10%
more coverage for apparmor/aa.py.
2023-08-13 21:02:50 +02:00
Christian Boltz
65de34f462 Merge Add include if exists <tunables/$FILE.d> to all tunables
(except the deprecated tunables/sys)

This allows users to extend variables without editing the main tunables
files.

It also allows to cleanly introduce new tunable files (via
tunables/global.d) and new aliases (via tunables/alias.d).

Note: some files already had `include <tunables/$FILE.d>`. These get
changed to `include if exists`, and the comments for these includes get
unified.

Also extend make check to ensure that all tunables include tunables/$FILE.d

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

I propose this patch for 3.0..master.

Closes #347
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1077
Approved-by: timeout
Merged-by: Christian Boltz <apparmor@cboltz.de>
2023-08-13 15:02:45 +00:00
Peter Levine
37ffc6eac8 profiles: allow for the default dovecot libexecdir
Allow for the default libexec subdir, /usr/libexec/dovecot, as well
as the more common /usr/lib/dovecot.

Signed-off-by: Peter Levine <plevine457@gmail.com>
2023-08-03 01:30:42 -04:00
John Johansen
313366fbbc Merge parser: fix encoding of unix permissions for setopt and getopt
The permissions for AA_NET_OPT need to be bounded by mask so we can
make sure it matches when a policy specified only setopt or only
getopt. This was causing failures on the regression tests
unix_socket_pathname, unix_socket_abstract, unix_socket_unnamed and
unix_socket_autobind

Fixes: 44f3be091 ("parser: convert the stored audit from a bit mask to a bool")
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1079
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-08-02 11:13:40 +00:00
Georgia Garcia
64c1eb9cda tests: fix feature test
Fixes: 81f0b84d ("tests: fix feature checking if it's a directory")
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-08-01 16:20:20 -03:00
Georgia Garcia
210ad63cbf parser: fix encoding of unix permissions for setopt and getopt
The permissions for AA_NET_OPT need to be bounded by mask so we can
make sure it matches when a policy specified only setopt or only
getopt. This was causing failures on the regression tests
unix_socket_pathname, unix_socket_abstract, unix_socket_unnamed and
unix_socket_autobind

Fixes: 44f3be091 ("parser: convert the stored audit from a bit mask to a bool")
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-08-01 14:25:41 -03:00
John Johansen
93dff6a806 Merge parser: add support for prompt profile mode
Add support for the prompt profile flag. That allows policy to do an upcall to userspace if supported by the kernel and if a userspace daemon is available.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1062
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-31 04:10:33 +00:00
John Johansen
e5dace9ffd parser: add support for prompt profile mode
Add support for the prompt profile mode.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-07-30 20:50:03 -07:00
John Johansen
80f7add3b7 Merge Add option to log aa-logprof json input and output
Add a json_log option (default: disabled) to logprof.conf that enables
logging of all aa-logprof and aa-genprof input and output to a
/tmp/aa-jsonlog-* file.

This can be useful for debugging, and maybe also to create tests that do
a full aa-logprof run.

This patch introduces a minor behaviour change if aa-logprof errors out
on startup (for example if the config file is broken or the parser can't
be found):

Before:

```
$ aa-logprof --json
{"dialog": "apparmor-json-version","data": "2.12"}

ERROR: Can't find apparmor_parser at /sbin/apparmor_parser
```

After:

```
$ aa-logprof --json

ERROR: Can't find apparmor_parser at /sbin/apparmor_parser
```

Note that the json version line will not be printed if aa-logprof or
aa-genprof error out that early.

If there are no startup errors, the behaviour will not change.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1078
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-31 02:40:23 +00:00
John Johansen
c2b8ca1b28 Merge firefox: fix app name and DBus access
Minor fixes for the firefox profile:

1. The attachment spec was failing to match `/usr/lib/firefox-esr/firefox-esr` on Debian;
2. The `Mounted` method of `org.gtk.vfs.MountTracker` is received, not sent.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1076
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-31 02:39:44 +00:00
Christian Boltz
7dc0254b90 Add option to log aa-logprof json input and output
Add a json_log option (default: disabled) to logprof.conf that enables
logging of all aa-logprof and aa-genprof input and output to a
/tmp/aa-jsonlog-* file.

This can be useful for debugging, and maybe also to create tests that do
a full aa-logprof run.

This patch introduces a minor behaviour change if aa-logprof errors out
on startup (for example if the config file is broken or the parser can't
be found):

Before:

```
$ aa-logprof --json
{"dialog": "apparmor-json-version","data": "2.12"}

ERROR: Can't find apparmor_parser at /sbin/apparmor_parser
```

After:

```
$ aa-logprof --json

ERROR: Can't find apparmor_parser at /sbin/apparmor_parser
```

Note that the json version line will not be printed if aa-logprof or
aa-genprof error out that early.

If there are no startup errors, the behaviour will not change.
2023-07-30 21:28:35 +02:00
Christian Boltz
d6bc107940 make check: ensure that all tunables include tunables/$FILE.d
(except the deprecated tunables/sys)
2023-07-30 00:58:21 +02:00
Christian Boltz
5657799dc7 Add include if exists <tunables/$FILE.d> to all tunables
(except the deprecated tunables/sys)

This allows users to extend variables without editing the main tunables
files.

It also allows to cleanly introduce new tunable files (via
tunables/global.d) and new aliases (via tunables/alias.d).

Note: some files already had `include <tunables/$FILE.d>`. These get
changed to `include if exists`, and the comments for these includes get
unified.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/347
2023-07-30 00:47:34 +02:00
Daniel Richard G
018efdeb9d firefox: fix app name and DBus access 2023-07-25 20:04:26 -04:00
John Johansen
17a521ff50 Merge ask_exec: Stop checking for CMD_nx (named exec)
... because it gets translated to CMD_px or CMD_cx earlier in the
function.

Also add a safety check for unknown answers.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1072
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-19 21:17:35 +00:00
John Johansen
853b138537 Merge libapparmor: fix dynamic linkage
It appears that lto1 does not support -dynamic, and that ld no longer
documents -dynamic. Which results in the following build failure
when usine lto1 for link time optimizations

```
[   45s] libtool: link: gcc -shared  -fPIC -DPIC  .libs/grammar.o .libs/libaalogparse.o .libs/kernel.o .libs/scanner.o .libs/private.o .libs/features.o .libs/kernel_interface.o .libs/policy_cache.o .libs/PMurHash.o    -flto-partition=none -O2 -fstack-protector-strong -flto=auto -dynamic -Wl,--version-script=../src/libapparmor.map -flto=auto   -pthread -Wl,-soname -Wl,libapparmor.so.1 -o .libs/libapparmor.so.1.17.0
[   45s] lto1: warning: unrecognized gcc debugging option: y
[   45s] lto1: warning: unrecognized gcc debugging option: n
[   45s] lto1: warning: unrecognized gcc debugging option: m
[   45s] lto1: warning: unrecognized gcc debugging option: i
[   45s] lto1: warning: unrecognized gcc debugging option: c
```

Switch to -Bdynamic which is documented.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1071
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: John Johansen <john@jjmx.net>
2023-07-19 21:16:36 +00:00
John Johansen
d6673f95d2 Merge tests: fix feature checking if it's a directory
The test to check if the kernel supports a feature covers two cases:
1. The file/directory indicates a feature is supported.
2. The feature is supported if it's in the contents of the file.

When the intended check is for case 1, and the file does not exist,
then the code checks if it's case 2, but since it was not supposed to
be, we end up grepping a directory, causing an error message. Fix this
by checking if we're grepping a file.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1074
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-19 21:16:23 +00:00
John Johansen
b2274a7f5d Merge Revert "policy: pin policy to 4.0 abi for dev"
This reverts commit 460c3d5b59.

The 4.0 ABI was pinned for the development cycle but it can cause
in-tree uses of parser/parser.conf to fail if it cannot find the 4.0
file in /etc/apparmor.d/abi/.

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

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1073
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
2023-07-19 21:14:45 +00:00
Georgia Garcia
81f0b84da5 tests: fix feature checking if it's a directory
The test to check if the kernel supports a feature covers two cases:
1. The file/directory indicates a feature is supported.
2. The feature is supported if it's in the contents of the file.

When the intended check is for case 1, and the file does not exist,
then the code checks if it's case 2, but since it was not supposed to
be, we end up grepping a directory, causing an error message. Fix this
by checking if we're grepping a file.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-07-19 17:46:13 -03:00
Georgia Garcia
10529a6db7 Revert "policy: pin policy to 4.0 abi for dev"
This reverts commit 460c3d5b59.

The 4.0 ABI was pinned for the development cycle but it can cause
in-tree uses of parser/parser.conf to fail if it cannot find the 4.0
file in /etc/apparmor.d/abi/.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
2023-07-19 17:37:24 -03:00
Christian Boltz
f1ab009a09 ask_exec: Stop checking for CMD_nx (named exec)
... because it gets translated to CMD_px or CMD_cx earlier in the
function.

Also add a safety check for unknown answers.
2023-07-19 21:41:43 +02:00
John Johansen
94082cc5e4 libapparmor: fix dynamic linkage
It appears that lto1 does not support -dynamic, and that ld no longer
documents -dynamic. Which results in the following build failure
when usine lto1 for link time optimizations

[   45s] libtool: link: gcc -shared  -fPIC -DPIC  .libs/grammar.o .libs/libaalogparse.o .libs/kernel.o .libs/scanner.o .libs/private.o .libs/features.o .libs/kernel_interface.o .libs/policy_cache.o .libs/PMurHash.o    -flto-partition=none -O2 -fstack-protector-strong -flto=auto -dynamic -Wl,--version-script=../src/libapparmor.map -flto=auto   -pthread -Wl,-soname -Wl,libapparmor.so.1 -o .libs/libapparmor.so.1.17.0
[   45s] lto1: warning: unrecognized gcc debugging option: y
[   45s] lto1: warning: unrecognized gcc debugging option: n
[   45s] lto1: warning: unrecognized gcc debugging option: m
[   45s] lto1: warning: unrecognized gcc debugging option: i
[   45s] lto1: warning: unrecognized gcc debugging option: c

Switch to -Bdynamic which is documented.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2023-07-17 21:04:11 -07:00
Steve Beattie
b6bd4f5421 parser: improve errors.py test coverage, convert to unittest.main
Merge the following commits:

- [12cf66ff0] parser/errors.py: check error message + error code for non-existent profiles
- [87896b949] parser/errors.py: convert to unittest.main()

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1070
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Approved-by: John Johansen <john@jjmx.net>
2023-07-13 13:43:40 -05:00
Steve Beattie
87896b9496 parser/errors.py: convert to unittest.main()
Do this to simplify test identification, and also support the different
invocation mechanisms of unittest, like running individual tests.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1070
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Approved-by: John Johansen <john@jjmx.net>
2023-07-13 13:40:42 -05:00
Steve Beattie
12cf66ff0b parser/errors.py: check error message + error code for non-existent profiles
Add tests for passing the parser a file that doesn't exist, a symlink
to a file that doesn't exist, and a directory that contains that
latter.  Also include tests for different levels of -j passed as an
argument. These tests are based on the fixing commit 1259319508
("parser: Fix parser failing to handle errors when setting up work")

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1070
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Approved-by: John Johansen <john@jjmx.net>
2023-07-13 13:38:52 -05:00
89 changed files with 784 additions and 123 deletions

View File

@@ -1 +1 @@
4.0.0~alpha1
4.0.0~alpha2

View File

@@ -59,7 +59,7 @@ lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -Bdynamic -pthread \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
pkgconfigdir = $(libdir)/pkgconfig

View File

@@ -413,7 +413,7 @@ int unix_rule::gen_policy_re(Profile &prof)
tmp << "..";
buf = tmp.str();
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
map_perms(AA_NET_OPT),
map_perms(mask & AA_NET_OPT),
map_perms(audit == AUDIT_FORCE ? AA_NET_OPT : 0),
parseopts))
goto fail;

View File

@@ -113,9 +113,11 @@ B<XATTR VALUE FILEGLOB> = I<FILEGLOB>
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted' | 'attach_disconnected' | 'chroot_relative' | 'debug'
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
| 'attach_disconnected' | 'attach_disconneced.path='I<ABS PATH> | 'chroot_relative'
| 'debug'
B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'unconfined'
B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'unconfined' | 'prompt'
B<AUDIT MODE> = 'audit'
@@ -459,6 +461,11 @@ profile replacement. This mode is should not be used under regular
deployment but can be useful during debugging and some system
initialization scenarios.
=item B<prompt> This mode allows task mediation to send an up call to
userspace to ask for a decision when there isn't a rule covering the
permission request. If userspace does not respond then the access
will be denied.
=back
=head4 Audit Mode
@@ -486,6 +493,10 @@ though they are part of the namespace. WARNING this mode is unsafe and
can result in aliasing and access to objects that should not be
allowed. Its intent is a debug and policy development tool.
=item B<attach_disconnected.path>=I<ABS PATH> Like attach_disconnected, but
attach disconnected objects to the supplied path instead of the root of
the namespace.
=item B<chroot_relative> This forces file names to be relative to a
chroot and behave as if the chroot is a mount namespace.

View File

@@ -77,7 +77,3 @@
## Pin older policy to the 5.4 kernel abi + out of tree network and af_unix
#policy-features=/etc/apparmor.d/abi/kernel-5.4-outoftree-network
## TO BE reverted - this is only for 4.0 dev cycle
## pin policy that doesn't have an abi to 4.0
policy-features=/etc/apparmor.d/abi/4.0

View File

@@ -420,6 +420,12 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
}
}
/* added in 4.13, unfortunately there is no features flag */
if (profile->flags.disconnected_path) {
sd_write_string(buf, profile->flags.disconnected_path,
"disconnected");
}
sd_write_struct(buf, "flags");
/* used to be flags.debug, but that's no longer supported */
sd_write_uint32(buf, profile->flags.flags);

View File

@@ -285,7 +285,20 @@ static int process_variables_in_name(Profile &prof)
int error = expand_entry_variables(&prof.name);
if (!error && prof.attachment)
error = expand_entry_variables(&prof.attachment);
if (!error && prof.flags.disconnected_path) {
error = expand_entry_variables(&prof.flags.disconnected_path);
if (error)
return error;
filter_slashes(prof.flags.disconnected_path);
// TODO: semantic check should go somewhere else
if (prof.flags.disconnected_path[0] != '/')
yyerror(_("attach_disconnected_path value must begin with a /"));
int n = strlen(prof.flags.disconnected_path);
// removing trailing / */
while (n && prof.flags.disconnected_path[n-1] == '/')
prof.flags.disconnected_path[--n] = 0;
}
return error;
}

View File

@@ -575,7 +575,7 @@ valuelist: valuelist TOK_VALUE
}
flags: { /* nothing */
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0 };
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
$$ = fv;
};
@@ -627,7 +627,7 @@ flagvals: flagval
flagval: TOK_VALUE
{
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0 };
flagvals fv = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
enum profile_mode mode;
if (strcmp($1, "debug") == 0) {
@@ -653,6 +653,10 @@ flagval: TOK_VALUE
fv.path |= PATH_CHROOT_NSATTACH;
} else if (strcmp($1, "chroot_no_attach") == 0) {
fv.path |= PATH_CHROOT_NO_ATTACH;
} else if (strncmp($1, "attach_disconnected.path=", 25) == 0) {
/* TODO: make this a proper parse */
fv.path |= PATH_ATTACH;
fv.disconnected_path = strdup($1 + 25);
} else {
yyerror(_("Invalid profile flag: %s."), $1);
}

View File

@@ -27,6 +27,7 @@ const char *profile_mode_table[] = {
"complain",
"kill",
"unconfined",
"prompt"
};
bool deref_profileptr_lt::operator()(Profile * const &lhs, Profile * const &rhs) const
@@ -106,6 +107,8 @@ Profile::~Profile()
free(name);
if (attachment)
free(attachment);
if (flags.disconnected_path)
free(flags.disconnected_path);
if (ns)
free(ns);
for (int i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++)

View File

@@ -62,9 +62,10 @@ enum profile_mode {
MODE_COMPLAIN = 2,
MODE_KILL = 3,
MODE_UNCONFINED = 4,
MODE_CONFLICT = 5 /* greater than MODE_LAST */
MODE_PROMPT = 5,
MODE_CONFLICT = 6 /* greater than MODE_LAST */
};
#define MODE_LAST MODE_UNCONFINED
#define MODE_LAST MODE_PROMPT
static inline enum profile_mode operator++(enum profile_mode &mode)
{
@@ -120,6 +121,7 @@ public:
enum profile_mode mode;
int audit;
int path;
char *disconnected_path;
ostream &dump(ostream &os)
{
@@ -131,6 +133,8 @@ public:
if (flags & FLAG_HAT)
os << ", Hat";
if (disconnected_path)
os << ", attach_disconnected.path=" << disconnected_path;
os << "\n";
return os;
@@ -221,7 +225,7 @@ public:
parent = NULL;
flags = { 0, MODE_UNSPECIFIED, 0, 0 };
flags = { 0, MODE_UNSPECIFIED, 0, 0, NULL };
rlimits = {0, {}};
std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL);

View File

@@ -13,10 +13,13 @@
#
# ------------------------------------------------------------------
import os
import subprocess
import sys
import unittest
from argparse import ArgumentParser
from shutil import rmtree
from tempfile import mkdtemp
import testlib
@@ -28,6 +31,15 @@ class AAErrorTests(testlib.AATestTemplate):
self.maxDiff = None
self.cmd_prefix = [config.parser, '--config-file=./parser.conf', '-S', '-I', 'errors']
self.tmpdir = os.path.realpath(mkdtemp(prefix='test-aa-parser-errors-'))
self.profile_dir = os.path.join(self.tmpdir, 'profile')
os.mkdir(self.profile_dir)
def tearDown(self):
if os.path.exists(self.tmpdir):
rmtree(self.tmpdir)
def _run_test(self, profile, message='', is_error=True):
cmd = self.cmd_prefix + [profile]
@@ -90,28 +102,65 @@ class AAErrorTests(testlib.AATestTemplate):
is_error=False
)
def test_non_existant_profile(self):
test_profile = os.path.join(self.profile_dir, "does-not-exist.sd")
self._run_test(
test_profile,
"File {} not found, skipping...\n".format(test_profile),
)
# We can run this test with multiple different arguments
def _test_non_existant_symlink_target(self):
"""Helper Function to test the parser on a symlink with a non-existent target"""
test_profile = os.path.join(self.profile_dir, "non-existant-target.sd")
os.symlink('does-not-exist.sd', test_profile)
self._run_test(
test_profile,
"File {} not found, skipping...\n".format(test_profile),
)
def test_non_existant_symlink_target(self):
'''Basic symlink test that goes nowhere'''
self._test_non_existant_symlink_target()
def test_non_existant_symlink_target_j0(self):
'''Basic symlink test that goes nowhere with 0 jobs'''
self.cmd_prefix.append('-j0')
self._test_non_existant_symlink_target()
def test_non_existant_symlink_target_j1(self):
'''Basic symlink test that goes nowhere with 1 job arg'''
self.cmd_prefix.append('-j1')
self._test_non_existant_symlink_target()
def test_non_existant_symlink_target_j8(self):
'''Basic symlink test that goes nowhere with 8 job arg'''
self.cmd_prefix.append('-j8')
self._test_non_existant_symlink_target()
def test_non_existant_symlink_target_jauto(self):
'''Basic symlink test that goes nowhere with auto job arg'''
self.cmd_prefix.append('-jauto')
self._test_non_existant_symlink_target()
def test_non_existant_symlink_target_in_directory(self):
'''Symlink test passing a directory to the parser'''
test_profile = os.path.join(self.profile_dir, "non-existant-target.sd")
os.symlink('does-not-exist.sd', test_profile)
self._run_test(
self.profile_dir,
"There was an error while loading profiles from {}\n".format(self.profile_dir),
)
def main():
global config
p = ArgumentParser()
p.add_argument('-p', '--parser', default=testlib.DEFAULT_PARSER, action="store", dest='parser',
help="Specify path of apparmor parser to use [default = %(default)s]")
p.add_argument('-v', '--verbose', action="store_true", dest="verbose")
config = p.parse_args()
verbosity = 2 if config.verbose else 1
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AAErrorTests))
try:
result = unittest.TextTestRunner(verbosity=verbosity).run(test_suite)
except Exception:
rc = 1
else:
rc = 0 if result.wasSuccessful() else 1
return rc
config, args = p.parse_known_args()
unittest.main(argv=sys.argv[:1] + args)
if __name__ == "__main__":
sys.exit(main())
main()

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(enforce, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(complain, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(kill, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt, enforce) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt, complain) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt, kill) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt, unconfined) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(enforce, kill, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(complain, kill, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,10 @@
#
#=DESCRIPTION Ensure conflicting mode flags cause an error
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(enforce, complain, kill, unconfined, prompt) {
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=foo/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar/
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=bar/
/does/not/exist flags=(attach_disconnected.path=@{var}/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,12 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,12 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(prompt audit) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo//) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,13 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
/does/not/exist flags=(attach_disconnected.path=/foo/bar) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=/foo/@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=/foo/@{var}/) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=@{var}/foo) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -0,0 +1,16 @@
#
#=DESCRIPTION validate some uses of the profile flags.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005
#
@{var}=/bar
/does/not/exist flags=(attach_disconnected.path=@{var}) {
#include <includes/base>
/usr/X11R6/lib/lib*so* r,
/does/not/exist r,
}

View File

@@ -119,7 +119,7 @@ CHECK_PROFILES=$(filter-out ${IGNORE_FILES} ${SUBDIRS}, $(wildcard ${PROFILES_SO
CHECK_ABSTRACTIONS=$(shell find ${ABSTRACTIONS_SOURCE} -type f -print)
.PHONY: check
check: check-parser check-logprof check-abstractions.d check-extras
check: check-parser check-logprof check-abstractions.d check-tunables.d check-extras
.PHONY: check-parser
check-parser: test-dependencies local
@@ -152,6 +152,15 @@ check-abstractions.d:
grep -q "^ include if exists <abstractions/$${file}.d>$$" $$file || { echo "$$file does not contain 'include if exists <abstractions/$${file}.d>'"; exit 1; } ; \
done
.PHONY: check-tunables.d
check-tunables.d:
@echo "*** Checking if all tunables (with a few exceptions) contain include if exists <tunables/*.d>"
$(Q)cd apparmor.d/tunables && for file in * ; do \
test -d "$$file" && continue ; \
test "$$file" = 'sys' && continue ; \
grep -q "^include if exists <tunables/$${file}.d>$$" $$file || { echo "$$file does not contain 'include if exists <tunables/$${file}.d>'"; exit 1; } ; \
done
.PHONY: check-extras
check-extras:
@echo "*** Checking if all extra profiles contain include if exists <local/*>"

View File

@@ -14,3 +14,6 @@
#
# Or if mysql databases are stored in /home:
# alias /var/lib/mysql/ -> /home/mysql/,
# Also, include files in tunables/alias.d for site-specific adjustments
include if exists <tunables/alias.d>

View File

@@ -9,3 +9,6 @@
include <tunables/securityfs>
@{apparmorfs}=@{securityfs}/apparmor/
# Also, include files in tunables/apparmorfs.d for site-specific adjustments
include if exists <tunables/apparmorfs.d>

View File

@@ -18,3 +18,5 @@
@{DOVECOT_MAILSTORE}=@{HOME}/Maildir/ @{HOME}/mail/ @{HOME}/Mail/ /var/vmail/ /var/mail/ /var/spool/mail/
# Also, include files in tunables/dovecot.d for site-specific adjustments
include if exists <tunables/dovecot.d>

View File

@@ -24,6 +24,5 @@
# For rules that only allows read access, use @{etc_ro}.
@{etc_rw}=/etc/
# Also, include files in tunables/etc.d/ for site-specific adjustments to
# @{etc_ro} and @{etc_rw}.
# Also, include files in tunables/etc.d for site-specific adjustments
include if exists <tunables/etc.d>

View File

@@ -21,3 +21,6 @@ include <tunables/xdg-user-dirs>
include <tunables/share>
include <tunables/etc>
include <tunables/run>
# Also, include files in tunables/global.d for site-specific adjustments
include if exists <tunables/global.d>

View File

@@ -20,6 +20,5 @@
# refer to a specific home directory
@{HOME}=@{HOMEDIRS}/*/ /root/
# Also, include files in tunables/home.d for site-specific adjustments to
# @{HOMEDIRS}.
include <tunables/home.d>
# Also, include files in tunables/home.d for site-specific adjustments
include if exists <tunables/home.d>

View File

@@ -31,3 +31,6 @@
# until kernel var is implemented
@{sys}=/sys/
# Also, include files in tunables/kernelvars.d for site-specific adjustments
include if exists <tunables/kernelvars.d>

View File

@@ -12,6 +12,5 @@
# install prefixes.
@{multiarch}=*-linux-gnu*
# Also, include files in tunables/multiarch.d for site and packaging
# specific adjustments to @{multiarch}.
include <tunables/multiarch.d>
# Also, include files in tunables/multiarch.d for site-specific adjustments
include if exists <tunables/multiarch.d>

View File

@@ -12,3 +12,6 @@
#Add your ntpd devices here eg. if you have a DCF clock
# @{NTPD_DEVICE}=/dev/ttyS*
@{NTPD_DEVICE}="/dev/tty10"
# Also, include files in tunables/ntpd.d for site-specific adjustments
include if exists <tunables/ntpd.d>

View File

@@ -10,3 +10,6 @@
# @{PROC} is the location where procfs is mounted.
@{PROC}=/proc/
# Also, include files in tunables/proc.d for site-specific adjustments
include if exists <tunables/proc.d>

View File

@@ -1 +1,4 @@
@{run}=/run/ /var/run/
# Also, include files in tunables/run.d for site-specific adjustments
include if exists <tunables/run.d>

View File

@@ -8,3 +8,6 @@
# @{securityfs} is the location where securityfs is mounted.
@{securityfs}=@{sys}/kernel/security/
# Also, include files in tunables/securityfs.d for site-specific adjustments
include if exists <tunables/securityfs.d>

View File

@@ -13,3 +13,6 @@
# XDG_DATA_DIRS or XDG_DATA_HOME, and are the parent directory
# for the same subdirectories as @{system_share_dirs}
@{user_share_dirs} = @{HOME}/.local{,/share/@{flatpak_exports_root}}/share
# Also, include files in tunables/share.d for site-specific adjustments
include if exists <tunables/share.d>

View File

@@ -20,5 +20,4 @@
@{XDG_VIDEOS_DIR}="Videos"
# Also, include files in tunables/xdg-user-dirs.d for site-specific adjustments
# to the various XDG directories
include <tunables/xdg-user-dirs.d>
include if exists <tunables/xdg-user-dirs.d>

View File

@@ -13,7 +13,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-anvil /usr/lib/dovecot/anvil {
profile dovecot-anvil /usr/lib*/dovecot/anvil {
include <abstractions/base>
include <abstractions/dovecot-common>
@@ -24,7 +24,7 @@ profile dovecot-anvil /usr/lib/dovecot/anvil {
@{run}/dovecot/anvil rw,
@{run}/dovecot/anvil-auth-penalty rw,
/usr/lib/dovecot/anvil mr,
/usr/lib*/dovecot/anvil mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.anvil>

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-auth /usr/lib/dovecot/auth {
profile dovecot-auth /usr/lib*/dovecot/auth {
include <abstractions/authentication>
include <abstractions/base>
include <abstractions/mysql>
@@ -34,7 +34,7 @@ profile dovecot-auth /usr/lib/dovecot/auth {
/etc/my.cnf.d/*.cnf r,
/etc/dovecot/* r,
/usr/lib/dovecot/auth mr,
/usr/lib*/dovecot/auth mr,
/var/lib/dovecot/auth-chroot/* r,
# kerberos replay cache

View File

@@ -13,7 +13,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-config /usr/lib/dovecot/config {
profile dovecot-config /usr/lib*/dovecot/config {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -24,8 +24,8 @@ profile dovecot-config /usr/lib/dovecot/config {
/etc/dovecot/** r,
/usr/bin/doveconf rix,
/usr/lib/dovecot/config mr,
/usr/lib/dovecot/managesieve Px,
/usr/lib*/dovecot/config mr,
/usr/lib*/dovecot/managesieve Px,
/usr/share/dovecot/** r,
/var/lib/dovecot/ssl-parameters.dat r,

View File

@@ -16,7 +16,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-deliver /usr/lib/dovecot/deliver {
profile dovecot-deliver /usr/lib*/dovecot/deliver {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -32,7 +32,7 @@ profile dovecot-deliver /usr/lib/dovecot/deliver {
/etc/dovecot/dovecot-postfix.conf r, # ???
@{HOME} r, # ???
/usr/lib/dovecot/deliver mr,
/usr/lib*/dovecot/deliver mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.deliver>

View File

@@ -13,7 +13,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-dict /usr/lib/dovecot/dict {
profile dovecot-dict /usr/lib*/dovecot/dict {
include <abstractions/base>
include <abstractions/mysql>
include <abstractions/nameservice>
@@ -27,7 +27,7 @@ profile dovecot-dict /usr/lib/dovecot/dict {
/etc/dovecot/dovecot-database.conf.ext r,
/etc/dovecot/dovecot-dict-sql.conf.ext r,
/etc/my.cnf r,
/usr/lib/dovecot/dict mr,
/usr/lib*/dovecot/dict mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.dict>

View File

@@ -11,7 +11,7 @@
include <tunables/global>
profile dovecot-director /usr/lib/dovecot/director flags=(attach_disconnected) {
profile dovecot-director /usr/lib*/dovecot/director flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/nameservice>
@@ -20,7 +20,7 @@ profile dovecot-director /usr/lib/dovecot/director flags=(attach_disconnected) {
capability sys_chroot,
/run/dovecot/login/proxy-notify rw,
/usr/lib/dovecot/director mr,
/usr/lib*/dovecot/director mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.director>

View File

@@ -11,11 +11,11 @@
include <tunables/global>
profile dovecot-doveadm-server /usr/lib/dovecot/doveadm-server flags=(attach_disconnected) {
profile dovecot-doveadm-server /usr/lib*/dovecot/doveadm-server flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/dovecot-common>
/usr/lib/dovecot/doveadm-server mr,
/usr/lib*/dovecot/doveadm-server mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.doveadm-server>

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-dovecot-auth /usr/lib/dovecot/dovecot-auth {
profile dovecot-dovecot-auth /usr/lib*/dovecot/dovecot-auth {
include <abstractions/authentication>
include <abstractions/base>
include <abstractions/nameservice>
@@ -25,7 +25,7 @@ profile dovecot-dovecot-auth /usr/lib/dovecot/dovecot-auth {
capability dac_override,
@{PROC}/@{pid}/mounts r,
/usr/lib/dovecot/dovecot-auth mr,
/usr/lib*/dovecot/dovecot-auth mr,
@{run}/dovecot/** rw,
# required for postfix+dovecot integration
/var/spool/postfix/private/dovecot-auth w,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-dovecot-lda /usr/lib/dovecot/dovecot-lda flags=(attach_disconnected) {
profile dovecot-dovecot-lda /usr/lib*/dovecot/dovecot-lda flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -30,7 +30,7 @@ profile dovecot-dovecot-lda /usr/lib/dovecot/dovecot-lda flags=(attach_disconnec
@{run}/dovecot/mounts r,
@{run}/dovecot/auth-userdb rw,
/usr/bin/doveconf mrix,
/usr/lib/dovecot/dovecot-lda mrix,
/usr/lib*/dovecot/dovecot-lda mrix,
/usr/{bin,sbin}/sendmail Cx -> sendmail,
/usr/share/dovecot/protocols.d/ r,
/usr/share/dovecot/protocols.d/** r,

View File

@@ -15,7 +15,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-imap /usr/lib/dovecot/imap {
profile dovecot-imap /usr/lib*/dovecot/imap {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -37,7 +37,7 @@ profile dovecot-imap /usr/lib/dovecot/imap {
@{PROC}/@{pid}/attr/{apparmor/,}current rw,
@{PROC}/@{pid}/stat r,
/usr/bin/doveconf rix,
/usr/lib/dovecot/imap mrix,
/usr/lib*/dovecot/imap mrix,
/usr/share/dovecot/** r,
@{run}/dovecot/login/imap rw,
@{run}/dovecot/auth-master rw,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-imap-login /usr/lib/dovecot/imap-login {
profile dovecot-imap-login /usr/lib*/dovecot/imap-login {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/openssl>
@@ -26,7 +26,7 @@ profile dovecot-imap-login /usr/lib/dovecot/imap-login {
network inet6 stream,
network unix stream,
/usr/lib/dovecot/imap-login mr,
/usr/lib*/dovecot/imap-login mr,
@{run}/dovecot/anvil rw,
@{run}/dovecot/login-master-notify* rw,
@{run}/dovecot/login/ r,

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-lmtp /usr/lib/dovecot/lmtp {
profile dovecot-lmtp /usr/lib*/dovecot/lmtp {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -35,7 +35,7 @@ profile dovecot-lmtp /usr/lib/dovecot/lmtp {
owner @{PROC}/@{pid}/stat r,
@{PROC}/*/mounts r,
/tmp/dovecot.lmtp.* rw,
/usr/lib/dovecot/lmtp mr,
/usr/lib*/dovecot/lmtp mr,
@{run}/dovecot/mounts r,
# Site-specific additions and overrides. See local/README for details.

View File

@@ -13,11 +13,11 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-log /usr/lib/dovecot/log flags=(attach_disconnected) {
profile dovecot-log /usr/lib*/dovecot/log flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/dovecot-common>
/usr/lib/dovecot/log mr,
/usr/lib*/dovecot/log mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.log>

View File

@@ -15,7 +15,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-managesieve /usr/lib/dovecot/managesieve {
profile dovecot-managesieve /usr/lib*/dovecot/managesieve {
include <abstractions/base>
include <abstractions/dovecot-common>
@@ -29,7 +29,7 @@ profile dovecot-managesieve /usr/lib/dovecot/managesieve {
/etc/dovecot/** r,
/usr/bin/doveconf rix,
/usr/lib/dovecot/managesieve mrix,
/usr/lib*/dovecot/managesieve mrix,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.managesieve>

View File

@@ -16,7 +16,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-managesieve-login /usr/lib/dovecot/managesieve-login {
profile dovecot-managesieve-login /usr/lib*/dovecot/managesieve-login {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/openssl>
@@ -28,7 +28,7 @@ profile dovecot-managesieve-login /usr/lib/dovecot/managesieve-login {
network inet6 stream,
network unix stream,
/usr/lib/dovecot/managesieve-login mr,
/usr/lib*/dovecot/managesieve-login mr,
@{run}/dovecot/login-master-notify* rw,
@{run}/dovecot/login/ r,
@{run}/dovecot/login/* rw,

View File

@@ -15,7 +15,7 @@ abi <abi/4.0>,
include <tunables/global>
include <tunables/dovecot>
profile dovecot-pop3 /usr/lib/dovecot/pop3 {
profile dovecot-pop3 /usr/lib*/dovecot/pop3 {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/dovecot-common>
@@ -27,7 +27,7 @@ profile dovecot-pop3 /usr/lib/dovecot/pop3 {
@{HOME} r, # ???
@{PROC}/@{pid}/stat r,
/usr/lib/dovecot/pop3 mr,
/usr/lib*/dovecot/pop3 mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.pop3>

View File

@@ -14,7 +14,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-pop3-login /usr/lib/dovecot/pop3-login {
profile dovecot-pop3-login /usr/lib*/dovecot/pop3-login {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/openssl>
@@ -26,7 +26,7 @@ profile dovecot-pop3-login /usr/lib/dovecot/pop3-login {
network inet6 stream,
network unix stream,
/usr/lib/dovecot/pop3-login mr,
/usr/lib*/dovecot/pop3-login mr,
@{run}/dovecot/anvil rw,
@{run}/dovecot/login-master-notify* rw,
@{run}/dovecot/login/ r,

View File

@@ -15,7 +15,7 @@
include <tunables/dovecot>
include <tunables/global>
profile dovecot-replicator /usr/lib/dovecot/replicator {
profile dovecot-replicator /usr/lib*/dovecot/replicator {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/nameservice>
@@ -25,7 +25,7 @@ profile dovecot-replicator /usr/lib/dovecot/replicator {
/etc/dovecot/conf.d/ r,
/etc/dovecot/conf.d/** r,
/etc/dovecot/dovecot.conf r,
/usr/lib/dovecot/replicator mr,
/usr/lib*/dovecot/replicator mr,
/usr/share/dovecot/** r,
/{,var/}run/dovecot/auth-master rw,
@{DOVECOT_MAILSTORE}/ rw,

View File

@@ -14,14 +14,14 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-script-login /usr/lib/dovecot/script-login {
profile dovecot-script-login /usr/lib*/dovecot/script-login {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/nameservice>
capability setuid,
/usr/lib/dovecot/script-login mrPx,
/usr/lib*/dovecot/script-login mrPx,
# NOTE: You'll need to allow execution of your actual login script.
# The recommended way is to add a rule for it in local/usr.lib.dovecot.script-login

View File

@@ -13,13 +13,13 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-ssl-params /usr/lib/dovecot/ssl-params {
profile dovecot-ssl-params /usr/lib*/dovecot/ssl-params {
include <abstractions/base>
include <abstractions/dovecot-common>
@{run}/dovecot/ssl-params rw,
@{run}/dovecot/login/ssl-params rw,
/usr/lib/dovecot/ssl-params mr,
/usr/lib*/dovecot/ssl-params mr,
/var/lib/dovecot/ssl-parameters.dat rw,
/var/lib/dovecot/ssl-parameters.dat.tmp rwk,

View File

@@ -13,7 +13,7 @@ abi <abi/4.0>,
include <tunables/global>
profile dovecot-stats /usr/lib/dovecot/stats {
profile dovecot-stats /usr/lib*/dovecot/stats {
include <abstractions/base>
include <abstractions/dovecot-common>
@@ -24,7 +24,7 @@ profile dovecot-stats /usr/lib/dovecot/stats {
network inet stream,
network inet6 stream,
/usr/lib/dovecot/stats mr,
/usr/lib*/dovecot/stats mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.stats>

View File

@@ -33,10 +33,10 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
capability sys_chroot,
capability sys_resource,
signal send peer=/usr/lib/dovecot/*,
signal send peer=/usr/lib*/dovecot/*,
signal send peer=dovecot-*,
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
unix (receive, send) type=stream peer=(label=/usr/lib*/dovecot/anvil),
unix (receive, send) type=stream peer=(label=dovecot-anvil),
/etc/dovecot/** r,
@@ -46,26 +46,26 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
@{PROC}/@{pid}/mounts r,
@{PROC}/sys/fs/suid_dumpable r,
/usr/bin/doveconf rix,
/usr/lib/dovecot/anvil mrPx,
/usr/lib/dovecot/auth mrPx,
/usr/lib/dovecot/config mrPx,
/usr/lib/dovecot/dict mrPx,
/usr/lib/dovecot/director mrPx,
/usr/lib/dovecot/doveadm-server mrPx,
/usr/lib/dovecot/dovecot-auth Pxmr,
/usr/lib/dovecot/imap Pxmr,
/usr/lib/dovecot/imap-login Pxmr,
/usr/lib/dovecot/lmtp mrPx,
/usr/lib/dovecot/log mrPx,
/usr/lib/dovecot/managesieve mrPx,
/usr/lib/dovecot/managesieve-login Pxmr,
/usr/lib/dovecot/pop3 mrPx,
/usr/lib/dovecot/pop3-login Pxmr,
/usr/lib/dovecot/replicator mrPx,
/usr/lib/dovecot/script-login Px,
/usr/lib/dovecot/ssl-build-param rix,
/usr/lib/dovecot/ssl-params mrPx,
/usr/lib/dovecot/stats Px,
/usr/lib*/dovecot/anvil mrPx,
/usr/lib*/dovecot/auth mrPx,
/usr/lib*/dovecot/config mrPx,
/usr/lib*/dovecot/dict mrPx,
/usr/lib*/dovecot/director mrPx,
/usr/lib*/dovecot/doveadm-server mrPx,
/usr/lib*/dovecot/dovecot-auth Pxmr,
/usr/lib*/dovecot/imap Pxmr,
/usr/lib*/dovecot/imap-login Pxmr,
/usr/lib*/dovecot/lmtp mrPx,
/usr/lib*/dovecot/log mrPx,
/usr/lib*/dovecot/managesieve mrPx,
/usr/lib*/dovecot/managesieve-login Pxmr,
/usr/lib*/dovecot/pop3 mrPx,
/usr/lib*/dovecot/pop3-login Pxmr,
/usr/lib*/dovecot/replicator mrPx,
/usr/lib*/dovecot/script-login Px,
/usr/lib*/dovecot/ssl-build-param rix,
/usr/lib*/dovecot/ssl-params mrPx,
/usr/lib*/dovecot/stats Px,
/usr/{bin,sbin}/dovecot mrix,
/usr/share/dovecot/dh.pem r,
/usr/share/dovecot/protocols.d/ r,

View File

@@ -22,7 +22,7 @@ include <tunables/global>
# /usr/lib/firefox-4.0b8/firefox
# but not:
# /usr/lib/firefox-4.0b8/firefox.sh
profile firefox @{MOZ_LIBDIR}/firefox{,*[^s][^h]} {
profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
include <abstractions/audio>
include <abstractions/cups-client>
include <abstractions/dbus-strict>
@@ -279,11 +279,17 @@ profile firefox @{MOZ_LIBDIR}/firefox{,*[^s][^h]} {
interface=org.gtk.vfs.Mount
member={CreateFileMonitor,Enumerate,QueryInfo}
peer=(label=unconfined),
dbus (receive)
bus=session
path=/org/gtk/vfs/mounttracker
interface=org.gtk.vfs.MountTracker
member=Mounted
peer=(label=unconfined),
dbus (send)
bus=session
path=/org/gtk/vfs/mounttracker
interface=org.gtk.vfs.MountTracker
member={ListMountableInfo,ListMounts2,LookupMount,Mounted}
member={ListMountableInfo,ListMounts2,LookupMount}
peer=(label=unconfined),
# Allow access to xdg-desktop-portal and xdg-document-portal (LP: #1974449)

View File

@@ -102,10 +102,18 @@ create_dir="$new_root:w $put_old:w"
# Ensure everything works as expected when unconfined
do_test "attach_disconnected" pass $file $att_dis_client $socket $loop_device $new_root $put_old
# TODO: adding attach_disconnected.path to a replaced unconfined
genprofile $file_perm unix:create $socket:rw $att_dis_client:px -- image=$att_dis_client $file_perm unix:create $socket:rw $create_dir $cap "pivot_root:ALL" "mount:ALL" flag:attach_disconnected
do_test "attach_disconnected" pass $file $att_dis_client $socket $loop_device $new_root $put_old
genprofile $file_perm unix:create $socket:rw $att_dis_client:px -- image=$att_dis_client $file_perm unix:create $socket:rw $create_dir $cap "pivot_root:ALL" "mount:ALL" flag:attach_disconnected flag:attach_disconnected.path=/foo/
do_test "attach_disconnected.path rule at /" fail $file $att_dis_client $socket $loop_device $new_root $put_old
do_test "attach_disconnected.path" pass "/foo/$file" $att_dis_client $socket $loop_device $new_root $put_old
genprofile $file_perm unix:create $socket:rw $att_dis_client:px -- image=$att_dis_client $file_perm unix:create $socket:rw $create_dir $cap "pivot_root:ALL" "mount:ALL" flag:no_attach_disconnected
do_test "no_attach_disconnected" fail $file $att_dis_client $socket $loop_device $new_root $put_old

View File

@@ -70,9 +70,14 @@ kernel_features()
# check if feature is in file
feature=$(basename "$features_dir/$f")
file=$(dirname "$features_dir/$f")
if ! grep -q $feature $file; then
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 2;
return 3;
fi
fi
done

View File

@@ -72,12 +72,13 @@ parser.add_argument('-j', '--json', action="store_true", help=_('Input and Outpu
parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS)
args = parser.parse_args()
if args.json:
aaui.set_json_mode()
profiling = args.program
apparmor.init_aa(confdir=args.configdir, profiledir=args.dir)
if args.json:
aaui.set_json_mode(apparmor.cfg)
apparmor.set_logfile(args.file)
aa_mountpoint = apparmor.check_for_apparmor()

View File

@@ -29,19 +29,20 @@ parser.add_argument('-f', '--file', type=str, help=_('path to logfile'))
parser.add_argument('-m', '--mark', type=str, help=_('mark in the log to start processing after'))
parser.add_argument('-j', '--json', action='store_true', help=_('Input and Output in JSON'))
parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS)
parser.add_argument('--no-check-mountpoint', action='store_true', help=argparse.SUPPRESS)
args = parser.parse_args()
if args.json:
aaui.set_json_mode()
logmark = args.mark or ''
apparmor.init_aa(confdir=args.configdir, profiledir=args.dir)
if args.json:
aaui.set_json_mode(apparmor.cfg)
apparmor.set_logfile(args.file)
aa_mountpoint = apparmor.check_for_apparmor()
if not aa_mountpoint:
if not aa_mountpoint and not args.no_check_mountpoint:
raise AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
apparmor.loadincludes()

View File

@@ -1031,7 +1031,7 @@ def ask_exec(hashlog):
if target_profile and hashlog[aamode].get(target_profile):
hashlog[aamode][target_profile]['final_name'] = profile
elif re.search('^CMD_(px|nx|pix|nix)', ans):
elif ans.startswith('CMD_px') or ans.startswith('CMD_pix'):
if to_name:
exec_target = to_name
@@ -1087,6 +1087,8 @@ def ask_exec(hashlog):
elif ans.startswith('CMD_ux'):
continue
else:
raise AppArmorBug('Unhandled ans %s, please open a bugreport!' % ans)
def order_globs(globs, original_path):
"""Returns the globs in sorted order, more specific behind"""

View File

@@ -33,14 +33,20 @@ debug_logger = DebugLogger('UI')
ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'}
UI_mode = 'text'
jsonlog = None
def write_json(jsonout):
print(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')))
jtxt = json.dumps(jsonout, sort_keys=False, separators=(',', ': '))
if jsonlog:
jsonlog.write('o ' + jtxt + '\n')
print(jtxt)
sys.stdout.flush()
def set_json_mode():
def set_json_mode(cfg):
"""
Currently this is only used by aa-genprof and aa-logprof, while e.g.
aa-status generates its own JSON output.
@@ -50,8 +56,14 @@ def set_json_mode():
Current known consumers of the JSON output:
- YaST
The cfg parameter expects the parsed logprof.conf aka apparmor.aa.cfg.
"""
global UI_mode
global UI_mode, jsonlog
if int(cfg['settings'].get('json_log', False)):
jsonlog = NamedTemporaryFile('w', prefix='aa-jsonlog-', delete=False, encoding='utf-8')
UI_mode = 'json'
jsonout = {'dialog': 'apparmor-json-version', 'data': '2.12'}
write_json(jsonout)
@@ -67,6 +79,10 @@ def set_text_mode():
# for the dialog type
def json_response(dialog_type):
string = input('\n')
if jsonlog:
jsonlog.write('i ' + string + '\n')
rh = json.loads(string.strip())
if rh["dialog"] != dialog_type:
raise AppArmorException('Expected response %s got %s.' % (dialog_type, string))

View File

@@ -35,6 +35,10 @@
# files.
custom_includes =
# When called with --json, log all input and output to a tempfile (/tmp/aa-jsonlog-*)
# Only enable for debugging.
# Note that aa-logprof will not display any hint that aa-jsonlog-* gets written.
json_log = 0
[qualifiers]
# things will be painfully broken if bash has a profile

View File

@@ -21,7 +21,7 @@ COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules
# files that don't have 100% test coverage
INCOMPLETE_COVERAGE=libraries/libapparmor/swig/python/.*/LibAppArmor/LibAppArmor.py|utils/apparmor/aa.py|utils/apparmor/common.py|utils/apparmor/config.py|utils/apparmor/easyprof.py|utils/apparmor/fail.py|utils/apparmor/logparser.py|utils/apparmor/profile_storage.py|utils/apparmor/rules.py|utils/apparmor/ui.py|minitools_test.py
INCOMPLETE_COVERAGE=libraries/libapparmor/swig/python/.*/LibAppArmor/LibAppArmor.py|utils/aa-logprof|utils/apparmor/aa.py|utils/apparmor/common.py|utils/apparmor/config.py|utils/apparmor/easyprof.py|utils/apparmor/fail.py|utils/apparmor/logparser.py|utils/apparmor/profile_storage.py|utils/apparmor/rules.py|utils/apparmor/ui.py|minitools_test.py
ifdef USE_SYSTEM

View File

@@ -0,0 +1,3 @@
type=AVC msg=audit(1691930856.284:29963): apparmor="DENIED" operation="open" class="file" profile="ping" name="/proc/21622/cmdline" pid=9136 comm="cat" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
type=SYSCALL msg=audit(1691930856.284:29963): arch=c000003e syscall=257 success=no exit=-13 a0=ffffff9c a1=7ffc4539abf8 a2=0 a3=0 items=0 ppid=21622 pid=9136 auid=1000 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 ses=2 comm="cat" exe="/usr/bin/cat" subj=ping key=(null)
type=AVC msg=audit(1691930881.661:29975): apparmor="STATUS" operation="profile_replace" profile="apparmor_parser" name="ping" pid=10005 comm="apparmor_parser"

View File

@@ -0,0 +1,33 @@
abi <abi/4.0>,
include <tunables/global>
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2010 Canonical Ltd.
#
# 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.
#
# ------------------------------------------------------------------
profile ping /{usr/,}bin/{,iputils-}ping {
include <abstractions/base>
include <abstractions/consoles>
include <abstractions/nameservice>
include if exists <local/bin.ping>
capability net_raw,
capability setuid,
network inet raw,
network inet6 raw,
/etc/modules.conf r,
/proc/21622/cmdline r,
/{,usr/}bin/{,iputils-}ping mrix,
}

View File

@@ -0,0 +1,13 @@
o {"dialog": "apparmor-json-version","data": "2.12"}
o {"dialog": "info","data": "Updating AppArmor profiles in /etc/apparmor.d."}
o {"dialog": "info","data": "Reading log entries from /var/log/audit/audit.log."}
o {"dialog": "info","data": "Complain-mode changes:"}
o {"dialog": "info","data": "Enforce-mode changes:"}
o {"dialog": "promptuser","title": null,"headers": {"Profile": "ping","Path": "/proc/21622/cmdline","New Mode": "owner r","Severity": 6},"explanation": null,"options": ["owner /proc/*/cmdline r,","owner /proc/21622/cmdline r,"],"menu_items": ["(A)llow","[(D)eny]","(I)gnore","(G)lob","Glob with (E)xtension","(N)ew","Audi(t)","(O)wner permissions off","Abo(r)t","(F)inish"],"default_key": "d"}
i {"dialog":"promptuser","selected":0,"response_key":"o"}
o {"dialog": "promptuser","title": null,"headers": {"Profile": "ping","Path": "/proc/21622/cmdline","New Mode": "r","Severity": 6},"explanation": null,"options": ["/proc/*/cmdline r,","/proc/21622/cmdline r,"],"menu_items": ["(A)llow","[(D)eny]","(I)gnore","(G)lob","Glob with (E)xtension","(N)ew","Audi(t)","(O)wner permissions on","Abo(r)t","(F)inish"],"default_key": "d"}
i {"dialog":"promptuser","selected":1,"response_key":"a"}
o {"dialog": "info","data": "Adding /proc/21622/cmdline r, to profile."}
o {"dialog": "promptuser","title": "Changed Local Profiles","headers": {},"explanation": "The following local profiles were changed. Would you like to save them?","options": ["ping"],"menu_items": ["(S)ave Changes","Save Selec(t)ed Profile","[(V)iew Changes]","View Changes b/w (C)lean profiles","Abo(r)t"],"default_key": "v"}
i {"dialog":"promptuser","selected":0,"response_key":"t"}
o {"dialog": "info","data": "Writing updated profile for ping."}

1
utils/test/severity.db Symbolic link
View File

@@ -0,0 +1 @@
../severity.db

View File

@@ -61,7 +61,7 @@ class AACliBootstrapTest(AATest):
self.assertEqual(sys.stdout.getvalue(), 'Test string\n')
def test_aa_ui_info_json(self):
aaui.set_json_mode()
aaui.set_json_mode({'settings': {}})
sys.stdout.getvalue()
aaui.UI_Info('Test string')
self.assertEqual(

119
utils/test/test-logprof.py Normal file
View File

@@ -0,0 +1,119 @@
#! /usr/bin/python3
# ------------------------------------------------------------------
#
# Copyright (C) 2023 Christian Boltz <apparmor@cboltz.de>
#
# 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.
#
# ------------------------------------------------------------------
import os
import shutil
import subprocess
import sys
import unittest
# import apparmor.aa as aa # see the setup_aa() call for details
from common_test import AATest, read_file, setup_all_loops # , setup_aa
class TestLogprof(AATest):
# This test expects a set of files:
# - logprof/TESTNAME.auditlog - audit.log
# - logprof/TESTNAME.jsonlog - expected aa-logprof --json input and output (gathered with json_log=1 in logprof.conf)
# - logprof/TESTNAME.PROFILE - one or more profiles in the expected state
# where TESTNAME is the name given in the first column of 'tests'
tests = (
# test name # profiles to verify
('ping', ['bin.ping']),
)
def AASetup(self):
self.createTmpdir()
# copy the local profiles to the test directory
self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
def AATeardown(self):
self._terminate()
def _startLogprof(self, auditlog):
exe = [sys.executable]
if 'coverage' in sys.modules:
exe = exe + ['-m', 'coverage', 'run', '--branch', '-p']
exe = exe + ['../aa-logprof', '--json', '--configdir', './', '-f', auditlog, '-d', self.profile_dir, '--no-check-mountpoint']
process = subprocess.Popen(
exe,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
# stderr=subprocess.STDOUT,
env={'LANG': 'C',
'PYTHONPATH': os.environ.get('PYTHONPATH', ''),
'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''),
},
)
return process
def _terminate(self):
self.process.stdin.close()
self.process.stdout.close()
self.process.terminate()
self.process.wait(timeout=0.2)
def _run_test(self, params, expected):
auditlog = './logprof/%s.auditlog' % params
jsonlog = './logprof/%s.jsonlog' % params
jlog = read_file(jsonlog)
jlog = jlog.replace('/etc/apparmor.d', self.profile_dir)
jlog = jlog.replace('/var/log/audit/audit.log', auditlog)
jlog = jlog.strip().split('\n')
self.process = self._startLogprof(auditlog)
for line in jlog:
if line.startswith('o '): # read from stdout
output = self.process.stdout.readline().decode("utf-8").strip()
self.assertEqual(output, line[2:])
elif line.startswith('i '): # send to stdin
# expect an empty prompt line
output = self.process.stdout.readline().decode("utf-8").strip()
self.assertEqual(output, '')
# "type" answer
self.process.stdin.write(line[2:].encode("utf-8") + b"\n")
self.process.stdin.flush()
else:
raise Exception('Unknown line in json log %s: %s' % (jsonlog, line))
# give logprof some time to write the updated profile and terminate
self.process.wait(timeout=0.2)
self.assertEqual(self.process.returncode, 0)
for file in expected:
exp = read_file('./logprof/%s.%s' % (params, file))
actual = read_file(os.path.join(self.profile_dir, file))
# remove '# Last Modified:' line from updated profile
actual = actual.split('\n')
if actual[0].startswith('# Last Modified:'):
actual = actual[1:]
actual = '\n'.join(actual)
self.assertEqual(actual, exp)
# if you import apparmor.aa and call init_aa() in your tests, uncomment this
# setup_aa(aa)
setup_all_loops(__name__)
if __name__ == '__main__':
unittest.main(verbosity=1)

View File

@@ -154,6 +154,21 @@ exception_not_raised = (
'profile/flags/flags_bad44.sd',
'profile/flags/flags_bad45.sd',
'profile/flags/flags_bad46.sd',
'profile/flags/flags_bad47.sd',
'profile/flags/flags_bad48.sd',
'profile/flags/flags_bad49.sd',
'profile/flags/flags_bad50.sd',
'profile/flags/flags_bad51.sd',
'profile/flags/flags_bad52.sd',
'profile/flags/flags_bad53.sd',
'profile/flags/flags_bad54.sd',
'profile/flags/flags_bad55.sd',
'profile/flags/flags_bad56.sd',
'profile/flags/flags_bad_disconnected_path1.sd',
'profile/flags/flags_bad_disconnected_path2.sd',
'profile/flags/flags_bad_disconnected_path3.sd',
'profile/flags/flags_bad_disconnected_path4.sd',
'profile/flags/flags_bad_disconnected_path5.sd',
'profile/profile_ns_bad8.sd', # 'profile :ns/t' without terminating ':'
'ptrace/bad_05.sd', # actually contains a capability rule with invalid (ptrace-related) keyword
'ptrace/bad_06.sd', # actually contains a capability rule with invalid (ptrace-related) keyword