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

Compare commits

...

80 Commits

Author SHA1 Message Date
John Johansen
f2fb53c6c3 Release: Bumper version for the 2.12.3 release
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-18 01:46:41 -07:00
Daniel Richard G
3ae5213241 Updated abstractions to allow writing to some common config dirs
(cherry picked from commit 7972c038d7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
Daniel Richard G
053b1df7b1 Updated abstractions to allow creating some common config dirs
(cherry picked from commit 094dc741ee)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
Jörg Sommer
e9f12f3adb profiles/gnome: add @{HOME}/.cache/gtk-3.0
Found this path is used by gtk_compose_hash_get_cache_path() in
gtkcomposetable.c.

(cherry picked from commit 6da7ed2a78)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
Daniel Richard G
bcd7ee7b97 ldapclient abstraction: allow rw access to the nslcd socket.
This addresses https://launchpad.net/bugs/1575438 and also the case of
applications accessing the socket directly (due to NSS config).

(cherry picked from commit ac1d0545f4)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
Vincas Dargis
0144df6b75 Update nvidia for reading application profiles
Add file rule to allow reading application profiles for NVIDIA
Linux graphics driver.

(cherry picked from commit f2e0fdc72b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
segfault
41702a0c35 abstractions/python: allow /usr/local/lib/python3
(cherry picked from commit 548de2f3b8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-14 04:59:27 -07:00
Cameron Nemo
3e71e003c6 abstractions/qt5: read user configuration
Signed-off-by: Cameron Nemo <camerontnorman@gmail.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 6d81563267)
2019-06-14 04:59:27 -07:00
Christian Boltz
28c8a3a760 syslog-ng: add abstractions/python for python-parser
When running syslog-ng with a defined python-parser, it needs access to
python libraries.

For details about python-parser, see
https://www.syslog-ng.com/community/b/blog/posts/format-your-log-messages-in-python

References: https://github.com/balabit/syslog-ng/issues/2625
PR: https://gitlab.com/apparmor/apparmor/merge_requests/361
(cherry picked from commit 234a924480)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-13 17:41:43 -07:00
Jörg Sommer
99755daafb parser: Fix parsing of arrow “px -> …”
The parser failed to read the profile name after the the arrow. Rules with
`-> foo-bar;` failed with “Found unexpected character: '-'”. Rules with
`-> @{tgt};` compiled fine, but failed at runtime with “profile transition
not found”.

The patch was written by sbeattie and published on
https://paste.ubuntu.com/p/tzxxmVwGJ8/

https://matrix.to/#/!pNJIrowvqsuGgjXsEY:matrix.org/$15477566201815716pmube:matrix.org?via=matrix.org&via=alea.gnuu.de
PR: https://gitlab.com/apparmor/apparmor/merge_requests/334
(cherry picked from commit 0e0663e99e)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-06-13 17:36:29 -07:00
John Johansen
224b9593e9 parser: Don't skip cache just because optimizations are specified
The parser currently skips the cache if optimizations are specified
because it can not determine if the cached policy was compiled
with the specified optimization. However this causes cache misses
even if policy is cached with those options, and distros are setting
some optimizations by default.

Instead of skipping reading the cache if optimizations are set, users
can force overwriting the cache if needed, until the parser can
store aditional meta info in the cache.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/385
BugLink: http://bugs.launchpad.net/bugs/1820068
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit f6cd5c01c1)
2019-06-13 17:22:16 -07:00
Christian Boltz
7dcb4a4f77 Merge branch 'cboltz-dovecot-backports' into 'apparmor-2.13'
[2.12+2.13] backport dovecot profile additions

See merge request apparmor/apparmor!389

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

(cherry picked from commit 39a81f4a19)

e97af4af backport dovecot profile additions
2019-06-13 20:33:52 +00:00
Christian Boltz
c6b8354fc5 Merge branch 'cboltz-postfix-name' into 'apparmor-2.13'
[2.12+2.13] make abstractions/postfix-common compatible with latest postfix profiles

See merge request apparmor/apparmor!387

Seth Arnold <seth.arnold@canonical.com>

(cherry picked from commit 9318977332)

4573d252 make abstractions/postfix-common compatible with latest postfix profiles
2019-06-13 20:06:43 +00:00
Christian Boltz
1495b65f80 Merge branch 'cboltz-backports-from-2.13' into 'apparmor-2.12'
[2.12] profile backports from 2.13

Backport two profile fixes that made it into 2.13, but not into 2.12:

* dovecot/lmtp: allow dac_read_search
* Allow dovecot-lda to read anything under /usr/share/dovecot/protocols.d/.

See merge request apparmor/apparmor!386

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2019-06-13 19:02:55 +00:00
Christian Boltz
a70161a549 dovecot/lmtp: allow dac_read_search
Fixes https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=887591

(cherry picked from commit 1541175c36)
2019-06-13 20:57:57 +02:00
intrigeri
316f992b41 Allow dovecot-lda to read anything under /usr/share/dovecot/protocols.d/.
On current Debian sid it needs to read
/usr/share/dovecot/protocols.d/imapd.protocol, which is not surprising given it
already needed read access to /usr/share/dovecot/protocols.d/.

(cherry picked from commit 1b51dac4c9)
2019-06-13 20:57:25 +02:00
John Johansen
788669490a libapparmor python: Fix 'aa_log_record' object has no attribute '__getattr__'
When building with swig 4 we are seeing the error

AttributeError: 'aa_log_record' object has no attribute '__getattr__'

Which forces swig to use modern classes which do not generate __getattr__
methods.

issue: https://gitlab.com/apparmor/apparmor/issues/33
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit a6ac6f4cfc)
2019-06-04 21:51:42 -07:00
John Johansen
b68fe11978 tests/regression: fix mount test to use next available loop device
looping through the first 16 loop devices to find a free device will
fail if those mount devices are taken, and unfortunately there are
now services that use an excessive amount of loop devices causing
the regression test to fail.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/379
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
(cherry picked from commit ab0f2af1da)
2019-05-11 22:27:23 -07:00
Christian Boltz
b638f453e0 Merge branch 'cboltz-fix-deny-hat' into 'apparmor-2.13'
[2.11..2.13] handle_children: Fix denying of adding a hat

See merge request apparmor/apparmor!378

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

(cherry picked from commit d2e83231f0)

87f91864 handle_children: Fix denying of adding a hat
2019-05-02 22:19:24 +00:00
Christian Boltz
fdb9a6e43f Merge branch 'cboltz-link-man' into 'master'
Drop 'to' option for link rules from manpage

See merge request apparmor/apparmor!368

Acked-by: Eric Chiang <ericchiang@google.com>

(cherry picked from commit 041cd95a98)

115a1d89 Drop 'to' option for link rules from manpage
2019-04-29 19:22:25 +00:00
Christian Boltz
914a0a443f Merge branch 'cboltz-gitignore' into 'master'
Add several libapparmor/swig/ruby files to gitignore

See merge request apparmor/apparmor!366

(cherry picked from commit 9c11ce37c6)

7ed1a16a Add several libapparmor/swig/ruby files to gitignore
2019-04-26 16:16:38 +00:00
Christian Boltz
cfa7ec1a79 Merge branch 'bugfix/aa-always-logfile-fallback' into 'master'
Fix error 'KeyError: 'logfiles'' when no logprof.conf exists

See merge request apparmor/apparmor!365

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

(cherry picked from commit cece787182)

455c4413 aa.py: Ensure there is always a fallback falue for the logfile location
3c7e1668 aa.py: Indicate permission error if log file is found but cannot be opened
2019-04-21 16:48:58 +00:00
Goldwyn Rodrigues
43e3365a28 identd: Add network netlink dgram
identd requires access to network netlink dgram.

(cherry picked from commit 1d75abba3f)
PR: https://gitlab.com/apparmor/apparmor/merge_requests/353
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-03-29 01:07:57 -07:00
Simon Deziel
e5888e7031 dovecot: master SIGTERM child that are slow to die
When doing a service reload, I noticed the following:

    ```Mar 22 15:52:27 smtp dovecot: master: Warning: SIGHUP received - reloading configuration
    Mar 22 15:52:27 smtp dovecot: imap(simon): Server shutting down. in=35309 out=232805
    Mar 22 15:52:27 smtp dovecot: imap(simon): Server shutting down. in=24600 out=1688166
    Mar 22 15:52:27 smtp dovecot: imap(simon): Server shutting down. in=14026 out=95516
    Mar 22 15:52:27 smtp dovecot: imap(simon): Server shutting down. in=13776 out=141513
    Mar 22 15:52:33 smtp dovecot: master: Warning: Processes aren't dying after reload, sending SIGTERM.
    Mar 22 15:52:33 smtp dovecot: master: Error: service(imap): kill(5806, 15) failed: Permission denied
    Mar 22 15:52:33 smtp dovecot: master: Error: service(imap-login): kill(5804, 15) failed: Permission denied
    Mar 22 15:52:33 smtp dovecot: master: Error: service(config): kill(506, 15) failed: Permission denied
    Mar 22 15:52:33 smtp kernel: [65542.184326] audit: type=1400 audit(1553284353.609:82): apparmor="DENIED" operation="signal" profile="dovecot" pid=414 comm="dovecot" requested_mask="send" denied_mask="send" signal=term peer="/usr/lib/dovecot/imap"
    Mar 22 15:52:33 smtp kernel: [65542.197596] audit: type=1400 audit(1553284353.625:83): apparmor="DENIED" operation="signal" profile="dovecot" pid=414 comm="dovecot" requested_mask="send" denied_mask="send" signal=term peer="/usr/lib/dovecot/imap-login"
    Mar 22 15:52:33 smtp kernel: [65542.197635] audit: type=1400 audit(1553284353.625:84): apparmor="DENIED" operation="signal" profile="dovecot" pid=414 comm="dovecot" requested_mask="send" denied_mask="send" signal=term peer="/usr/lib/dovecot/config"
    Mar 22 15:52:36 smtp dovecot: imap(simon): Server shutting down. in=17882 out=104004
    ```

The server was heavily loaded which is probably why it ended up trying to SIGTERM those.

Signed-off-by: Simon Deziel <simon@sdeziel.info>
(cherry picked from commit f01fd38ca0)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-03-22 16:06:19 -07:00
Christian Boltz
66148c3fa5 Merge branch 'cboltz-subshell' into 'master'
remove_profiles(): Fix returning $retval

See merge request apparmor/apparmor!352

Acked-by: Eric Chiang <ericchiang@google.com> for 2.11..master

(cherry picked from commit c9148a304c)

be02f008 remove_profiles(): Fix returning $retval
2019-03-18 17:46:34 +00:00
Christian Boltz
162480cfb1 Merge branch 'cboltz-utils-keywords' into 'master'
update network keyword list in utils and add test

See merge request apparmor/apparmor!350

Acked-by: Eric Chiang <ericchiang@google.com> for 2.12..master

(cherry picked from commit dc010bc034)

49849ed7 update network keyword list in utils and add test
2019-03-18 16:03:05 +00:00
Christian Boltz
56772306c3 Merge branch 'cboltz-network-keywords' into 'master'
apparmor.d manpage: update list of network domain keywords

See merge request apparmor/apparmor!349

Acked-by: Eric Chiang <ericchiang@google.com> for 2.12..master

(cherry picked from commit 6416ccebf6)

6b276563 apparmor.d manpage: update list of network domain keywords
2019-03-14 21:20:24 +00:00
Eric Chiang
78a7df6711 parser: determine xmatch priority based on smallest DFA match
The length of a xmatch is used to prioritize multiple profiles that
match the same path, with the intent that the more specific match wins.
Currently, the length of a xmatch is computed by the position of the
first regex character.

While trying to work around issues with no_new_privs by combining
profiles, we noticed that the xmatch length computation doesn't work as
expected for multiple regexs. Consider the following two profiles:

    profile all /** { }
    profile bins /{,usr/,usr/local/}bin/** { }

xmatch_len is currently computed as "1" for both profiles, even though
"bins" is clearly more specific.

When determining the length of a regex, compute the smallest possible
match and use that for xmatch priority instead of the position of the
first regex character.

(cherry picked from commit cc09794fbd)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-03-12 04:29:57 -07:00
Christian Boltz
5d9bb17a3b dnsmasq: Work around breakage caused by {bin,sbin} alternation
Even if we expected it to stay compatible with peer=/usr/sbin/dnsmasq in
the libvirtd profile, practise shows that we were wrong.

This patch adds a tricky workaround so that the profile name doesn't
change, but the profile will attach even on distributions with merged
bin and sbin. (Credits for this crazy idea go to John ;-)

It also re-adds the libvirtd peer name /usr/sbin/libvirtd to avoid
breaking libvirtd.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1127073
and the discussion in https://gitlab.com/apparmor/apparmor/merge_requests/346

(cherry picked from commit 0afd232e5b)
PR: https://gitlab.com/apparmor/apparmor/merge_requests/346
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-03-07 15:40:54 -08:00
John Johansen
7cd903dd20 parser: Fix parser failing to handle errors when setting up work
The parser is not correctly handling some error conditions when
dealing with work units. Failure to spawn work, access files, etc
should be returned where appropriate, and be able to abort processing
if abort_on_error is set.

In addition some errors are leading to a direct exit without checking
for abort_on_error.

BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=921866
BugLink: http://bugs.launchpad.net/bugs/1815294

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Eric Chiang <ericchiang@google.com>
(backported from 2.13 commit 394d086e58)

Conflicts:
	parser/parser_main.c
Reason:
	commit 1328a42d5 not backported
2019-02-22 02:42:43 -08:00
Christian Boltz
1ce8cd213c Merge branch 'dovecot-fixes-no-doveadm' into 'master'
misc dovecot fixes (take #2)

See merge request apparmor/apparmor!336

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

(cherry picked from commit e68beb988a)

a57f01d8 dovecot: allow FD passing between dovecot and dovecot's anvil
d0aa863f dovecot: allow chroot'ing the auth processes
9afeb225 dovecot: let dovecot/anvil rw the auth-penalty socket
17db8f38 dovecot: auth processes need to read from postfix auth socket
6a7c49b1 dovecot: add abstractions/ssl_certs to lmtp
2019-02-17 21:04:49 +00:00
Steve Beattie
df05b82f7d usr merge fixups
Debian and Ubuntu have releases coming out with usr-merge in place. For
these systems, /bin and /sbin are symlinks to their respective /usr
directories. This breaks a few tests in the python utils and in the
regression tests. This patch series fixes them, mostly by performing
realpath() calls when necessary. For the ptrace regression test,
it copies the called /bin/true binary into the created temporary
directory and executes it from there. (Good for other reasons, too.)

(cherry picked from commit b4ab8476e4)
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
MR: https://gitlab.com/apparmor/apparmor/merge_requests/331
2019-02-13 09:41:34 -08:00
Christian Boltz
56934923cc Merge branch 'update-vulkan' into 'master'
vulkan: allow reading /etc/vulkan/icd.d/

See merge request apparmor/apparmor!329

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

(cherry picked from commit f2c0a11327)

e322c02c vulkan: allow reading /etc/vulkan/icd.d/
2019-02-10 13:41:18 +00:00
Christian Boltz
30a1e69379 Merge branch 'backport-kde-213' into 'apparmor-2.13'
Backport kde abstraction to 2.13

See merge request apparmor/apparmor!327

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

(cherry picked from commit 6779402786)

aae838fa Update kde abstraction for common settings
dc3b73da kde: fix global settings access for Kubuntu and openSUSE
2019-02-09 17:28:08 +00:00
intrigeri
319856b6a5 audio abstraction: grant read access to the libao configuration files.
Bug-Debian: https://bugs.debian.org/920670

Relevant documentation: https://xiph.org/ao/doc/config.html

(cherry picked from commit 16c4713363)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-01-31 17:17:01 -08:00
intrigeri
55a2d35c85 audio abstraction: grant read access to the system-wide asound.conf.
Bug-Debian: https://bugs.debian.org/920669

Relevant documentation: http://www.alsa-project.org/main/index.php/Asoundrc

We already grant read access to the corresponding per-user configuration file
(~/.asoundrc) so it makes sense to also grant access to the system-wide one.

(cherry picked from commit 2d72795f65)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-01-31 17:16:45 -08:00
Marius Tomaschewski
b75ba6902d abstractions/nameservice: allow /run/netconfig/resolv.conf
Latest netconfig in openSUSE writes /run/netconfig/resolv.conf, and only
has a symlink to it in /etc

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1097370
Acked-by: Christian Boltz <apparmor@cboltz.de>
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit b0bacba9db)
2019-01-24 02:45:42 -08:00
John Johansen
e41b9b2d54 [2.12] drop failing corner-case check in logparser.py
aa-logprof errors out if it hits a log event for a non-existing profile while a profile file with the default filename for that non-existing profile exists. This can for example happen after adding a profile name to a profile if audit.log still contains events for the attachment-based profile name.

Since we ignore log events for non-existing profiles in general, drop the code for the special case "but a file matching the default filename for that non-existing profile exists" and also silently ignore events for this very special non-existing profile.

Also drop the now unused function get_profile_filename()

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


PR: https://gitlab.com/apparmor/apparmor/merge_requests/297

Acked-by: Eric Chiang <ericchiang@google.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-01-24 10:23:53 +00:00
Christian Boltz
811625233f update mysqld profile
This updates the mysqld to what I use on my servers nowadays.

Note: my profile also has capability sys_resource,, but I'm not sure
why I had to add this and therefore didn't include it in this merge
request.

Speaking about "why I had added $whatever" - these changes were
collected over the last years and of course ;-) I don't remember any
details.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/310
(cherry picked from commit 0199edf8e7)
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-01-23 20:29:47 -08:00
Jamie Strandboge
bc4a1afac1 Merge branch 'update-fonts' into 'master'
Update fonts for Debian and openSUSE

- Allow to read conf-avail dir itself.
- Add various openSUSE-specific font config directories.

See merge request !96 (merged) for details.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/309
(cherry picked from commit 7bd3029f25)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2019-01-23 20:10:10 -08:00
Christian Boltz
512c81b3e1 Merge branch 'cboltz-dnsmasq-libvirtd' into 'master'
dnsmasq: allow peer=libvirtd to support named profile

See merge request apparmor/apparmor!304

Acked-by: Eric Chiang <ericchiang@google.com> for 2.12..master

(cherry picked from commit 5d384d9625)

20fe099c dnsmasq: allow peer=libvirtd to support named profile
2019-01-22 22:24:25 +00:00
Christian Boltz
ac7a848a1f Merge branch 'fix-compose-cache' into 'master'
qt5-compose-cache-write: fix anonymous shared memory access

See merge request apparmor/apparmor!301

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

(cherry picked from commit 027dcdb23f)

12504024 qt5-compose-cache-write: fix anonymous shared memory access
2019-01-14 20:51:33 +00:00
Christian Boltz
99df4f4c76 Merge branch 'fix-qt5-settings' into 'master'
qt5-settings-write: fix anonymous shared memory access

See merge request apparmor/apparmor!302

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

(cherry picked from commit 3e3c90152f)

f1200873 qt5-settings-write: fix anonymous shared memory access
8f6a8fb1 Refactor qt5-settings-write
2019-01-14 20:48:43 +00:00
Christian Boltz
0130fcaa24 Merge branch 'fix-alsa' into 'master'
audio: Fix alsa settings access

See merge request apparmor/apparmor!303

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

(cherry picked from commit 808218d8ee)

73f01196 audio: Fix alsa settings access
2019-01-13 16:12:05 +00:00
Christian Boltz
bc586f7897 Merge branch 'var-lib-dehydrated' into 'master'
abstractions/ssl_{certs,keys}: dehydrated uses /var/lib on Debian

See merge request apparmor/apparmor!299

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

(cherry picked from commit 1f53de174d)

1306f9a6 abstractions/ssl_{certs,keys}: dehydrated uses /var/lib on Debian
c5a89d5d abstractions/ssl_{certs,keys}: sort the alternation for dehydrated and drop...
04b2842e abstractions/ssl_{certs,keys}: allow reading ocsp.der maintained by dehydrated for OCSP stapling
2019-01-03 17:33:14 +00:00
Christian Boltz
49bb2d753e Drop get_profile_filename() from logparser.py
This function is unused since the last commit.

(cherry picked from commit ed692337a5)
2019-01-02 20:50:49 +01:00
Christian Boltz
182c3e47fb drop failing corner-case check in logparser.py
aa-logprof errors out if it hits a log event for a non-existing profile
while a profile file with the default filename for that non-existing
profile exists. This can for example happen after adding a profile name
to a profile if audit.log still contains events for the attachment-based
profile name.

Since we ignore log events for non-existing profiles in general, drop
the code for the special case "but a file matching the default filename
for that non-existing profile exists" and also silently ignore events
for this very special non-existing profile.

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

(cherry picked from commit 03ea5b82b7)
2019-01-02 20:50:17 +01:00
John Johansen
50aa7293dd Release: Bump revisions in preparation for 2.12.2 release
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-21 03:52:51 -08:00
Christian Boltz
79940b8e18 revert naming the dnsmasq profile
Changing to "profile dnsmasq /..." broke the peer=/usr/sbin/dnsmasq in
the libvirtd profile. Revert adding the name to avoid breaking the
libvirtd profile in stable branches.

See also https://bugzilla.opensuse.org/show_bug.cgi?id=1118952
which is a request to update the libvirtd profile to allow both
peer=dnsmasq and peer=/usr/sbin/dnsmasq

BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1118952
PR: https://gitlab.com/apparmor/apparmor/merge_requests/290
(cherry picked from commit a68e6426f4)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-15 21:21:02 -08:00
Christian Boltz
e6d2ada55c dovecot: allow reading /proc/sys/fs/suid_dumpable
This is needed if a dovecot child process segfaults - in this case,
dovecot provides a helpful error message like

dovecot[6179]: auth-worker: Fatal: master: service(auth-worker): child 8103 killed with signal 11 (core not dumped - https://dovecot.org/bugreport.html#coredumps - set /proc/sys/fs/suid_dumpable to 2)

which involves reading the current value in suid_dumpable.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/286
(cherry picked from commit 2202a8a267)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-08 00:33:45 -08:00
Christian Boltz
60d75132fc Ignore *.orig and *.rej files when loading profiles
or: get rc.apparmor.functions in sync with the tools and libapparmor.

This was "accidently" reported by Ralph on the opensuse-support
mailinglist.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/282
(cherry picked from commit 228b92ce5a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-08 00:18:29 -08:00
Jamie Strandboge
ccda637998 deny ~/.mutt** in private-files and audit deny ~/.aws in private-files-strict
PR: https://gitlab.com/apparmor/apparmor/merge_requests/276
Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
(cherry picked from commit 170e8d6ac8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 23:00:49 -08:00
Christian Boltz
44ca6942f0 Fix viewing a local inactive profile in aa-genprof
aa-genprof checks if one of the profiles in the extra profile dir
matches the binary, and proposes to use that profile as a starting
point.

Since 4d722f1839 the "(V)iew profile"
option to display the proposed profile was broken.

The easiest fix is to remember the filename in the extras directory, and
display the file from there.

Sidenote: when choosing to use the extra profile, it gets written to
disk without any problems, so this bug really only affected "(V)iew
profile" to preview the proposed extra profile.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit 8b4e76a7d5)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:49:26 -08:00
Christian Boltz
5e45af1752 serialize_profile(): Fix handling of options
In the 2.13 branch (and older), 'options' is not always a dict, but can
also be None or an empty string.

Adjust the if condition in serialize_profile() so that "View changes
between clean profiles" doesn't error out.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:47:44 -08:00
Christian Boltz
f997977e6b Replace existing_profiles & fix minitools for named profiles
Technical stuff first:

Replace existing_profiles (a dict with the filenames for both active and
inactive profiles) with active_profiles and extra_profiles which are
ProfileList()s and store the active profiles and those in the extra
directory separately. Thanks to ProfileList, now also the relation
between attachments and filenames is easily available.

Also replace all usage of existing_profiles with active_profiles and
extra_profiles, and adjust it to the ProfileList syntax everywhere.

With this change, several bugs in aa-complain and the other minitools
get fixed:
- aa-complain etc. never found profiles that have a profile name
  (the attachment wasn't checked)
- even if the profile name was given as parameter to aa-complain, it
  first did "which $parameter" so it never matched on named profiles
- profile names with alternations (without attachment specification)
  also never matched because the old code didn't use AARE.

References: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882047#92
(search for "As usual" ;-)

Just for completeness - the matching still doesn't honor/expand
variables in the profile name.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit 4d722f1839)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:47:11 -08:00
Christian Boltz
848fbae814 add ProfileList class to store list of profiles
ProfileList is meant to store the list of profiles (both name and
attachment) and in which files they live.

Also add unittests to make sure everything works as expected.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit 789c4658e2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:46:28 -08:00
Christian Boltz
368097d8e7 Move updating existing_profiles out of parse_profile_data()
parse_profile_data() returns the parsed profiles, but writes to
existing_profiles directly.

read_profiles() calls parse_profile_data() and already handles adding
the parsed profiles to aa, original_aa or extras, which means updating
existing_profiles there is a much better place.

This commit also includes a hidden change: Previously, when parsing
include files, they were also added to existing_profiles. This is
superfluous, only real profiles need to be stored there.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit 8809218ac8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:45:45 -08:00
Christian Boltz
9da95e607e split off get_new_profile_filename()
... and call it from get_profile_filename_* if get_new is True
(= always with the current code)

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit a6b8d14908)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:45:11 -08:00
Christian Boltz
43c4c10501 split get_profile_filename into .._from_profile_name and .._from_attachment
Split get_profile_filename() into
- get_profile_filename_from_profile_name() (parameter: a profile name)
- get_profile_filename_from_attachment() (parameter: an attachment)

Currently both functions call get_profile_filename_orig() (formerly
get_profile_filename()) so the behaviour doesn't change yet.

The most important part of this commit is changing all
get_profile_filename() calls to use one of the new functions to make
clear if they specify a profile or an attachment/executable as
parameter.

As promised, the is_attachment parameter starts to get used in this
patch ;-)

Note: The get_new parameter (which I'll explain in the patch actually
using it) is set to True in all calls to the new functions.
The long term plan is to get rid of it in most cases (hence defaulting
to False), but that will need more testing.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit ec741424f8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:44:31 -08:00
Christian Boltz
c0766035df Add is_attachment parameter to write_profile
The minitools call write_profile(), write_profile_feedback_ui() and
serialize_profile() with the _attachment_ as parameter.

However, aa-logprof etc. call them with the _profile name_ as parameter.

This patch adds an is_attachment parameter to write_profile() and
write_profile_feedback_ui(). It also passes it through to
serialize_profile() via the options parameter.

If is_attachment is True, the parameter will be handled as attachment,
otherwise it is expected to be a profile name.

tools.py gets changed to set is_attachment to True when calling the
functions listed above to make clear that the parameter is an attachment.

Note: This patch only adds the is_attachment parameter/option, but
doesn't change any behaviour. That will happen in the next patch.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/268
(cherry picked from commit bc783372b8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:42:43 -08:00
Petr Vorel
679e670024 dnsmasq: Add pid file used by NetworkManager
PR: https://gitlab.com/apparmor/apparmor/merge_requests/288
Signed-off-by: Petr Vorel <pvorel@suse.cz>
(cherry picked from commit 49848b9081)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:28:27 -08:00
Petr Vorel
0fcb7d032e dnsmasq: Adjust pattern for log files to comply SELinux
i.e. move '*' from beginning to before suffix.

Commit 025c7dc6 ("dnsmasq: Add permission to open log files") added
pattern, which is not compatible with SELinux. As this pattern has been
in SELinux since 2011 (with recent change to accept '.log' suffix +
logrotate patterns which are not relevant to AppArmor) IMHO it's better
to adjust our profile.

Fixes: 025c7dc6 ("dnsmasq: Add permission to open log files")
PR: PR: https://gitlab.com/apparmor/apparmor/merge_requests/288
Signed-off-by: Petr Vorel <pvorel@suse.cz>
(cherry picked from commit 3ef8df6ac0)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-12-07 22:28:12 -08:00
Vincas Dargis
288c67d639 Merge branch 'backport-sys-212' into 'apparmor-2.12'
Backport for 2.12: Use @{sys} tunable in profiles and abstractions

See merge request apparmor/apparmor!278

Acked-by: Christian Boltz <apparmor@cboltz.de>
2018-12-06 18:42:48 +00:00
Christian Boltz
d24b373138 Merge branch 'certbot' into 'master'
Add /etc/letsencrypt/archive to ssl_key abstraction

See merge request apparmor/apparmor!283

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

(cherry picked from commit 0a666b8e48)

cb468786 Add /etc/letsencrypt stuff to ssl_keys/ssl_certs abstraction
2018-11-30 15:44:33 +00:00
Vincas Dargis
699ec8434d Backport: Use @{sys} tunable in profiles and abstractions
Commit aa06528790 made @{sys} tunable
available by default.

Update profiles and abstractions to actually use @{sys} tunable for
better confinement in the future (when @{sys} becomes kernel var).

Closes LP#1728551

(this is backport of 2438179b76 for
AppArmor 2.12)
2018-11-22 20:16:32 +02:00
Vincas Dargis
10d3abf930 Merge branch 'backport-vulkan' into 'apparmor-2.13'
Backport: Add vulkan abstraction

See merge request apparmor/apparmor!266

Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.10..2.13

(cherry picked from commit 6249579842)

31461701 Add vulkan abstraction
2018-11-22 17:36:25 +00:00
Christian Boltz
82d3b322da parse_profile_data(): Ensure last line in a profile is valid
'lastline' gets merged into 'line' (and reset to None) when reading the
next line. If 'lastline' isn't empty after reading the whole profile,
this means there's something unparseable at the end of the profile,
therefore parse_profile_data() should error out.

Also remove some simple_tests testcases from the 'exception_not_raised'
list - they only didn't raise the exception because the invalid rule was
the last line in the affected profile.

Thanks to Eric Chiang for accidently (and maybe even unnoticedly ;-)
discovering this bug while adding some xattr testcases that surprisingly
didn't fail in the tools.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/271
(cherry picked from commit 4efff35bf8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-11-13 16:03:22 -08:00
Christian Boltz
bceac420a6 Merge branch 'cboltz-view-changes-2.13' into 'apparmor-2.13'
[2.12+2.13] use serialize_profile() for the new profile in (V)iew Changes

See merge request apparmor/apparmor!267

Acked-by: John Johansen <john.johansen@canonical.com> for 2.12 and 2.13

(cherry picked from commit f4d7f8ae57)

dd4c2b05 use serialize_profile() for the new profile in (V)iew Changes
1b32d764 delete serialize_profile_from_old_profile()
2018-11-11 17:28:28 +00:00
Christian Boltz
f4b955ce75 Merge branch 'cboltz-strict-todo-check' into 'master'
error out on superfluous TODOs

See merge request apparmor/apparmor!197

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

(cherry picked from commit 39a2031487)

4b26850e error out on superfluous TODOs
2018-11-06 21:15:03 +00:00
Christian Boltz
66ef169a8b Merge branch 'cboltz-disable-some-abi-tests' into 'master'
disable abi/ok_10 and abi/ok_12 tests

See merge request apparmor/apparmor!259

(cherry picked from commit 608af94dff)

a3305b51 disable abi/ok_10 and abi/ok_12 tests
2018-11-06 20:43:26 +00:00
Christian Boltz
5f0dc143fc Merge branch 'cboltz-fixed-todos' into 'master'
Remove TODO notes from no-longer-failing tests

See merge request apparmor/apparmor!180

Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: intrigeri <intrigeri@debian.org>

(cherry picked from commit c98d8570ee)

d15bdaba Remove TODO notes from no-longer-failing tests
2018-11-06 17:50:24 +00:00
intrigeri
9064c1e185 apparmor(7): Document various debugging options.
Credits go to John Johansen <john@jjmx.net> for most of the information
and the initial phrasing.

Bug-Debian: https://bugs.debian.org/826218

Cherry-picked from commit b95f9bdd3b
2018-11-04 12:04:27 +00:00
Christian Boltz
300760a13e Merge branch 'cboltz-postalias' into 'master'
allow locking /etc/aliases.db

See merge request apparmor/apparmor!250

Acked-by: intrigeri <intrigeri@debian.org>

(cherry picked from commit 473d1f5daa)

f74edd5d allow locking /etc/aliases.db
2018-10-26 14:39:52 +00:00
John Johansen
c23cd2e389 Merge branch 'cboltz-aa-notify.pod' into 'apparmor-2.12'
aa-notify man page: update user's configuration file path

[2.10..2.12] aa-notify man page: update user's configuration file path

PR: https://gitlab.com/apparmor/apparmor/merge_requests/243
(backported from commit 2209e09aef)
Acked-by: John Johansen <john.johansen@canonical.com>
2018-10-22 02:38:17 +00:00
Christian Boltz
7176c1433b add libapparmor/src/PMurHash.{o,lo} to gitignore
(cherry picked from commit db92d96e68)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-10-21 19:05:38 -07:00
Christian Boltz
d88b047b3c add utils/test/common_test.pyc to gitignore
(cache file that gets created when running the tests with python2)

(cherry picked from commit 63d17ecf16)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-10-21 19:05:19 -07:00
Christian Boltz
6e8d5712c7 Merge branch 'cboltz-profile-names' into 'master'
Add profile names to all profiles with {bin,sbin} attachment

See merge request apparmor/apparmor!242

Acked-by: intrigeri <intrigeri@debian.org>

(cherry picked from commit fd68a5eb64)

b77116e6 Add profile names to all profiles with {bin,sbin} attachment
2018-10-21 10:35:31 +00:00
Christian Boltz
500b857d24 Merge branch 'test-includes' into 'apparmor-2.12'
profiles/Makefile: test abstractions against apparmor_parser

See merge request apparmor/apparmor!244

Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.10, 2.11 and 2.12.
2018-10-18 17:14:54 +00:00
Vincas Dargis
93ccf15ce6 profiles/Makefile: test abstractions against apparmor_parser
Update Makefile to test abstractions by generating temporary profile, to
check for missing (not backported) abstractions or other issues.

This is backport of dc7ae28de0 for
2.10..2.12 series (without --config-file option).
2018-10-18 20:00:03 +03:00
Christian Boltz
e908b415d7 aa-notify man page: update user's configuration file path
This is a backport of !239

    commit 2209e09aef
    Author: nl6720 <nl6720@gmail.com>

    aa-notify man page: update user's configuration file path

    Signed-off-by: nl6720 <nl6720@gmail.com>
2018-10-16 18:01:02 +02:00
86 changed files with 1070 additions and 953 deletions

9
.gitignore vendored
View File

@@ -95,6 +95,8 @@ libraries/libapparmor/src/.deps
libraries/libapparmor/src/.libs
libraries/libapparmor/src/Makefile
libraries/libapparmor/src/Makefile.in
libraries/libapparmor/src/PMurHash.lo
libraries/libapparmor/src/PMurHash.o
libraries/libapparmor/src/af_protos.h
libraries/libapparmor/src/change_hat.lo
libraries/libapparmor/src/features.lo
@@ -161,8 +163,14 @@ libraries/libapparmor/swig/python/test/test-suite.log
libraries/libapparmor/swig/python/test/test_python.py
libraries/libapparmor/swig/python/test/test_python.py.log
libraries/libapparmor/swig/python/test/test_python.py.trs
libraries/libapparmor/swig/ruby/LibAppArmor.so
libraries/libapparmor/swig/ruby/LibAppArmor_wrap.c
libraries/libapparmor/swig/ruby/LibAppArmor_wrap.o
libraries/libapparmor/swig/ruby/Makefile
libraries/libapparmor/swig/ruby/Makefile.in
libraries/libapparmor/swig/ruby/Makefile.new
libraries/libapparmor/swig/ruby/Makefile.ruby
libraries/libapparmor/swig/ruby/mkmf.log
libraries/libapparmor/testsuite/.deps
libraries/libapparmor/testsuite/.libs
libraries/libapparmor/testsuite/Makefile
@@ -188,6 +196,7 @@ utils/*.tmp
utils/po/*.mo
utils/apparmor/*.pyc
utils/apparmor/rule/*.pyc
utils/test/common_test.pyc
utils/test/.coverage
utils/test/htmlcov/
utils/vim/apparmor.vim

View File

@@ -1 +1 @@
2.12.1
2.12.3

View File

@@ -109,7 +109,7 @@ class AAPythonBindingsTests(unittest.TestCase):
new_record = dict()
for key in [x for x in dir(record) if not (x.startswith('_') or x == 'this')]:
value = record.__getattr__(key)
value = getattr(record, key)
if key == "event" and value in EVENT_MAP:
new_record[key] = EVENT_MAP[value]
elif key == "version":

View File

@@ -111,7 +111,7 @@ capabilities(7))
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
B<DOMAIN> = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' | 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'mpls' | 'ib' | 'kcm' | 'smc' ) ','
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' ) ','
B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
@@ -271,7 +271,7 @@ B<EXEC TRANSITION> = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' |
B<EXEC TARGET> = name
Requires I<EXEC TRANSITION> specified.
B<LINK RULE> = I<QUALIFIERS> [ 'owner' ] 'link' [ 'subset' ] I<FILEGLOB> ( 'to' | '-E<gt>' ) I<FILEGLOB>
B<LINK RULE> = I<QUALIFIERS> [ 'owner' ] 'link' [ 'subset' ] I<FILEGLOB> '-E<gt>' I<FILEGLOB>
B<ALPHA> = ('a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')

View File

@@ -143,6 +143,56 @@ messages with the KERN facility. Thus, REJECTING and PERMITTING messages
may go to either F</var/log/audit/audit.log> or F</var/log/messages>,
depending upon local configuration.
=head1 DEBUGGING
AppArmor provides a few facilities to log more information,
which can help debugging profiles.
=head2 Enable debug mode
When debug mode is enabled, AppArmor will log a few extra messages to
dmesg (not via the audit subsystem). For example, the logs will tell
whether environment scrubbing has been applied.
To enable debug mode, run:
echo 1 > /sys/module/apparmor/parameters/debug
=head2 Turn off deny audit quieting
By default, operations that trigger C<deny> rules are not logged.
This is called I<deny audit quieting>.
To turn off deny audit quieting, run:
echo -n noquiet >/sys/module/apparmor/parameters/audit
=head2 Force audit mode
AppArmor can log a message for every operation that triggers a rule
configured in the policy. This is called I<force audit mode>.
B<Warning!> Force audit mode can be extremely noisy even for a single profile,
let alone when enabled globally.
To set a specific profile in force audit mode, add the C<audit> flag:
profile foo flags=(audit) { ... }
To enable force audit mode globally, run:
echo -n all > /sys/module/apparmor/parameters/audit
If auditd is not running, to avoid losing too many of the extra log
messages, you will likely have to turn off rate limiting by doing:
echo 0 > /proc/sys/kernel/printk_ratelimit
But even then the kernel ring buffer may overflow and you might
lose messages.
Else, if auditd is running, see auditd(8) and auditd.conf(5).
=head1 FILES
=over 4

View File

@@ -126,9 +126,10 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
/* create a dfa from the ruleset
* returns: buffer contain dfa tables, @size set to the size of the tables
* else NULL on failure
* else NULL on failure, @min_match_len set to the shortest string
* that can match the dfa for determining xmatch priority.
*/
void *aare_rules::create_dfa(size_t *size, dfaflags_t flags)
void *aare_rules::create_dfa(size_t *size, int *min_match_len, dfaflags_t flags)
{
char *buffer = NULL;
@@ -150,6 +151,7 @@ void *aare_rules::create_dfa(size_t *size, dfaflags_t flags)
root = new AltNode(root, new CatNode(tmp, i->first));
}
}
*min_match_len = root->min_match_len();
/* dumping of the none simplified tree without -O no-expr-simplify
* is broken because we need to build the tree above first, and

View File

@@ -104,7 +104,7 @@ class aare_rules {
uint32_t audit, dfaflags_t flags);
bool add_rule_vec(int deny, uint32_t perms, uint32_t audit, int count,
const char **rulev, dfaflags_t flags);
void *create_dfa(size_t *size, dfaflags_t flags);
void *create_dfa(size_t *size, int *min_match_len, dfaflags_t flags);
};
#endif /* __LIBAA_RE_RULES_H */

View File

@@ -123,6 +123,19 @@ public:
virtual void compute_firstpos() = 0;
virtual void compute_lastpos() = 0;
virtual void compute_followpos() { }
/*
* min_match_len determines the smallest string that can match the
* syntax tree. This is used to determine the priority of a regex.
*/
virtual int min_match_len() { return 0; }
/*
* contains_null returns if the expression tree contains a null character.
* Null characters indicate that the rest of the DFA matches the xattrs and
* not the path. This is used to compute min_match_len.
*/
virtual bool contains_null() { return false; }
virtual int eq(Node *other) = 0;
virtual ostream &dump(ostream &os) = 0;
void dump_syntax_tree(ostream &os);
@@ -257,6 +270,17 @@ public:
return os << c;
}
int min_match_len()
{
if (c == 0) {
// Null character indicates end of string.
return 0;
}
return 1;
}
bool contains_null() { return c == 0; }
uchar c;
};
@@ -298,6 +322,24 @@ public:
return os << ']';
}
int min_match_len()
{
if (contains_null()) {
return 0;
}
return 1;
}
bool contains_null()
{
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
if (*i == 0) {
return true;
}
}
return false;
}
Chars chars;
};
@@ -346,6 +388,24 @@ public:
return os << ']';
}
int min_match_len()
{
if (contains_null()) {
return 0;
}
return 1;
}
bool contains_null()
{
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
if (*i == 0) {
return false;
}
}
return true;
}
Chars chars;
};
@@ -369,6 +429,8 @@ public:
return 0;
}
ostream &dump(ostream &os) { return os << "."; }
bool contains_null() { return true; }
};
/* Match a node zero or more times. (This is a unary operator.) */
@@ -396,6 +458,8 @@ public:
child[0]->dump(os);
return os << ")*";
}
bool contains_null() { return child[0]->contains_null(); }
};
/* Match a node one or more times. (This is a unary operator.) */
@@ -423,6 +487,8 @@ public:
child[0]->dump(os);
return os << ")+";
}
int min_match_len() { return child[0]->min_match_len(); }
bool contains_null() { return child[0]->contains_null(); }
};
/* Match a pair of consecutive nodes. */
@@ -470,6 +536,22 @@ public:
return os;
}
void normalize(int dir);
int min_match_len()
{
int len = child[0]->min_match_len();
if (child[0]->contains_null()) {
// Null characters are used to indicate when the DFA transitions
// from matching the path to matching the xattrs. If the left child
// contains a null character, the right side doesn't contribute to
// the path match.
return len;
}
return len + child[1]->min_match_len();
}
bool contains_null()
{
return child[0]->contains_null() || child[1]->contains_null();
}
};
/* Match one of two alternative nodes. */
@@ -507,6 +589,20 @@ public:
return os;
}
void normalize(int dir);
int min_match_len()
{
int m1, m2;
m1 = child[0]->min_match_len();
m2 = child[1]->min_match_len();
if (m1 < m2) {
return m1;
}
return m2;
}
bool contains_null()
{
return child[0]->contains_null() || child[1]->contains_null();
}
};
class SharedNode: public ImportantNode {

View File

@@ -171,13 +171,23 @@ extern int preprocess_only;
#ifdef DEBUG
#define PDEBUG(fmt, args...) fprintf(stderr, "parser: " fmt, ## args)
#define PDEBUG(fmt, args...) \
do { \
int pdebug_error = errno; \
fprintf(stderr, "parser: " fmt, ## args); \
errno = pdebug_error; \
} while (0)
#else
#define PDEBUG(fmt, args...) /* Do nothing */
#endif
#define NPDEBUG(fmt, args...) /* Do nothing */
#define PERROR(fmt, args...) fprintf(stderr, fmt, ## args)
#define PERROR(fmt, args...) \
do { \
int perror_error = errno; \
fprintf(stderr, fmt, ## args); \
errno = perror_error; \
} while (0)
#ifndef TRUE
#define TRUE (1)

View File

@@ -605,7 +605,7 @@ include/{WS} {
{CARET} { PUSH_AND_RETURN(SUB_ID, TOK_CARET); }
{ARROW} { RETURN_TOKEN(TOK_ARROW); }
{ARROW} { PUSH_AND_RETURN(SUB_ID_WS, TOK_ARROW); }
{EQUALS} { PUSH_AND_RETURN(ASSIGN_MODE, TOK_EQUALS); }

View File

@@ -439,8 +439,6 @@ static int process_arg(int c, char *optarg)
}
break;
case 'O':
skip_read_cache = 1;
if (!handle_flag_table(optflag_table, optarg,
&dfaflags)) {
PERROR("%s: Invalid --Optimize option %s\n",
@@ -899,8 +897,11 @@ do { \
work_sync_one(RESULT); \
} while (0)
/* returns -1 if work_spawn fails, not a return value of any unit of work */
#define work_spawn(WORK, RESULT) \
do { \
({ \
int localrc = 0; \
do { \
/* what to do to avoid fork() overhead when single threaded \
if (jobs == 1) { \
// no parallel work so avoid fork() overhead \
@@ -937,11 +938,17 @@ do { \
fprintf(stderr, " JOBS SPAWN: created %ld ...\n", njobs); \
} else { \
/* error */ \
if (debug_jobs) \
fprintf(stderr, " JOBS SPAWN: failed error: %d) ...\n", errno); \
if (debug_jobs) { \
int error = errno; \
fprintf(stderr, " JOBS SPAWN: failed error: %d) ...\n", errno); \
errno = error; \
} \
RESULT(errno); \
localrc = -1; \
} \
} while (0)
} while (0); \
localrc; \
})
/* sadly C forces us to do this with exit, long_jump or returning error
@@ -1018,11 +1025,15 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
autofree char *path = NULL;
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0) {
PERROR(_("Out of memory"));
work_spawn(process_profile(option, cb_data->kernel_interface,
path, cb_data->cachedir),
handle_work_result);
handle_work_result(errno);
return -1;
}
rc = work_spawn(process_profile(option,
cb_data->kernel_interface,
path, cb_data->cachedir),
handle_work_result);
}
return rc;
}
@@ -1036,11 +1047,15 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
autofree char *path = NULL;
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0) {
PERROR(_("Out of memory"));
work_spawn(process_binary(option, cb_data->kernel_interface,
path),
handle_work_result);
handle_work_result(errno);
return -1;
}
rc = work_spawn(process_binary(option,
cb_data->kernel_interface,
path),
handle_work_result);
}
return rc;
}
@@ -1157,11 +1172,14 @@ int main(int argc, char *argv[])
}
/* skip stdin if we've seen other command line arguments */
if (i == argc && optind != argc)
continue;
goto cleanup;
if (profilename && stat(profilename, &stat_file) == -1) {
last_error = errno;
PERROR("File %s not found, skipping...\n", profilename);
continue;
if (abort_on_error)
break;
goto cleanup;
}
if (profilename && S_ISDIR(stat_file.st_mode)) {
@@ -1176,20 +1194,27 @@ int main(int argc, char *argv[])
cb = binary_input ? binary_dir_cb : profile_dir_cb;
if ((retval = dirat_for_each(AT_FDCWD, profilename,
&cb_data, cb))) {
last_error = errno;
PDEBUG("Failed loading profiles from %s\n",
profilename);
if (abort_on_error)
break;
}
} else if (binary_input) {
/* ignore return as error is handled in work_spawn */
work_spawn(process_binary(option, kernel_interface,
profilename),
handle_work_result);
} else {
/* ignore return as error is handled in work_spawn */
work_spawn(process_profile(option, kernel_interface,
profilename, cacheloc),
handle_work_result);
}
if (profilename) free(profilename);
cleanup:
if (profilename)
free(profilename);
profilename = NULL;
}
work_sync(handle_work_result);

View File

@@ -473,17 +473,13 @@ static int process_profile_name_xmatch(Profile *prof)
ptype = convert_aaregex_to_pcre(alt->name, 0,
glob_default,
tbuf, &len);
if (ptype == ePatternBasic)
len = strlen(alt->name);
if (len < prof->xmatch_len)
prof->xmatch_len = len;
if (!rules->add_rule(tbuf.c_str(), 0, AA_MAY_EXEC, 0, dfaflags)) {
delete rules;
return FALSE;
}
}
}
prof->xmatch = rules->create_dfa(&prof->xmatch_size, dfaflags);
prof->xmatch = rules->create_dfa(&prof->xmatch_size, &prof->xmatch_len, dfaflags);
delete rules;
if (!prof->xmatch)
return FALSE;
@@ -679,8 +675,9 @@ int process_profile_regex(Profile *prof)
goto out;
if (prof->dfa.rules->rule_count > 0) {
int xmatch_len = 0;
prof->dfa.dfa = prof->dfa.rules->create_dfa(&prof->dfa.size,
dfaflags);
&xmatch_len, dfaflags);
delete prof->dfa.rules;
prof->dfa.rules = NULL;
if (!prof->dfa.dfa)
@@ -815,7 +812,9 @@ int process_profile_policydb(Profile *prof)
goto out;
if (prof->policy.rules->rule_count > 0) {
prof->policy.dfa = prof->policy.rules->create_dfa(&prof->policy.size, dfaflags);
int xmatch_len = 0;
prof->policy.dfa = prof->policy.rules->create_dfa(&prof->policy.size,
&xmatch_len, dfaflags);
delete prof->policy.rules;
prof->policy.rules = NULL;

View File

@@ -113,6 +113,8 @@ skip_profile() {
local profile=$1
if [ "${profile%.rpmnew}" != "${profile}" -o \
"${profile%.rpmsave}" != "${profile}" -o \
"${profile%.orig}" != "${profile}" -o \
"${profile%.rej}" != "${profile}" -o \
-e "${PROFILE_DIR}/disable/`basename ${profile}`" -o \
"${profile%\~}" != "${profile}" ] ; then
return 1
@@ -401,14 +403,16 @@ remove_profiles() {
# We filter child profiles as removing the parent will remove
# the children
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
LC_COLLATE=C sort | grep -v // | while read profile ; do
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
rc=$?
if [ ${rc} -ne 0 ] ; then
retval=${rc}
fi
done
return ${retval}
LC_COLLATE=C sort | grep -v // | {
while read profile ; do
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
rc=$?
if [ ${rc} -ne 0 ] ; then
retval=${rc}
fi
done
return ${retval}
}
}
apparmor_stop() {

View File

@@ -131,9 +131,13 @@ sub test_profile {
} elsif ($coredump) {
ok(0, "$profile: Produced core dump (signal $signal): $description");
} elsif ($istodo) {
TODO: {
local $TODO = "Unfixed testcase.";
ok($expass ? !$result : $result, "TODO: $profile: $description");
if ($expass != $result) {
fail("TODO passed unexpectedly: $profile: $description");
} else {
TODO: {
local $TODO = "Unfixed testcase.";
ok($expass ? !$result : $result, "TODO: $profile: $description");
}
}
} else {
ok($expass ? !$result : $result, "$profile: $description");

View File

@@ -2,6 +2,7 @@
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
#=EXRESULT PASS
#=TODO
#=DISABLED - results in "superfluous TODO", but fails after removing TODO
abi < "abi/4.19">,

View File

@@ -2,6 +2,7 @@
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
#=EXRESULT PASS
#=TODO
#=DISABLED - results in "superfluous TODO", but fails after removing TODO
abi < "abi/4.19" >,

View File

@@ -1,6 +1,5 @@
#=DESCRIPTION reference variables in rules that also have alternations
#=EXRESULT PASS
#=TODO
# This test needs check on @{FOO} attachment having leading / post var expansion
@{FOO}=/bar /baz

View File

@@ -1,6 +1,5 @@
#=DESCRIPTION reference variables is null
#=EXRESULT FAIL
#=TODO
#needs post var expansion check that variable contained a value
@{FOO}=

View File

@@ -1,6 +1,5 @@
#=DESCRIPTION reference variables is null
#=EXRESULT FAIL
#=TODO
#needs post var expansion check that variable contained a value
@{FOO}=

View File

@@ -1,7 +1,6 @@
#
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
#=EXRESULT PASS
#=TODO
#
/usr/bin/foo {

View File

@@ -1,7 +1,6 @@
#
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
#=EXRESULT FAIL
#=TODO
#
/usr/bin/foo {
/b* px,

View File

@@ -29,6 +29,7 @@ DESTDIR=/
PROFILES_DEST=${DESTDIR}/etc/apparmor.d
EXTRAS_DEST=${DESTDIR}/usr/share/apparmor/extra-profiles/
PROFILES_SOURCE=./apparmor.d
ABSTRACTIONS_SOURCE=./apparmor.d/abstractions
EXTRAS_SOURCE=./apparmor/profiles/extras/
SUBDIRS=$(shell find ${PROFILES_SOURCE} -type d -print)
@@ -84,6 +85,8 @@ docs:
IGNORE_FILES=${EXTRAS_SOURCE}/README
CHECK_PROFILES=$(filter-out ${IGNORE_FILES} ${SUBDIRS}, $(wildcard ${PROFILES_SOURCE}/*) $(wildcard ${EXTRAS_SOURCE}/*))
# use find because Make wildcard is not recursive:
CHECK_ABSTRACTIONS=$(shell find ${ABSTRACTIONS_SOURCE} -type f -print)
.PHONY: check
check: check-parser check-logprof
@@ -96,6 +99,14 @@ check-parser: local
${PARSER} -S -b ${PWD}/apparmor.d $${profile} > /dev/null || exit 1; \
done
@echo "*** Checking abstractions from ${ABSTRACTIONS_SOURCE} against apparmor_parser"
$(Q)for abstraction in ${CHECK_ABSTRACTIONS} ; do \
[ -n "${VERBOSE}" ] && echo "Testing $${abstraction}" ; \
echo "#include <tunables/global> profile test { #include <$${abstraction}> }" \
| ${PARSER} -S -b ${PWD}/apparmor.d -I ${PWD} > /dev/null \
|| exit 1; \
done
.PHONY: check-logprof
check-logprof: local
@echo "*** Checking profiles from ${PROFILES_SOURCE} against logprof"

View File

@@ -7,9 +7,9 @@
# Allow unconfined processes to send us signals by default
signal (receive) peer=unconfined,
# Allow apache to send us signals by default
signal (receive) peer=/usr/{bin,sbin}/apache2,
signal (receive) peer=apache2,
# Allow other hats to signal by default
signal peer=/usr/{bin,sbin}/apache2//*,
signal peer=apache2//*,
# Allow us to signal ourselves
signal peer=@{profile_name},

View File

@@ -41,9 +41,14 @@
/usr/share/sounds/** r,
owner @{HOME}/.esd_auth r,
/etc/asound.conf r,
owner @{HOME}/.asoundrc r,
/etc/esound/esd.conf r,
# libao
/etc/libao.conf r,
owner @{HOME}/.libao r,
# libcanberra
owner @{HOME}/.cache/event-sound-cache.* rwk,
@@ -68,6 +73,7 @@ owner /tmp/pulse-*/* rw,
/etc/sound/** r,
# openal
/etc/alsa/conf.d/{,*} r,
/etc/openal/alsoft.conf r,
owner @{HOME}/.alsoftrc r,
/usr/{,local/}share/openal/hrtf/{,**} r,

View File

@@ -90,8 +90,8 @@
@{PROC}/meminfo r,
@{PROC}/stat r,
@{PROC}/cpuinfo r,
/sys/devices/system/cpu/ r,
/sys/devices/system/cpu/online r,
@{sys}/devices/system/cpu/ r,
@{sys}/devices/system/cpu/online r,
# glibc's *printf protections read the maps file
@{PROC}/@{pid}/{maps,auxv,status} r,

View File

@@ -14,6 +14,6 @@
deny capability block_suspend,
# dovecot's master can send us signals
signal receive peer=/usr/{bin,sbin}/dovecot,
signal receive peer=dovecot,
/{var/,}run/dovecot/config rw,

View File

@@ -18,7 +18,9 @@
/usr/share/fonts/** r,
/etc/fonts/** r,
/usr/share/fontconfig/conf.avail/** r,
# Debian, openSUSE paths are different
/usr/share/{fontconfig,fonts-config,*-fonts}/conf.avail/{,**} r,
/usr/share/ghostscript/fonts/{,**} r,
/opt/kde3/share/fonts/** r,
@@ -42,8 +44,8 @@
owner @{HOME}/.local/share/fonts/ r,
owner @{HOME}/.local/share/fonts/** r,
owner @{HOME}/.fonts.cache-2 mr,
owner @{HOME}/.{,cache/}fontconfig/ r,
owner @{HOME}/.{,cache/}fontconfig/** mrl,
owner @{HOME}/.{,cache/}fontconfig/ rw,
owner @{HOME}/.{,cache/}fontconfig/** mrwl,
owner @{HOME}/.fonts.conf.d/ r,
owner @{HOME}/.fonts.conf.d/** r,
owner @{HOME}/.config/fontconfig/ r,

View File

@@ -42,6 +42,7 @@
/usr/lib/@{multiarch}/gdk-pixbuf-*/** mr,
# per-user gtk configuration
owner @{HOME}/.config/gtk-3.0/ w,
owner @{HOME}/.config/gtk-3.0/* r,
owner @{HOME}/.gnome/Gnome r,
owner @{HOME}/.gtk r,
@@ -52,6 +53,7 @@
owner @{HOME}/.themes/** r,
# for gtk file dialog
owner @{HOME}/.config/gtk-2.0/ w,
owner @{HOME}/.config/gtk-2.0/** r,
owner @{HOME}/.config/gtk-2.0/gtkfilechooser.ini* rw,
@@ -62,6 +64,9 @@
# per-user font business
owner @{HOME}/.fonts.cache-* rwl,
# GtkComposeTable
owner @{HOME}/.cache/gtk-3.0/** r,
# icon caches
/var/cache/**/icon-theme.cache r,
/usr/share/**/icon-theme.cache r,

View File

@@ -23,7 +23,10 @@
/etc/kderc r,
/etc/kde3/* r,
/etc/kde4rc r,
/etc/xdg/kdeglobals r,
/etc/xdg/Trolltech.conf r,
/usr/share/knotifications5/*.notifyrc r, # KNotification::sendEvent()
/usr/share/kubuntu-default-settings/kf5-settings/* r,
owner @{HOME}/.DCOPserver_* r,
owner @{HOME}/.ICEauthority r,
@@ -31,7 +34,14 @@ owner @{HOME}/.fonts.* lrw,
owner @{HOME}/.kde{,4}/share/config/kdeglobals rw,
owner @{HOME}/.kde{,4}/share/config/*.lock rwl,
owner @{HOME}/.qt/** rw,
owner @{HOME}/.cache/ksycoca5_??_* r, # KDE System Configuration Cache
owner @{HOME}/.config/Trolltech.conf rwk,
owner @{HOME}/.config/baloofilerc r, # indexing options (excludes, etc), used by KFileWidget
owner @{HOME}/.config/dolphinrc r, # settings used by KFileWidget
owner @{HOME}/.config/kde.org/libphonon.conf r, # for KNotifications::sendEvent()
owner @{HOME}/.config/kdeglobals r, # global settings, used by Breeze style, etc.
owner @{HOME}/.config/klanguageoverridesrc r, # per-application languages, for KDEPrivate::initializeLanguages() from libKF5XmlGui.so
owner @{HOME}/.config/trashrc r, # Used by KFileWidget
/usr/share/icons/ r,
/usr/share/icons/** r,

View File

@@ -18,4 +18,7 @@
/etc/sasl2/* r,
/usr/lib{,32,64}/sasl2/* r,
# local LDAP name service daemon
/{,var/}run/nslcd/socket rw,
#include <abstractions/ssl_certs>

View File

@@ -39,7 +39,7 @@
/etc/resolv.conf r,
# On systems where /etc/resolv.conf is managed programmatically, it is
# a symlink to /{,var/}run/(whatever program is managing it)/resolv.conf.
/{,var/}run/{resolvconf,NetworkManager,systemd/resolve,connman}/resolv.conf r,
/{,var/}run/{resolvconf,NetworkManager,systemd/resolve,connman,netconfig}/resolv.conf r,
/etc/resolvconf/run/resolv.conf r,
/{,var/}run/systemd/resolve/stub-resolv.conf r,

View File

@@ -4,6 +4,8 @@
# configuration queries
capability ipc_lock,
/usr/share/nvidia/nvidia-application-profiles* r,
# libvdpau config file for nvidia workarounds
/etc/vdpau_wrapper.cfg r,

View File

@@ -17,8 +17,10 @@
# postfix's master can send us signals
signal receive peer=/usr/lib/postfix/master,
signal receive peer=postfix-master,
unix (send, receive) peer=(label=/usr/lib/postfix/master),
unix (send, receive) peer=(label=postfix-master),
/etc/mailname r,
/etc/postfix/*.cf r,

View File

@@ -6,6 +6,7 @@
# lot of false positives when reading contents of directories)
deny @{HOME}/.*history mrwkl,
deny @{HOME}/.fetchmail* mrwkl,
deny @{HOME}/.mutt** mrwkl,
deny @{HOME}/.viminfo* mrwkl,
deny @{HOME}/.*~ mrwkl,
deny @{HOME}/.*.swp mrwkl,

View File

@@ -5,6 +5,7 @@
#include <abstractions/private-files>
# potentially extremely sensitive files
audit deny @{HOME}/.aws/{,**} mrwkl,
audit deny @{HOME}/.gnupg/{,**} mrwkl,
audit deny @{HOME}/.ssh/{,**} mrwkl,
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,

View File

@@ -15,9 +15,9 @@
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
/usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
# Site-wide configuration
@@ -28,7 +28,7 @@
/{var,usr}/lib/{pyshared,pycentral,python-support}/** r,
/usr/lib/{pyshared,pycentral,python-support}/**.so mr,
/var/lib/{pyshared,pycentral,python-support}/**.pyc mr,
/usr/{,local/}lib/python3/dist-packages/**.so mr,
/usr/lib/python3/dist-packages/**.so mr,
# wx paths
/usr/lib/wx/python/*.pth r,

View File

@@ -16,6 +16,7 @@
# User files
owner @{HOME}/.config/QtProject/qtlogging.ini r,
owner @{HOME}/.config/QtProject.conf r, # common settings for QFileDialog, etc (application might need write access)
owner @{HOME}/.cache/qt_compose_cache_{little,big}_endian_* r, # for "platforminputcontexts" plugins

View File

@@ -3,5 +3,6 @@
# User files
owner @{HOME}/.cache/qt_compose_cache_{little,big}_endian_* rw,
owner @{HOME}/.cache/qt_compose_cache_{little,big}_endian_* rwl -> @{HOME}/.cache/#[0-9]*[0-9],
owner @{HOME}/.cache/#[0-9]*[0-9] rw, # QSaveFile (anonymous shared memory)

View File

@@ -3,9 +3,9 @@
# User files
owner @{HOME}/.config/#[0-9]* rw,
owner @{HOME}/.config/QtProject.conf rw,
owner @{HOME}/.config/QtProject.conf.?????? l -> @{HOME}/.config/#[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],
owner @{HOME}/.config/QtProject.conf.?????? rw, # for temporary files like QtProject.conf.Aqrgeb
owner @{HOME}/.config/#[0-9]*[0-9] rw,
owner @{HOME}/.config/QtProject.conf rwl -> @{HOME}/.config/#[0-9]*[0-9],
# for temporary files like QtProject.conf.Aqrgeb
owner @{HOME}/.config/QtProject.conf.?????? rwl -> @{HOME}/.config/#[0-9]*[0-9],
owner @{HOME}/.config/QtProject.conf.lock rwk,

View File

@@ -29,6 +29,12 @@
/var/lib/acme/certs/*/cert r,
# dehydrated
/etc/dehydrated/certs/*/cert-*.pem r,
/etc/dehydrated/certs/*/chain-*.pem r,
/etc/dehydrated/certs/*/fullchain-*.pem r,
/{etc,var/lib}/dehydrated/certs/*/cert*.pem r,
/{etc,var/lib}/dehydrated/certs/*/chain*.pem r,
/{etc,var/lib}/dehydrated/certs/*/fullchain*.pem r,
/{etc,var/lib}/dehydrated/certs/*/ocsp*.der r,
# certbot
/etc/letsencrypt/archive/*/cert*.pem r,
/etc/letsencrypt/archive/*/chain*.pem r,
/etc/letsencrypt/archive/*/fullchain*.pem r,

View File

@@ -22,4 +22,7 @@
/var/lib/acme/keys/** r,
# dehydrated
/etc/dehydrated/certs/*/privkey-*.pem r,
/{etc,var/lib}/dehydrated/certs/*/privkey*.pem r,
# certbot / letsencrypt
/etc/letsencrypt/archive/*/privkey*.pem r,

View File

@@ -41,8 +41,8 @@
@{PROC}/@{pid}/ r,
@{PROC}/@{pid}/fd/ r,
@{PROC}/filesystems r,
/sys/devices/system/cpu/ r,
/sys/devices/system/cpu/** r,
@{sys}/devices/system/cpu/ r,
@{sys}/devices/system/cpu/** r,
/usr/share/** r,
/var/lib/dbus/machine-id r,
@@ -88,8 +88,8 @@
@{PROC}/@{pid}/ r,
@{PROC}/@{pid}/fd/ r,
@{PROC}/filesystems r,
/sys/devices/system/cpu/ r,
/sys/devices/system/cpu/** r,
@{sys}/devices/system/cpu/ r,
@{sys}/devices/system/cpu/** r,
/usr/share/** r,
/var/lib/dbus/machine-id r,

View File

@@ -17,6 +17,9 @@
/usr/bin/gwenview Cxr -> sanitized_helper,
#include <abstractions/ubuntu-media-players>
owner @{HOME}/.adobe/ w,
owner @{HOME}/.adobe/** rw,
owner @{HOME}/.macromedia/ w,
owner @{HOME}/.macromedia/** rw,
/opt/real/RealPlayer/mozilla/nphelix.so rm,
/usr/bin/lpstat Cxr -> sanitized_helper,

View File

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

View File

@@ -0,0 +1,15 @@
# vim:syntax=apparmor
# Vulkan access requirements
# System files
/dev/dri/ r, # libvulkan_radeon.so, libvulkan_intel.so (Mesa)
/etc/vulkan/icd.d/{,*.json} r,
/etc/vulkan/{explicit,implicit}_layer.d/{,*.json} r,
# for drmGetMinorNameForFD() from libvulkan_intel.so (Mesa)
@{sys}/devices/pci[0-9]*/*/drm/ r,
/usr/share/vulkan/icd.d/{,*.json} r,
/usr/share/vulkan/{explicit,implicit}_layer.d/{,*.json} r,
# User files
owner @{HOME}/.local/share/vulkan/implicit_layer.d/{,*.json} r,

View File

@@ -20,13 +20,13 @@
/etc/phpsysinfo/config.php r,
/etc/udev/udev.conf r,
@{PROC}/** r,
/sys/bus/ r,
/sys/bus/pci/devices/ r,
/sys/bus/pci/slots/ r,
/sys/bus/pci/slots/** r,
/sys/bus/usb/devices/ r,
/sys/class/ r,
/sys/devices/** r,
@{sys}/bus/ r,
@{sys}/bus/pci/devices/ r,
@{sys}/bus/pci/slots/ r,
@{sys}/bus/pci/slots/** r,
@{sys}/bus/usb/devices/ r,
@{sys}/class/ r,
@{sys}/devices/** r,
/usr/bin/ r,
/usr/bin/apt-cache ixr,
/usr/bin/dpkg-query ixr,

View File

@@ -21,6 +21,7 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
#include <abstractions/nameservice>
#include <abstractions/mysql>
#include <abstractions/openssl>
#include <abstractions/python>
capability chown,
capability dac_override,
@@ -47,7 +48,7 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
/etc/hosts.deny r,
/etc/hosts.allow r,
/{usr/,}{bin,sbin}/syslog-ng mr,
/sys/devices/system/cpu/online r,
@{sys}/devices/system/cpu/online r,
/usr/share/syslog-ng/** r,
/var/lib/syslog-ng/syslog-ng-?????.qf rw,
# chrooted applications

View File

@@ -18,7 +18,10 @@
capability setuid,
capability sys_chroot,
unix (receive, send) type=stream peer=(label=dovecot),
/run/dovecot/anvil rw,
/run/dovecot/anvil-auth-penalty rw,
/usr/lib/dovecot/anvil mr,
# Site-specific additions and overrides. See local/README for details.

View File

@@ -25,6 +25,7 @@
capability dac_override,
capability dac_read_search,
capability setuid,
capability sys_chroot,
/etc/my.cnf r,
/etc/my.cnf.d/ r,
@@ -32,6 +33,7 @@
/etc/dovecot/* r,
/usr/lib/dovecot/auth mr,
/var/lib/dovecot/auth-chroot/* r,
# kerberos replay cache
/var/tmp/imap_* rw,
@@ -40,6 +42,7 @@
/var/tmp/smtp_* rw,
/run/dovecot/auth-master rw,
/run/dovecot/auth-userdb rw,
/run/dovecot/auth-worker rw,
/run/dovecot/login/login rw,
/{var/,}run/dovecot/auth-token-secret.dat{,.tmp} rw,
@@ -47,7 +50,7 @@
/{var/,}run/dovecot/stats-user rw,
/{var/,}run/dovecot/anvil-auth-penalty rw,
/var/spool/postfix/private/auth w,
/var/spool/postfix/private/auth rw,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.lib.dovecot.auth>

View File

@@ -29,14 +29,15 @@
/run/dovecot/auth-userdb rw,
/usr/bin/doveconf mrix,
/usr/lib/dovecot/dovecot-lda mrix,
/usr/{bin,sbin}/sendmail Cx,
/usr/{bin,sbin}/sendmail Cx -> sendmail,
/usr/share/dovecot/protocols.d/ r,
/usr/share/dovecot/protocols.d/** r,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.lib.dovecot.dovecot-lda>
profile /usr/{bin,sbin}/sendmail flags=(attach_disconnected) {
profile sendmail /usr/{bin,sbin}/sendmail flags=(attach_disconnected) {
# this profile is based on the usr.sbin.sendmail profile in extras
# and should support both postfix' and sendmail's sendmail binary

View File

@@ -17,9 +17,11 @@
#include <abstractions/nameservice>
#include <abstractions/dovecot-common>
#include <abstractions/openssl>
#include <abstractions/ssl_certs>
#include <abstractions/ssl_keys>
capability dac_override,
capability dac_read_search,
capability setuid,
@{DOVECOT_MAILSTORE}/ rw,

View File

@@ -25,6 +25,7 @@
network inet stream,
network inet6 stream,
network unix stream,
/usr/lib/dovecot/managesieve-login mr,
/{,var/}run/dovecot/login-master-notify* rw,

View File

@@ -22,8 +22,11 @@
capability setuid,
capability sys_chroot,
network unix stream,
/usr/lib/dovecot/pop3-login mr,
/{,var/}run/dovecot/anvil rw,
/{,var/}run/dovecot/login-master-notify* rw,
/{,var/}run/dovecot/login/ r,
/{,var/}run/dovecot/login/* rw,

View File

@@ -1,7 +1,7 @@
# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>
#include <tunables/global>
/usr/{bin,sbin}/apache2 flags=(attach_disconnected) {
profile apache2 /usr/{bin,sbin}/apache2 flags=(attach_disconnected) {
# This profile is completely permissive.
# It is designed to target specific applications using mod_apparmor,

View File

@@ -1,5 +1,5 @@
#include <tunables/global>
/usr/{bin,sbin}/avahi-daemon {
profile avahi-daemon /usr/{bin,sbin}/avahi-daemon {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/dbus>

View File

@@ -12,7 +12,13 @@
@{TFTP_DIR}=/var/tftp /srv/tftpboot
#include <tunables/global>
profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
# This profile has the name "/usr/sbin/dnsmasq", but attaches to both /usr/bin/dnsmasq and /usr/sbin/dnsmasq.
# We are sorry for the confusion ;-) but this trick is needed to support distributions with merged bin and sbin
# while not breaking the libvirtd profile that has rules with peer=/usr/sbin/dnsmasq
# Future versions of AppArmor (> 2.13.x) will have "dnsmasq" as profile name.
profile /usr/sbin/dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
#include <abstractions/base>
#include <abstractions/dbus>
#include <abstractions/nameservice>
@@ -28,7 +34,11 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
network inet6 raw,
signal (receive) peer=/usr/{bin,sbin}/libvirtd,
signal (receive) peer=/usr/sbin/libvirtd,
signal (receive) peer=libvirtd,
ptrace (readby) peer=/usr/{bin,sbin}/libvirtd,
ptrace (readby) peer=/usr/sbin/libvirtd,
ptrace (readby) peer=libvirtd,
owner /dev/tty rw,
@@ -45,7 +55,7 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
/usr/{bin,sbin}/dnsmasq mr,
/var/log/*dnsmasq.log w,
/var/log/dnsmasq*.log w,
/usr/share/dnsmasq/ r,
/usr/share/dnsmasq/* r,
@@ -96,6 +106,7 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
/{,var/}run/sendsigs.omit.d/*dnsmasq.pid w,
/{,var/}run/NetworkManager/dnsmasq.conf r,
/{,var/}run/NetworkManager/dnsmasq.pid w,
/{,var/}run/NetworkManager/NetworkManager.pid w,
profile libvirt_leaseshelper {
#include <abstractions/base>
@@ -107,9 +118,9 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
owner @{PROC}/@{pid}/net/psched r,
owner @{PROC}/@{pid}/status r,
/sys/devices/system/cpu/ r,
/sys/devices/system/node/ r,
/sys/devices/system/node/*/meminfo r,
@{sys}/devices/system/cpu/ r,
@{sys}/devices/system/node/ r,
@{sys}/devices/system/node/*/meminfo r,
# libvirt lease and status files for dnsmasq
/var/lib/libvirt/dnsmasq/*.leases rw,

View File

@@ -12,7 +12,7 @@
#include <tunables/global>
/usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
#include <abstractions/authentication>
#include <abstractions/base>
#include <abstractions/dovecot-common>
@@ -31,13 +31,16 @@
capability sys_chroot,
capability sys_resource,
signal send set=(int,quit) peer=/usr/lib/dovecot/*,
signal send set=(int,quit,term) peer=/usr/lib/dovecot/*,
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
/etc/dovecot/** r,
/etc/mtab r,
/etc/lsb-release r,
/etc/SuSE-release r,
@{PROC}/@{pid}/mounts r,
@{PROC}/sys/fs/suid_dumpable r,
/usr/bin/doveconf rix,
/usr/lib/dovecot/anvil mrPx,
/usr/lib/dovecot/auth mrPx,

View File

@@ -11,12 +11,13 @@
#include <tunables/global>
/usr/{bin,sbin}/identd {
profile identd /usr/{bin,sbin}/identd {
#include <abstractions/base>
#include <abstractions/nameservice>
capability net_bind_service,
capability setgid,
capability setuid,
network netlink dgram,
/etc/identd.conf r,
/etc/identd.key r,
/etc/identd.pid w,

View File

@@ -11,7 +11,7 @@
#include <tunables/global>
/usr/{bin,sbin}/mdnsd {
profile mdnsd /usr/{bin,sbin}/mdnsd {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/nameservice>

View File

@@ -1,6 +1,6 @@
#include <tunables/global>
/usr/{bin,sbin}/nmbd {
profile nmbd /usr/{bin,sbin}/nmbd {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/samba>

View File

@@ -10,7 +10,7 @@
# ------------------------------------------------------------------
#include <tunables/global>
/usr/{bin,sbin}/nscd {
profile nscd /usr/{bin,sbin}/nscd {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/nameservice>

View File

@@ -11,7 +11,7 @@
#include <tunables/global>
#include <tunables/ntpd>
/usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
profile ntpd /usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/openssl>

View File

@@ -1,6 +1,6 @@
#include <tunables/global>
/usr/{bin,sbin}/smbd {
profile smbd /usr/{bin,sbin}/smbd {
#include <abstractions/authentication>
#include <abstractions/base>
#include <abstractions/consoles>

View File

@@ -1,7 +1,7 @@
# Last Modified: Tue Jan 3 00:17:40 2012
#include <tunables/global>
/usr/{bin,sbin}/smbldap-useradd {
profile smbldap-useradd /usr/{bin,sbin}/smbldap-useradd {
#include <abstractions/base>
#include <abstractions/bash>
#include <abstractions/nameservice>

View File

@@ -1,6 +1,6 @@
#include <tunables/global>
/usr/{bin,sbin}/winbindd {
profile winbindd /usr/{bin,sbin}/winbindd {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/samba>

View File

@@ -3,7 +3,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2014 Christian Boltz
# Copyright (C) 2014-2019 Christian Boltz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -30,13 +30,14 @@
/etc/my.cnf.d/ r,
/etc/my.cnf.d/*.cnf r,
/root/.my.cnf r,
/sys/devices/system/cpu/online r,
/usr/lib{,32,64}/**.so mr,
/usr/sbin/mysqld r,
/usr/sbin/mysqld mr,
/usr/share/mariadb/*/errmsg.sys r,
/usr/share/mysql-community-server/*/errmsg.sys r,
/usr/share/mysql/** r,
/var/lib/mysql/ r,
/var/lib/mysql/** rwl,
/var/lib/mysql/** rwlk,
/var/log/mysql/mysqld-upgrade-run.log w,
/var/log/mysql/mysqld.log w,
/var/log/mysql/mysqld.log-20* w,

View File

@@ -17,7 +17,7 @@
#include <abstractions/consoles>
#include <abstractions/postfix-common>
/etc/aliases r,
/etc/aliases.db rwl,
/etc/aliases.db rwlk,
/etc/postfix r,
/etc/postfix/main.cf r,
/etc/postfix/aliases r,

View File

@@ -132,10 +132,10 @@ sub gen_binary($) {
my $hashbang = head($bin);
if ($hashbang && $hashbang =~ /^#!\s*(\S+)/) {
my $interpreter = $1;
gen_file("$interpreter:rix");
gen_file(realpath($interpreter) . ":rix");
gen_elf_binary($interpreter);
} else {
gen_elf_binary($bin)
gen_elf_binary(realpath($bin))
}
}

View File

@@ -67,21 +67,9 @@ if [ ! -b /dev/loop0 ] ; then
modprobe loop
fi
# kinda ugly way of atomically finding a free loop device
for i in $(seq 0 15)
do
if [ "$loop_device" = "unset" ]
then
if /sbin/losetup /dev/loop$i ${mount_file} > /dev/null 2> /dev/null
then
loop_device=/dev/loop$i;
fi
fi
done
if [ "$loop_device" = "unset" ]
then
fatalerror 'Unable to find a free loop device'
fi
# find the next free loop device and mount it
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
# TEST 1. Make sure can mount and umount unconfined

View File

@@ -30,26 +30,29 @@ bin=$pwd
helper=$pwd/ptrace_helper
bin_true=${tmpdir}/true
cp -pL /bin/true ${tmpdir}/true
# -n number of syscalls to perform
# -c have the child call ptrace_me, else parent does ptrace_attach
# -h transition child to ptrace_helper before doing ptrace (used to test
# x transitions with ptrace)
# test base line of unconfined tracing unconfined
runchecktest "test 1" pass -n 100 /bin/true
runchecktest "test 1 -c" pass -c -n 100 /bin/true
runchecktest "test 1" pass -n 100 ${bin_true}
runchecktest "test 1 -c" pass -c -n 100 ${bin_true}
runchecktest "test 1 -h" pass -h -n 100 $helper
runchecktest "test 1 -hc" pass -h -c -n 100 $helper
runchecktest "test 1 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 1 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 1 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 1 -hc prog" pass -h -c -n 100 $helper ${bin_true}
# test that unconfined can ptrace before profile attaches
genprofile image=/bin/true signal:ALL
runchecktest "test 2" pass -n 100 /bin/true
runchecktest "test 2 -c" pass -c -n 100 /bin/true
genprofile image=${bin_true} signal:ALL
runchecktest "test 2" pass -n 100 ${bin_true}
runchecktest "test 2 -c" pass -c -n 100 ${bin_true}
runchecktest "test 2 -h" pass -h -n 100 $helper
runchecktest "test 2 -hc" pass -h -c -n 100 $helper
runchecktest "test 2 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 2 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 2 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 2 -hc prog" pass -h -c -n 100 $helper ${bin_true}
if [ "$(kernel_features ptrace)" == "true" -a "$(parser_supports 'ptrace,')" == "true" ] ; then

View File

@@ -13,133 +13,133 @@
genprofile image=$helper
runchecktest "test 3 -h" pass -h -n 100 $helper
runchecktest "test 3 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 3 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 3 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 3 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 3 -hc prog" fail -h -c -n 100 $helper ${bin_true}
# lack of 'r' perm is currently not working
genprofile image=$helper $helper:ix
runchecktest "test 4 -h" pass -h -n 100 $helper
runchecktest "test 4 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 4 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 4 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 4 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 4 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:rix
runchecktest "test 5 -h" pass -h -n 100 $helper
runchecktest "test 5 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 5 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 5 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 5 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 5 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:ix /bin/true:rix
genprofile image=$helper $helper:ix ${bin_true}:rix
runchecktest "test 6 -h" pass -h -n 100 $helper
runchecktest "test 6 -hc " pass -h -c -n 100 $helper
runchecktest "test 6 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 6 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 6 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 6 -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced child can ptrace_me to unconfined have unconfined trace them
genprofile image=/bin/true
runchecktest "test 7" pass -n 100 /bin/true
genprofile image=${bin_true}
runchecktest "test 7" pass -n 100 ${bin_true}
# pass - ptrace_attach is done in unconfined helper
runchecktest "test 7 -c " pass -c -n 100 /bin/true
runchecktest "test 7 -c " pass -c -n 100 ${bin_true}
runchecktest "test 7 -h" pass -h -n 100 $helper
# pass - ptrace_attach is done in unconfined helper
runchecktest "test 7 -hc " pass -h -c -n 100 $helper
runchecktest "test 7 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 7 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 7 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 7 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:ix /bin/true:rix
runchecktest "test 7a" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rix
runchecktest "test 7a" pass -n 100 ${bin_true}
# pass - ptrace_attach is allowed from confined process to unconfined
runchecktest "test 7a -c " pass -c -n 100 /bin/true
runchecktest "test 7a -c " pass -c -n 100 ${bin_true}
runchecktest "test 7a -h" pass -h -n 100 $helper
# pass - ptrace_attach is allowed from confined process to unconfined
runchecktest "test 7a -hc " pass -h -c -n 100 $helper
runchecktest "test 7a -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 7a -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 7a -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 7a -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced helper from unconfined
genprofile image=$helper $helper:ix /bin/true:rpx -- image=/bin/true
runchecktest "test 8" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rpx -- image=${bin_true}
runchecktest "test 8" pass -n 100 ${bin_true}
# pass - ptrace_attach is done before exec
runchecktest "test 8 -c " pass -c -n 100 /bin/true
runchecktest "test 8 -c " pass -c -n 100 ${bin_true}
runchecktest "test 8 -h" pass -h -n 100 $helper
runchecktest "test 8 -hc " pass -h -c -n 100 $helper
# pass - can px if tracer can ptrace target
runchecktest "test 8 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 8 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 8 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 8 -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced helper from unconfined
genprofile image=$helper $helper:ix /bin/true:rux -- image=/bin/true
runchecktest "test 9" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rux -- image=${bin_true}
runchecktest "test 9" pass -n 100 ${bin_true}
# pass - ptrace_attach is done before exec
runchecktest "test 9 -c " pass -c -n 100 /bin/true
runchecktest "test 9 -c " pass -c -n 100 ${bin_true}
runchecktest "test 9 -h" pass -h -n 100 $helper
runchecktest "test 9 -hc " pass -h -c -n 100 $helper
# pass - can ux if tracer can ptrace target
runchecktest "test 9 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 9 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 9 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 9 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile
# fail due to no exec permission
runchecktest "test 10" fail -n 100 /bin/true
runchecktest "test 10 -c" fail -c -n 100 /bin/true
runchecktest "test 10" fail -n 100 ${bin_true}
runchecktest "test 10 -c" fail -c -n 100 ${bin_true}
runchecktest "test 10 -h" fail -h -n 100 $helper
runchecktest "test 10 -hc" fail -h -c -n 100 $helper
runchecktest "test 10 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 10 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 10 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 10 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:ix $helper:ix
genprofile ${bin_true}:ix $helper:ix
# fail due to missing r permission
#runchecktest "test 11" fail -n 100 /bin/true
#runchecktest "test 11 -c" fail -c -n 100 /bin/true
#runchecktest "test 11" fail -n 100 ${bin_true}
#runchecktest "test 11 -c" fail -c -n 100 ${bin_true}
#runchecktest "test 11 -h" fail -h -n 100 $helper
#runchecktest "test 11 -hc" fail -h -c -n 100 $helper
#runchecktest "test 11 -h prog" fail -h -n 100 $helper /bin/true
#runchecktest "test 11 -hc prog" fail -h -c -n 100 $helper /bin/true
#runchecktest "test 11 -h prog" fail -h -n 100 $helper ${bin_true}
#runchecktest "test 11 -hc prog" fail -h -c -n 100 $helper ${bin_true}
# pass allowed to ix self
genprofile /bin/true:rix $helper:rix
runchecktest "test 12" pass -n 100 /bin/true
runchecktest "test 12 -c" pass -c -n 100 /bin/true
genprofile ${bin_true}:rix $helper:rix
runchecktest "test 12" pass -n 100 ${bin_true}
runchecktest "test 12 -c" pass -c -n 100 ${bin_true}
runchecktest "test 12 -h" pass -h -n 100 $helper
runchecktest "test 12 -hc" pass -h -c -n 100 $helper
runchecktest "test 12 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 12 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 12 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 12 -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app can't px - fails to unset profile
genprofile image=$helper $helper:rix /bin/true:rpx
runchecktest "test 13 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rpx
runchecktest "test 13 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app can ux - if the tracer is unconfined
#
genprofile image=$helper $helper:rix /bin/true:rux
runchecktest "test 14a -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 14a -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rux
runchecktest "test 14a -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 14a -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app can't ux - if the tracer can't trace unconfined
genprofile $helper:rpx -- image=$helper $helper:rix /bin/true:rux
runchecktest "test 14b -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 14b -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile $helper:rpx -- image=$helper $helper:rix ${bin_true}:rux
runchecktest "test 14b -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 14b -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an unconfined app
genprofile $helper:rux
runchecktest "test 15 -h" fail -h -n 100 $helper
runchecktest "test 15 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15 -h prog" fail -h -n 100 $helper ${bin_true}
#an unconfined app can't ask a confined app to trace it
runchecktest "test 15 -hc" fail -h -c -n 100 $helper
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an app confined by a different profile
genprofile $helper:rpx -- image=$helper
runchecktest "test 15 -h" fail -h -n 100 $helper
runchecktest "test 15 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15 -h prog" fail -h -n 100 $helper ${bin_true}
#a confined app can't ask another confined app with a different profile to
#trace it
runchecktest "test 15 -hc" fail -h -c -n 100 $helper
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper ${bin_true}

View File

@@ -25,186 +25,186 @@ genprofile image=$helper signal:ALL ptrace:tracedby:peer=unconfined
runchecktest "test 3 -h" pass -h -n 100 $helper
runchecktest "test 3 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 3 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 3 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 3 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 3 -hc prog" fail -h -c -n 100 $helper ${bin_true}
# lack of 'r' perm is currently not working
genprofile image=$helper $helper:ix signal:ALL
runchecktest "test 4 -h" pass -h -n 100 $helper
runchecktest "test 4 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 4 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 4 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 4 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 4 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:rix signal:ALL
runchecktest "test 5 -h" pass -h -n 100 $helper
runchecktest "test 5 -hc " pass -h -c -n 100 $helper
# can't exec /bin/true so fail
runchecktest "test 5 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 5 -hc prog" fail -h -c -n 100 $helper /bin/true
# can't exec ${bin_true} so fail
runchecktest "test 5 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 5 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:ix /bin/true:rix signal:ALL
genprofile image=$helper $helper:ix ${bin_true}:rix signal:ALL
runchecktest "test 6 -h" pass -h -n 100 $helper
runchecktest "test 6 -hc " pass -h -c -n 100 $helper
runchecktest "test 6 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 6 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 6 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 6 -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced child can ptrace_me to unconfined have unconfined trace them
genprofile image=/bin/true signal:ALL
runchecktest "test 7" pass -n 100 /bin/true
genprofile image=${bin_true} signal:ALL
runchecktest "test 7" pass -n 100 ${bin_true}
# pass - ptrace_attach is done in unconfined helper
runchecktest "test 7 -c " pass -c -n 100 /bin/true
runchecktest "test 7 -c " pass -c -n 100 ${bin_true}
runchecktest "test 7 -h" pass -h -n 100 $helper
# pass - ptrace_attach is done in unconfined helper
runchecktest "test 7 -hc " pass -h -c -n 100 $helper
runchecktest "test 7 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 7 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 7 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 7 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile image=$helper $helper:ix /bin/true:rix signal:ALL
runchecktest "test 7a" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rix signal:ALL
runchecktest "test 7a" pass -n 100 ${bin_true}
# pass - ptrace_attach is allowed from confined process to unconfined
runchecktest "test 7a -c " pass -c -n 100 /bin/true
runchecktest "test 7a -c " pass -c -n 100 ${bin_true}
runchecktest "test 7a -h" pass -h -n 100 $helper
# pass - ptrace_attach is allowed from confined process to unconfined
runchecktest "test 7a -hc " pass -h -c -n 100 $helper
runchecktest "test 7a -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 7a -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 7a -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 7a -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced helper from unconfined
genprofile image=$helper $helper:ix /bin/true:rpx signal:ALL -- image=/bin/true signal:ALL
runchecktest "test 8" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rpx signal:ALL -- image=${bin_true} signal:ALL
runchecktest "test 8" pass -n 100 ${bin_true}
# pass - ptrace_attach is done before exec
runchecktest "test 8 -c " pass -c -n 100 /bin/true
runchecktest "test 8 -c " pass -c -n 100 ${bin_true}
runchecktest "test 8 -h" pass -h -n 100 $helper
runchecktest "test 8 -hc " pass -h -c -n 100 $helper
# pass - can px if tracer can ptrace target
runchecktest "test 8 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 8 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 8 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 8 -hc prog" pass -h -c -n 100 $helper ${bin_true}
#traced helper from unconfined
genprofile image=$helper $helper:ix /bin/true:rux signal:ALL -- image=/bin/true signal:ALL
runchecktest "test 9" pass -n 100 /bin/true
genprofile image=$helper $helper:ix ${bin_true}:rux signal:ALL -- image=${bin_true} signal:ALL
runchecktest "test 9" pass -n 100 ${bin_true}
# pass - ptrace_attach is done before exec
runchecktest "test 9 -c " pass -c -n 100 /bin/true
runchecktest "test 9 -c " pass -c -n 100 ${bin_true}
runchecktest "test 9 -h" pass -h -n 100 $helper
runchecktest "test 9 -hc " pass -h -c -n 100 $helper
# pass - can ux if tracer can ptrace target
runchecktest "test 9 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 9 -hc prog" pass -h -c -n 100 $helper /bin/true
runchecktest "test 9 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 9 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile signal:ALL
# fail due to no exec permission
runchecktest "test 10" fail -n 100 /bin/true
runchecktest "test 10 -c" fail -c -n 100 /bin/true
runchecktest "test 10" fail -n 100 ${bin_true}
runchecktest "test 10 -c" fail -c -n 100 ${bin_true}
runchecktest "test 10 -h" fail -h -n 100 $helper
runchecktest "test 10 -hc" fail -h -c -n 100 $helper
runchecktest "test 10 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 10 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 10 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 10 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:ix $helper:ix signal:ALL
genprofile ${bin_true}:ix $helper:ix signal:ALL
# fail due to missing r permission
#runchecktest "test 11" fail -n 100 /bin/true
#runchecktest "test 11 -c" fail -c -n 100 /bin/true
#runchecktest "test 11" fail -n 100 ${bin_true}
#runchecktest "test 11 -c" fail -c -n 100 ${bin_true}
#runchecktest "test 11 -h" fail -h -n 100 $helper
#runchecktest "test 11 -hc" fail -h -c -n 100 $helper
#runchecktest "test 11 -h prog" fail -h -n 100 $helper /bin/true
#runchecktest "test 11 -hc prog" fail -h -c -n 100 $helper /bin/true
#runchecktest "test 11 -h prog" fail -h -n 100 $helper ${bin_true}
#runchecktest "test 11 -hc prog" fail -h -c -n 100 $helper ${bin_true}
# fail was pass in v5 allowed to ix self
genprofile /bin/true:rix $helper:rix signal:ALL
runchecktest "test 12" fail -n 100 /bin/true
runchecktest "test 12 -c" fail -c -n 100 /bin/true
genprofile ${bin_true}:rix $helper:rix signal:ALL
runchecktest "test 12" fail -n 100 ${bin_true}
runchecktest "test 12 -c" fail -c -n 100 ${bin_true}
runchecktest "test 12 -h" fail -h -n 100 $helper
runchecktest "test 12 -hc" fail -h -c -n 100 $helper
runchecktest "test 12 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 12 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 12 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 12 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app traced by unconfined can px
genprofile image=$helper $helper:rix /bin/true:rpx signal:ALL -- image=/bin/true /bin/true:rix
runchecktest "test 13u -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13u -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rpx signal:ALL -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13u -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13u -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app traced by profile without ptrace on targeted can't px
genprofile /bin/true:rpx signal:ALL -- image=/bin/true /bin/true:rix
runchecktest "test 13 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx signal:ALL -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app can ux - if the tracer is unconfined
#
genprofile image=$helper $helper:rix /bin/true:rux signal:ALL
runchecktest "test 14a -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 14a -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rux signal:ALL
runchecktest "test 14a -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 14a -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app can't ux - if the tracer can't trace unconfined
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix /bin/true:rux signal:ALL
runchecktest "test 14b -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 14b -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix ${bin_true}:rux signal:ALL
runchecktest "test 14b -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 14b -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an unconfined app
genprofile $helper:rux signal:ALL
runchecktest "test 15 -h" fail -h -n 100 $helper
runchecktest "test 15 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15 -h prog" fail -h -n 100 $helper ${bin_true}
#an unconfined app can't ask a confined app to trace it
runchecktest "test 15 -hc" fail -h -c -n 100 $helper
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an app confined by a different profile
genprofile $helper:rpx signal:ALL -- image=$helper signal:ALL
runchecktest "test 15 -h" fail -h -n 100 $helper
runchecktest "test 15 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15 -h prog" fail -h -n 100 $helper ${bin_true}
#a confined app can't ask another confined app with a different profile to
#trace it
runchecktest "test 15 -hc" fail -h -c -n 100 $helper
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15 -hc prog" fail -h -c -n 100 $helper ${bin_true}
################### cap:sys_ptrace doesn't change results from above ##########################
# fail was pass in v5 allowed to ix self
genprofile /bin/true:rix $helper:rix signal:ALL cap:sys_ptrace
runchecktest "test 12c" fail -n 100 /bin/true
runchecktest "test 12c -c" fail -c -n 100 /bin/true
genprofile ${bin_true}:rix $helper:rix signal:ALL cap:sys_ptrace
runchecktest "test 12c" fail -n 100 ${bin_true}
runchecktest "test 12c -c" fail -c -n 100 ${bin_true}
runchecktest "test 12c -h" fail -h -n 100 $helper
runchecktest "test 12c -hc" fail -h -c -n 100 $helper
runchecktest "test 12c -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 12c -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 12c -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 12c -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app traced by unconfined can px
genprofile image=$helper $helper:rix /bin/true:rpx signal:ALL cap:sys_ptrace -- image=/bin/true /bin/true:rix cap:sys_ptrace
runchecktest "test 13cu -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13cu -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rpx signal:ALL cap:sys_ptrace -- image=${bin_true} ${bin_true}:rix cap:sys_ptrace
runchecktest "test 13cu -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13cu -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app traced by profile without ptrace on targeted can't px
genprofile /bin/true:rpx signal:ALL cap:sys_ptrace -- image=/bin/true /bin/true:rix cap:sys_ptrace
runchecktest "test 13c -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13c -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx signal:ALL cap:sys_ptrace -- image=${bin_true} ${bin_true}:rix cap:sys_ptrace
runchecktest "test 13c -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13c -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app can ux - if the tracer is unconfined
#
genprofile image=$helper $helper:rix /bin/true:rux signal:ALL cap:sys_ptrace
runchecktest "test 14ca -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 14ca -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rux signal:ALL cap:sys_ptrace
runchecktest "test 14ca -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 14ca -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app can't ux - if the tracer can't trace unconfined
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix /bin/true:rux signal:ALL
runchecktest "test 14cb -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 14cb -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix ${bin_true}:rux signal:ALL
runchecktest "test 14cb -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 14cb -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an unconfined app
genprofile $helper:rux signal:ALL cap:sys_ptrace
runchecktest "test 15c -h" fail -h -n 100 $helper
runchecktest "test 15c -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15c -h prog" fail -h -n 100 $helper ${bin_true}
#an unconfined app can't ask a confined app to trace it
runchecktest "test 15c -hc" fail -h -c -n 100 $helper
runchecktest "test 15c -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15c -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an app confined by a different profile
genprofile $helper:rpx signal:ALL cap:sys_ptrace -- image=$helper signal:ALL cap:sys_ptrace
runchecktest "test 15c -h" fail -h -n 100 $helper
runchecktest "test 15c -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15c -h prog" fail -h -n 100 $helper ${bin_true}
#a confined app can't ask another confined app with a different profile to
#trace it
runchecktest "test 15c -hc" fail -h -c -n 100 $helper
runchecktest "test 15c -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15c -hc prog" fail -h -c -n 100 $helper ${bin_true}
################################################################################
@@ -213,163 +213,163 @@ runchecktest "test 15c -hc prog" fail -h -c -n 100 $helper /bin/true
##### Now do tests with ptrace rules in profiles #######
# pass in v5 allowed to ix self
genprofile /bin/true:rix $helper:rix signal:ALL ptrace:ALL
runchecktest "test 12p" pass -n 100 /bin/true
runchecktest "test 12p -c" pass -c -n 100 /bin/true
genprofile ${bin_true}:rix $helper:rix signal:ALL ptrace:ALL
runchecktest "test 12p" pass -n 100 ${bin_true}
runchecktest "test 12p -c" pass -c -n 100 ${bin_true}
runchecktest "test 12p -h" pass -h -n 100 $helper
runchecktest "test 12p -hc" pass -h -c -n 100 $helper
runchecktest "test 12p -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 12p -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rix $helper:rix signal:ALL ptrace:peer=$test
runchecktest "test 12p1" pass -n 100 /bin/true
runchecktest "test 12p1 -c" pass -c -n 100 /bin/true
runchecktest "test 12p -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 12p -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rix $helper:rix signal:ALL ptrace:peer=$test
runchecktest "test 12p1" pass -n 100 ${bin_true}
runchecktest "test 12p1 -c" pass -c -n 100 ${bin_true}
runchecktest "test 12p1 -h" pass -h -n 100 $helper
runchecktest "test 12p1 -hc" pass -h -c -n 100 $helper
runchecktest "test 12p1 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 12p1 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rix $helper:rix signal:ALL ptrace:peer=notaprofile
runchecktest "test 12p2" fail -n 100 /bin/true
runchecktest "test 12p2 -c" fail -c -n 100 /bin/true
runchecktest "test 12p1 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 12p1 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rix $helper:rix signal:ALL ptrace:peer=notaprofile
runchecktest "test 12p2" fail -n 100 ${bin_true}
runchecktest "test 12p2 -c" fail -c -n 100 ${bin_true}
runchecktest "test 12p2 -h" fail -h -n 100 $helper
runchecktest "test 12p2 -hc" fail -h -c -n 100 $helper
runchecktest "test 12p2 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 12p2 -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 12p2 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 12p2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
#ptraced confined app traced by profile can px
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix
runchecktest "test 13p1 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p2 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p3 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p4 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p5 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p6 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p7 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p8 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p9 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p1 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p3 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p4 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p5 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p6 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p7 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p8 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p9 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix
runchecktest "test 13p11 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p21 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p31 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p41 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p51 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p61 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p71 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p81 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p91 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa1 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb1 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc1 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=/bin/true -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd1 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe1 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p11 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p21 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p31 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p41 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p51 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p61 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p71 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p81 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p91 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa1 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb1 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc1 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:trace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd1 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe1 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix
runchecktest "test 13p12 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p22 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p32 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p42 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p52 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 13p62 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p72 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p82 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p92 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa2 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb2 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc2 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd2 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe2 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p12 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p22 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p32 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p42 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p52 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 13p62 -hc prog" pass -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p72 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p82 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p92 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb2 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:ALL -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd2 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix
runchecktest "test 13p13 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p23 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p33 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p43 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p53 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p63 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p73 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p83 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p93 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa3 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb3 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc3 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd3 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe3 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p13 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p23 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p33 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p43 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p53 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p63 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p73 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p83 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p93 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa3 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb3 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc3 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd3 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe3 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix
runchecktest "test 13p14 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p24 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p34 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p44 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p54 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p64 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p74 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p84 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p94 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa4 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb4 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc4 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd4 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe4 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p14 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p24 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p34 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p44 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p54 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p64 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p74 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p84 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p94 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa4 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb4 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc4 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:tracedby:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd4 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe4 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix
runchecktest "test 13p15 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p25 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby
runchecktest "test 13p35 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p45 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=$test
runchecktest "test 13p55 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p65 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p75 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13p85 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace
runchecktest "test 13p95 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pa5 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace:peer=$test
runchecktest "test 13pb5 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pc5 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile /bin/true:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=/bin/true /bin/true:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd5 -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 13pe5 -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix
runchecktest "test 13p15 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p25 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby
runchecktest "test 13p35 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p45 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=$test
runchecktest "test 13p55 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p65 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:tracedby:peer=notaprofile
runchecktest "test 13p75 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13p85 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace
runchecktest "test 13p95 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pa5 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=$test
runchecktest "test 13pb5 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pc5 -hc prog" fail -h -c -n 100 $helper ${bin_true}
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=notaprofile -- image=${bin_true} ${bin_true}:rix ptrace:trace:peer=notaprofile
runchecktest "test 13pd5 -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 13pe5 -hc prog" fail -h -c -n 100 $helper ${bin_true}
### todo Variations of below tests
@@ -377,30 +377,30 @@ runchecktest "test 13pe5 -hc prog" fail -h -c -n 100 $helper /bin/true
#ptraced confined app can ux - if the tracer is unconfined
#
genprofile image=$helper $helper:rix /bin/true:rux signal:ALL
runchecktest "test 14pa -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test 14pa -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile image=$helper $helper:rix ${bin_true}:rux signal:ALL
runchecktest "test 14pa -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test 14pa -hc prog" pass -h -c -n 100 $helper ${bin_true}
#ptraced confined app can't ux - if the tracer can't trace unconfined
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix /bin/true:rux signal:ALL
runchecktest "test 14pb -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 14pb -hc prog" fail -h -c -n 100 $helper /bin/true
genprofile $helper:rpx signal:ALL -- image=$helper $helper:rix ${bin_true}:rux signal:ALL
runchecktest "test 14pb -h prog" fail -h -n 100 $helper ${bin_true}
runchecktest "test 14pb -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an unconfined app
genprofile $helper:rux signal:ALL
runchecktest "test 15p -h" fail -h -n 100 $helper
runchecktest "test 15p -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15p -h prog" fail -h -n 100 $helper ${bin_true}
#an unconfined app can't ask a confined app to trace it
runchecktest "test 15p -hc" fail -h -c -n 100 $helper
runchecktest "test 15p -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15p -hc prog" fail -h -c -n 100 $helper ${bin_true}
#confined app can't ptrace an app confined by a different profile
genprofile $helper:rpx signal:ALL -- image=$helper signal:ALL
runchecktest "test 15p -h" fail -h -n 100 $helper
runchecktest "test 15p -h prog" fail -h -n 100 $helper /bin/true
runchecktest "test 15p -h prog" fail -h -n 100 $helper ${bin_true}
#a confined app can't ask another confined app with a different profile to
#trace it
runchecktest "test 15p -hc" fail -h -c -n 100 $helper
runchecktest "test 15p -hc prog" fail -h -c -n 100 $helper /bin/true
runchecktest "test 15p -hc prog" fail -h -c -n 100 $helper ${bin_true}
# Test LP: #1390592
# The bug was a policy compilation bug that triggers in a rule such as
@@ -408,9 +408,9 @@ runchecktest "test 15p -hc prog" fail -h -c -n 100 $helper /bin/true
# a-f|A-F|0-9 to trigger the bug. A parser affected by this bug will create a
# bad binary policy that causes the kernel to unexpectedly deny the ptrace
# 'trace' of a process confined by profile ABC.
genprofile "$helper rpx -> ABC" signal:ALL ptrace:trace:peer=ABC -- image=ABC addimage:$helper /bin/true:rix signal:ALL ptrace:tracedby:peer=$test
runchecktest "test LP: #1390592 -h prog" pass -h -n 100 $helper /bin/true
runchecktest "test LP: #1390592 -hc prog" pass -h -c -n 100 $helper /bin/true
genprofile "$helper rpx -> ABC" signal:ALL ptrace:trace:peer=ABC -- image=ABC addimage:$helper ${bin_true}:rix signal:ALL ptrace:tracedby:peer=$test
runchecktest "test LP: #1390592 -h prog" pass -h -n 100 $helper ${bin_true}
runchecktest "test LP: #1390592 -hc prog" pass -h -c -n 100 $helper ${bin_true}
## TODO: ptrace read tests
## TODO: ptrace + change_profile

View File

@@ -107,7 +107,7 @@ apparmor.check_qualifiers(program)
apparmor.loadincludes()
profile_filename = apparmor.get_profile_filename(program)
profile_filename = apparmor.get_profile_filename_from_attachment(program, True)
if os.path.exists(profile_filename):
apparmor.helpers[program] = apparmor.get_profile_flags(profile_filename, program)
else:

View File

@@ -1,7 +1,7 @@
#! /usr/bin/python3
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
# Copyright (C) 2014-2018 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
@@ -57,7 +57,7 @@ def reset_aa():
apparmor.aa.aa = apparmor.aa.hasher()
apparmor.aa.filelist = apparmor.aa.hasher()
apparmor.aa.include = dict()
apparmor.aa.existing_profiles = apparmor.aa.hasher()
apparmor.aa.active_profiles = apparmor.aa.ProfileList()
apparmor.aa.original_aa = apparmor.aa.hasher()
def find_profiles_from_files(files):
@@ -75,7 +75,7 @@ def find_files_from_profiles(profiles):
apparmor.aa.read_profiles()
for profile_name in profiles:
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename(profile_name)
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename_from_profile_name(profile_name, True)
reset_aa()

View File

@@ -92,7 +92,8 @@ System-wide configuration for B<aa-notify> is done via
# only people in use_group can use aa-notify
use_group="admin"
Per-user configuration is done via ~/.apparmor/notify.conf:
Per-user configuration is done via $XDG_CONFIG_HOME/apparmor/notify.conf (or
the deprecated ~/.apparmor/notify.conf if it exists):
# set to 'yes' to enable AppArmor DENIED notifications
show_notifications="yes"

View File

@@ -1,6 +1,6 @@
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
# Copyright (C) 2014-2018 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
@@ -49,6 +49,8 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END, RE_PROFILE_LINK,
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
strip_quotes, parse_profile_start_line, re_match_include )
from apparmor.profile_list import ProfileList
from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletypes, write_abi
import apparmor.rules as aarules
@@ -88,7 +90,8 @@ extra_profile_dir = None
# To keep track of previously included profile fragments
include = dict()
existing_profiles = dict()
active_profiles = ProfileList()
extra_profiles = ProfileList()
# To store the globs entered by users so they can be provided again
# format: user_globs['/foo*'] = AARE('/foo*')
@@ -216,11 +219,29 @@ def find_executable(bin_path):
return full_bin
return None
def get_profile_filename(profile):
"""Returns the full profile name"""
if existing_profiles.get(profile, False):
return existing_profiles[profile]
elif profile.startswith('/'):
def get_profile_filename_from_profile_name(profile, get_new=False):
"""Returns the full profile name for the given profile name"""
filename = active_profiles.filename_from_profile_name(profile)
if filename:
return filename
if get_new:
return get_new_profile_filename(profile)
def get_profile_filename_from_attachment(profile, get_new=False):
"""Returns the full profile name for the given attachment"""
filename = active_profiles.filename_from_attachment(profile)
if filename:
return filename
if get_new:
return get_new_profile_filename(profile)
def get_new_profile_filename(profile):
'''Compose filename for a new profile'''
if profile.startswith('/'):
# Remove leading /
profile = profile[1:]
else:
@@ -237,7 +258,7 @@ def name_to_prof_filename(prof_filename):
else:
bin_path = find_executable(prof_filename)
if bin_path:
prof_filename = get_profile_filename(bin_path)
prof_filename = get_profile_filename_from_attachment(bin_path, True)
if os.path.isfile(prof_filename):
return (prof_filename, bin_path)
@@ -463,7 +484,7 @@ def create_new_profile(localfile, is_stub=False):
def delete_profile(local_prof):
"""Deletes the specified file from the disk and remove it from our list"""
profile_file = get_profile_filename(local_prof)
profile_file = get_profile_filename_from_profile_name(local_prof, True)
if os.path.isfile(profile_file):
os.remove(profile_file)
if aa.get(local_prof, False):
@@ -497,13 +518,15 @@ def get_profile(prof_name):
if inactive_profile:
uname = 'Inactive local profile for %s' % prof_name
inactive_profile[prof_name][prof_name]['flags'] = 'complain'
orig_filename = inactive_profile[prof_name][prof_name]['filename'] # needed for CMD_VIEW_PROFILE
inactive_profile[prof_name][prof_name]['filename'] = ''
profile_hash[uname]['username'] = uname
profile_hash[uname]['profile_type'] = 'INACTIVE_LOCAL'
profile_hash[uname]['profile'] = serialize_profile(inactive_profile[prof_name], prof_name, None)
profile_hash[uname]['profile_data'] = inactive_profile
existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
# no longer necessary after splitting active and extra profiles
# existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
# If no profiles in repo and no inactive profiles
if not profile_hash.keys():
@@ -537,11 +560,7 @@ def get_profile(prof_name):
q.selected = options.index(options[arg])
if ans == 'CMD_VIEW_PROFILE':
pager = get_pager()
proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
# proc.communicate('Profile submitted by %s:\n\n%s\n\n' %
# (options[arg], p['profile']))
proc.communicate(p['profile'].encode())
proc.kill()
subprocess.call([pager, orig_filename])
elif ans == 'CMD_USE_PROFILE':
if p['profile_type'] == 'INACTIVE_LOCAL':
profile_data = p['profile_data']
@@ -559,7 +578,7 @@ def activate_repo_profiles(url, profiles, complain):
attach_profile_data(aa, profile_data)
write_profile(pname)
if complain:
fname = get_profile_filename(pname)
fname = get_profile_filename_from_profile_name(pname, True)
change_profile_flags(profile_dir + fname, None, 'complain', True)
aaui.UI_Info(_('Setting %s to complain mode.') % pname)
except Exception as e:
@@ -591,7 +610,7 @@ def autodep(bin_name, pname=''):
# Create a new profile if no existing profile
if not profile_data:
profile_data = create_new_profile(pname)
file = get_profile_filename(pname)
file = get_profile_filename_from_profile_name(pname, True)
profile_data[pname][pname]['filename'] = None # will be stored in /etc/apparmor.d when saving, so it shouldn't carry the extra_profile_dir filename
attach_profile_data(aa, profile_data)
attach_profile_data(original_aa, profile_data)
@@ -691,15 +710,16 @@ def profile_exists(program):
"""Returns True if profile exists, False otherwise"""
# Check cache of profiles
if existing_profiles.get(program, False):
if active_profiles.filename_from_attachment(program):
return True
# Check the disk for profile
prof_path = get_profile_filename(program)
prof_path = get_profile_filename_from_attachment(program, True)
#print(prof_path)
if os.path.isfile(prof_path):
# Add to cache of profile
existing_profiles[program] = prof_path
return True
raise AppArmorBug('Reached strange condition in profile_exists(), please open a bugreport!')
# active_profiles[program] = prof_path
# return True
return False
def sync_profile():
@@ -972,7 +992,7 @@ def handle_children(profile, hat, root):
hat = default_hat
elif ans == 'CMD_DENY':
# As unknown hat is denied no entry for it should be made
return None
continue
elif typ == 'capability':
# If capability then we (should) have pid, profile, hat, program, mode, capability
@@ -1088,9 +1108,9 @@ def handle_children(profile, hat, root):
options += 'd'
# Define the default option
default = None
if 'p' in options and os.path.exists(get_profile_filename(exec_target)):
if 'p' in options and os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
default = 'CMD_px'
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename(exec_target))
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename_from_attachment(exec_target, True))
elif 'i' in options:
default = 'CMD_ix'
elif 'c' in options:
@@ -1104,7 +1124,7 @@ def handle_children(profile, hat, root):
parent_uses_ld_xxx = check_for_LD_XXX(profile)
sev_db.unload_variables()
sev_db.load_variables(get_profile_filename(profile))
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
severity = sev_db.rank_path(exec_target, 'x')
# Prompt portion starts
@@ -1228,7 +1248,7 @@ def handle_children(profile, hat, root):
profile_changes[pid] = '%s' % profile
# Check profile exists for px
if not os.path.exists(get_profile_filename(exec_target)):
if not os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
ynans = 'y'
if 'i' in exec_mode:
ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
@@ -1362,7 +1382,7 @@ def ask_the_questions(log_dict):
UI_SelectUpdatedRepoProfile(profile, p)
sev_db.unload_variables()
sev_db.load_variables(get_profile_filename(profile))
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
# Sorted list of hats with the profile name coming first
hats = list(filter(lambda key: key != profile, sorted(log_dict[aamode][profile].keys())))
@@ -1755,21 +1775,25 @@ def set_logfile(filename):
if filename:
logfile = filename
else:
elif 'logfiles' in cfg['settings']:
# This line can only run if the 'logfile' exists in settings, otherwise
# it will yield a Python KeyError
logfile = conf.find_first_file(cfg['settings']['logfiles']) or '/var/log/syslog'
else:
logfile = '/var/log/syslog'
if not os.path.exists(logfile):
if filename:
raise AppArmorException(_('The logfile %s does not exist. Please check the path') % logfile)
raise AppArmorException(_('The logfile %s does not exist. Please check the path.') % logfile)
else:
raise AppArmorException('Can\'t find system log "%s".' % (logfile))
raise AppArmorException('Can\'t find system log "%s". Please check permissions.' % (logfile))
elif os.path.isdir(logfile):
raise AppArmorException(_('%s is a directory. Please specify a file as logfile') % logfile)
def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
# set up variables for this pass
# transitions = hasher()
global existing_profiles
global active_profiles
global sev_db
# aa = hasher()
# profile_changes = hasher()
@@ -1786,13 +1810,13 @@ def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
if not sev_db:
sev_db = apparmor.severity.Severity(CONFDIR + '/severity.db', _('unknown'))
#print(pid)
#print(existing_profiles)
#print(active_profiles)
##if not repo_cf and cfg['repostory']['url']:
## repo_cfg = read_config('repository.conf')
## if not repo_cfg['repository'].get('enabled', False) or repo_cfg['repository]['enabled'] not in ['yes', 'no']:
## UI_ask_to_enable_repo()
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, existing_profiles, profile_dir)
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, active_profiles, profile_dir)
log = log_reader.read_log(logmark)
#read_log(logmark)
@@ -1867,13 +1891,11 @@ def save_profiles():
if aa[which][which].get('filename', False):
oldprofile = aa[which][which]['filename']
else:
oldprofile = get_profile_filename(which)
oldprofile = get_profile_filename_from_attachment(which, True)
try:
newprofile = serialize_profile_from_old_profile(aa[which], which, '')
except AttributeError:
# see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1528139
newprofile = "###\n###\n### Internal error while generating diff, please use '%s' instead\n###\n###\n" % _('View Changes b/w (C)lean profiles')
serialize_options = {}
serialize_options['METADATA'] = True
newprofile = serialize_profile(aa[which], which, serialize_options)
aaui.UI_Changes(oldprofile, newprofile, comments=True)
@@ -2085,9 +2107,29 @@ def read_profile(file, active_profile):
if profile_data and active_profile:
attach_profile_data(aa, profile_data)
attach_profile_data(original_aa, profile_data)
for profile in profile_data: # TODO: also honor hats
name = profile_data[profile][profile]['name']
attachment = profile_data[profile][profile]['attachment']
filename = profile_data[profile][profile]['filename']
if not attachment and name.startswith('/'):
active_profiles.add(filename, name, name) # use name as name and attachment
else:
active_profiles.add(filename, name, attachment)
elif profile_data:
attach_profile_data(extras, profile_data)
for profile in profile_data: # TODO: also honor hats
name = profile_data[profile][profile]['name']
attachment = profile_data[profile][profile]['attachment']
filename = profile_data[profile][profile]['filename']
if not attachment and name.startswith('/'):
extra_profiles.add(filename, name, name) # use name as name and attachment
else:
extra_profiles.add(filename, name, attachment)
def attach_profile_data(profiles, profile_data):
# Make deep copy of data to avoid changes to
@@ -2179,9 +2221,6 @@ def parse_profile_data(data, file, do_include):
if pps_set_hat_external:
profile_data[profile][hat]['external'] = True
# Profile stored
existing_profiles[profile] = file
# save profile name and filename
profile_data[profile][hat]['name'] = profile
profile_data[profile][hat]['filename'] = file
@@ -2506,6 +2545,11 @@ def parse_profile_data(data, file, do_include):
else:
raise AppArmorException(_('Syntax Error: Unknown line found in file %(file)s line %(lineno)s:\n %(line)s') % { 'file': file, 'lineno': lineno + 1, 'line': line })
if lastline:
# lastline gets merged into line (and reset to None) when reading the next line.
# If it isn't empty, this means there's something unparseable at the end of the profile
raise AppArmorException(_('Syntax Error: Unknown line found in file %(file)s line %(lineno)s:\n %(line)s') % { 'file': file, 'lineno': lineno + 1, 'line': lastline })
# Below is not required I'd say
if not do_include:
for hatglob in cfg['required_hats'].keys():
@@ -2886,7 +2930,11 @@ def serialize_profile(profile_data, name, options):
# comment.replace('\\n', '\n')
# string += comment + '\n'
prof_filename = get_profile_filename(name)
if options and options.get('is_attachment'):
prof_filename = get_profile_filename_from_attachment(name, True)
else:
prof_filename = get_profile_filename_from_profile_name(name, True)
if filelist.get(prof_filename, False):
data += write_abi(filelist[prof_filename], 0)
data += write_alias(filelist[prof_filename], 0)
@@ -2920,429 +2968,18 @@ def serialize_parse_profile_start(line, file, lineno, profile, hat, prof_data_pr
return (profile, hat, attachment, flags, in_contained_hat, correct)
def serialize_profile_from_old_profile(profile_data, name, options):
data = []
string = ''
include_metadata = False
include_flags = True
prof_filename = get_profile_filename(name)
write_filelist = deepcopy(filelist[prof_filename])
write_prof_data = deepcopy(profile_data)
# XXX profile_data / write_prof_data contain only one profile with its hats
# XXX this will explode if a file contains multiple profiles, see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1528139
# XXX fixing this needs lots of write_prof_data[hat] -> write_prof_data[profile][hat] changes (and of course also a change in the calling code)
# XXX (the better option is a full rewrite of serialize_profile_from_old_profile())
if options: # and type(options) == dict:
if options.get('METADATA', False):
include_metadata = True
if options.get('NO_FLAGS', False):
include_flags = False
if include_metadata:
string = '# Last Modified: %s\n' % time.asctime()
if (profile_data[name].get('repo', False) and
profile_data[name]['repo']['url'] and
profile_data[name]['repo']['user'] and
profile_data[name]['repo']['id']):
repo = profile_data[name]['repo']
string += '# REPOSITORY: %s %s %s\n' % (repo['url'], repo['user'], repo['id'])
elif profile_data[name]['repo']['neversubmit']:
string += '# REPOSITORY: NEVERSUBMIT\n'
if not os.path.isfile(prof_filename):
raise AppArmorException(_("Can't find existing profile to modify"))
# profiles_list = filelist[prof_filename].keys() # XXX
with open_file_read(prof_filename) as f_in:
profile = None
hat = None
write_methods = {'abi': write_abi,
'alias': write_alias,
'lvar': write_list_vars,
'include': write_includes,
'rlimit': write_rlimits,
'capability': write_capabilities,
'network': write_netdomain,
'dbus': write_dbus,
'mount': write_mount,
'signal': write_signal,
'ptrace': write_ptrace,
'pivot_root': write_pivot_root,
'unix': write_unix,
'link': write_links,
'file': write_file,
'change_profile': write_change_profile,
}
default_write_order = [ 'alias',
'lvar',
'include',
'rlimit',
'capability',
'network',
'dbus',
'mount',
'signal',
'ptrace',
'pivot_root',
'unix',
'link',
'file',
'change_profile',
]
# prof_correct = True # XXX correct?
segments = {'alias': False,
'lvar': False,
'include': False,
'rlimit': False,
'capability': False,
'network': False,
'dbus': False,
'mount': False,
'signal': True, # not handled otherwise yet
'ptrace': True, # not handled otherwise yet
'pivot_root': False,
'unix': False,
'link': False,
'file': False,
'change_profile': False,
'include_local_started': False, # unused
}
def write_prior_segments(prof_data, segments, line):
data = []
for segs in list(filter(lambda x: segments[x], segments.keys())):
depth = len(line) - len(line.lstrip())
data += write_methods[segs](prof_data, int(depth / 2))
segments[segs] = False
# delete rules from prof_data to avoid duplication (they are in data now)
if prof_data['allow'].get(segs, False):
prof_data['allow'].pop(segs)
if prof_data['deny'].get(segs, False):
prof_data['deny'].pop(segs)
if prof_data.get(segs, False):
t = type(prof_data[segs])
prof_data[segs] = t()
return data
#data.append('reading prof')
for line in f_in:
correct = True
line = line.rstrip('\n')
#data.append(' ')#data.append('read: '+line)
if RE_PROFILE_START.search(line):
(profile, hat, attachment, flags, in_contained_hat, correct) = serialize_parse_profile_start(
line, prof_filename, None, profile, hat, write_prof_data[hat]['profile'], write_prof_data[hat]['external'], correct)
if not write_prof_data[hat]['name'] == profile:
correct = False
if not write_filelist['profiles'][profile][hat] is True:
correct = False
if not write_prof_data[hat]['flags'] == flags:
correct = False
#Write the profile start
if correct:
if write_filelist:
data += write_alias(write_filelist, 0)
data += write_list_vars(write_filelist, 0)
data += write_includes(write_filelist, 0)
data.append(line)
else:
if write_prof_data[hat]['name'] == profile:
depth = len(line) - len(line.lstrip())
data += write_header(write_prof_data[name], int(depth / 2), name, False, include_flags)
elif RE_PROFILE_END.search(line):
# DUMP REMAINDER OF PROFILE
if profile:
depth = int(len(line) - len(line.lstrip()) / 2) + 1
# first write sections that were modified
#for segs in write_methods.keys():
for segs in default_write_order:
if segments[segs]:
data += write_methods[segs](write_prof_data[name], depth)
segments[segs] = False
# delete rules from write_prof_data to avoid duplication (they are in data now)
if write_prof_data[name]['allow'].get(segs, False):
write_prof_data[name]['allow'].pop(segs)
if write_prof_data[name]['deny'].get(segs, False):
write_prof_data[name]['deny'].pop(segs)
if write_prof_data[name].get(segs, False):
t = type(write_prof_data[name][segs])
write_prof_data[name][segs] = t()
# then write everything else
for segs in default_write_order:
data += write_methods[segs](write_prof_data[name], depth)
write_prof_data.pop(name)
#Append local includes
data.append(line)
if not in_contained_hat:
# Embedded hats
depth = int((len(line) - len(line.lstrip())) / 2)
pre2 = ' ' * (depth + 1)
for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
if not profile_data[hat]['external']:
data.append('')
if profile_data[hat]['profile']:
data += list(map(str, write_header(profile_data[hat], depth + 1, hat, True, include_flags)))
else:
data += list(map(str, write_header(profile_data[hat], depth + 1, '^' + hat, True, include_flags)))
data += list(map(str, write_rules(profile_data[hat], depth + 2)))
data.append('%s}' % pre2)
# External hats
for hat in list(filter(lambda x: x != name, sorted(profile_data.keys()))):
if profile_data[hat].get('external', False):
data.append('')
data += list(map(lambda x: ' %s' % x, write_piece(profile_data, depth - 1, name, name, include_flags)))
data.append(' }')
if in_contained_hat:
#Hat processed, remove it
hat = profile
in_contained_hat = False
else:
profile = None
elif CapabilityRule.match(line):
cap = CapabilityRule.parse(line)
if write_prof_data[hat]['capability'].is_covered(cap, True, True):
if not segments['capability'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['capability'] = True
write_prof_data[hat]['capability'].delete(cap)
data.append(line)
else:
# To-Do
pass
elif RE_PROFILE_LINK.search(line):
matches = RE_PROFILE_LINK.search(line).groups()
audit = False
if matches[0]:
audit = True
allow = 'allow'
if matches[1] and matches[1].strip() == 'deny':
allow = 'deny'
subset = matches[3]
link = strip_quotes(matches[6])
value = strip_quotes(matches[7])
if not write_prof_data[hat][allow]['link'][link]['to'] == value:
correct = False
if not write_prof_data[hat][allow]['link'][link]['mode'] & apparmor.aamode.AA_MAY_LINK:
correct = False
if subset and not write_prof_data[hat][allow]['link'][link]['mode'] & apparmor.aamode.AA_LINK_SUBSET:
correct = False
if audit and not write_prof_data[hat][allow]['link'][link]['audit'] & apparmor.aamode.AA_LINK_SUBSET:
correct = False
if correct:
if not segments['link'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['link'] = True
write_prof_data[hat][allow]['link'].pop(link)
data.append(line)
else:
# To-Do
pass
elif ChangeProfileRule.match(line):
change_profile_obj = ChangeProfileRule.parse(line)
if write_prof_data[hat]['change_profile'].is_covered(change_profile_obj, True, True):
if not segments['change_profile'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['change_profile'] = True
write_prof_data[hat]['change_profile'].delete(change_profile_obj)
data.append(line)
elif RE_PROFILE_ALIAS.search(line):
matches = RE_PROFILE_ALIAS.search(line).groups()
from_name = strip_quotes(matches[0])
to_name = strip_quotes(matches[1])
if profile:
if not write_prof_data[hat]['alias'][from_name] == to_name:
correct = False
else:
if not write_filelist['alias'][from_name] == to_name:
correct = False
if correct:
if not segments['alias'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['alias'] = True
if profile:
write_prof_data[hat]['alias'].pop(from_name)
else:
write_filelist['alias'].pop(from_name)
data.append(line)
else:
#To-Do
pass
elif RlimitRule.match(line):
rlimit_obj = RlimitRule.parse(line)
if write_prof_data[hat]['rlimit'].is_covered(rlimit_obj, True, True):
if not segments['rlimit'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['rlimit'] = True
write_prof_data[hat]['rlimit'].delete(rlimit_obj)
data.append(line)
else:
#To-Do
pass
elif RE_PROFILE_BOOLEAN.search(line):
matches = RE_PROFILE_BOOLEAN.search(line).groups()
bool_var = matches[0]
value = matches[1]
if not write_prof_data[hat]['lvar'][bool_var] == value:
correct = False
if correct:
if not segments['lvar'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['lvar'] = True
write_prof_data[hat]['lvar'].pop(bool_var)
data.append(line)
else:
#To-Do
pass
elif RE_PROFILE_VARIABLE.search(line):
matches = RE_PROFILE_VARIABLE.search(line).groups()
list_var = strip_quotes(matches[0])
var_operation = matches[1]
value = strip_quotes(matches[2])
var_set = hasher()
if var_operation == '+=':
correct = False # adding proper support for "add to variable" needs big changes
# (like storing a variable's "history" - where it was initially defined and what got added where)
# so just skip any comparison and assume a non-match
elif profile:
store_list_var(var_set, list_var, value, var_operation, prof_filename)
if not var_set[list_var] == write_prof_data['lvar'].get(list_var, False):
correct = False
else:
store_list_var(var_set, list_var, value, var_operation, prof_filename)
if not var_set[list_var] == write_filelist['lvar'].get(list_var, False):
correct = False
if correct:
if not segments['lvar'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['lvar'] = True
if profile:
write_prof_data[hat]['lvar'].pop(list_var)
else:
write_filelist['lvar'].pop(list_var)
data.append(line)
else:
#To-Do
pass
elif re_match_include(line):
include_name = re_match_include(line)
if profile:
if write_prof_data[hat]['include'].get(include_name, False):
if not segments['include'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['include'] = True
write_prof_data[hat]['include'].pop(include_name)
data.append(line)
else:
if write_filelist['include'].get(include_name, False):
write_filelist['include'].pop(include_name)
data.append(line)
elif NetworkRule.match(line):
network_obj = NetworkRule.parse(line)
if write_prof_data[hat]['network'].is_covered(network_obj, True, True):
if not segments['network'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['network'] = True
write_prof_data[hat]['network'].delete(network_obj)
data.append(line)
elif RE_PROFILE_CHANGE_HAT.search(line):
# "^hat," declarations are no longer supported, ignore them and don't write out the line
# (parse_profile_data() already prints a warning about that)
pass
elif RE_PROFILE_HAT_DEF.search(line):
matches = RE_PROFILE_HAT_DEF.search(line)
in_contained_hat = True
hat = matches.group('hat')
hat = strip_quotes(hat)
flags = matches.group('flags')
if not write_prof_data[hat]['flags'] == flags:
correct = False
if not write_filelist['profile'][profile][hat]:
correct = False
if correct:
data.append(line)
else:
#To-Do
pass
elif FileRule.match(line):
# leading permissions could look like a keyword, therefore handle file rules after everything else
file_obj = FileRule.parse(line)
if write_prof_data[hat]['file'].is_covered(file_obj, True, True):
if not segments['file'] and True in segments.values():
data += write_prior_segments(write_prof_data[name], segments, line)
segments['file'] = True
write_prof_data[hat]['file'].delete(file_obj)
data.append(line)
else:
#To-Do
pass
else:
if correct:
data.append(line)
else:
#To-Do
pass
# data.append('prof done')
# if write_filelist:
# data += write_alias(write_filelist, 0)
# data += write_list_vars(write_filelist, 0)
# data += write_includes(write_filelist, 0)
# data.append('from filelist over')
# data += write_piece(write_prof_data, 0, name, name, include_flags)
string += '\n'.join(data)
return string + '\n'
def write_profile_ui_feedback(profile):
def write_profile_ui_feedback(profile, is_attachment=False):
aaui.UI_Info(_('Writing updated profile for %s.') % profile)
write_profile(profile)
write_profile(profile, is_attachment)
def write_profile(profile):
def write_profile(profile, is_attachment=False):
prof_filename = None
if aa[profile][profile].get('filename', False):
prof_filename = aa[profile][profile]['filename']
elif is_attachment:
prof_filename = get_profile_filename_from_attachment(profile, True)
else:
prof_filename = get_profile_filename(profile)
prof_filename = get_profile_filename_from_profile_name(profile, True)
newprof = tempfile.NamedTemporaryFile('w', suffix='~', delete=False, dir=profile_dir)
if os.path.exists(prof_filename):
@@ -3352,8 +2989,7 @@ def write_profile(profile):
#os.chmod(newprof.name, permission_600)
pass
serialize_options = {}
serialize_options['METADATA'] = True
serialize_options = {'METADATA': True, 'is_attachment': is_attachment}
profile_string = serialize_profile(aa[profile], profile, serialize_options)
newprof.write(profile_string)
@@ -3476,7 +3112,7 @@ def reload_base(bin_path):
if not check_for_apparmor():
return None
prof_filename = get_profile_filename(bin_path)
prof_filename = get_profile_filename_from_profile_name(bin_path, True)
# XXX use reload_profile() from tools.py instead (and don't hide output in /dev/null)
subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" % (prof_filename, parser, profile_dir), shell=True)

View File

@@ -1,6 +1,6 @@
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
# Copyright (C) 2015-2016 Christian Boltz <apparmor@cboltz.de>
# Copyright (C) 2015-2018 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
@@ -12,7 +12,6 @@
# GNU General Public License for more details.
#
# ----------------------------------------------------------------------
import os
import re
import sys
import time
@@ -43,11 +42,11 @@ class ReadLog:
# used to pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing
RE_LOG_ALL = re.compile('(' + '|'.join(RE_log_parts) + ')')
def __init__(self, pid, filename, existing_profiles, profile_dir):
def __init__(self, pid, filename, active_profiles, profile_dir):
self.filename = filename
self.profile_dir = profile_dir
self.pid = pid
self.existing_profiles = existing_profiles
self.active_profiles = active_profiles
self.log = []
self.debug_logger = DebugLogger('ReadLog')
self.LOG = None
@@ -446,24 +445,7 @@ class ReadLog:
def profile_exists(self, program):
"""Returns True if profile exists, False otherwise"""
# Check cache of profiles
if self.existing_profiles.get(program, False):
if self.active_profiles.filename_from_profile_name(program):
return True
# Check the disk for profile
prof_path = self.get_profile_filename(program)
#print(prof_path)
if os.path.isfile(prof_path):
# Add to cache of profile
self.existing_profiles[program] = prof_path
return True
return False
def get_profile_filename(self, profile):
"""Returns the full profile name"""
if profile.startswith('/'):
# Remove leading /
profile = profile[1:]
else:
profile = "profile_" + profile
profile = profile.replace('/', '.')
full_profilename = self.profile_dir + '/' + profile
return full_profilename
return False

View File

@@ -0,0 +1,73 @@
# ----------------------------------------------------------------------
# Copyright (C) 2018 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 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# ----------------------------------------------------------------------
from apparmor.aare import AARE
from apparmor.common import AppArmorBug, AppArmorException
# setup module translations
from apparmor.translations import init_translation
_ = init_translation()
class ProfileList:
''' Stores the list of profiles (both name and attachment) and in which files they live '''
def __init__(self):
self.profile_names = {} # profile name -> filename
self.attachments = {} # attachment -> filename
self.attachments_AARE = {} # AARE(attachment) -> filename
def add(self, filename, profile_name, attachment):
''' Add the given profile and attachment to the list '''
if not filename:
raise AppArmorBug('Empty filename given to ProfileList')
if not profile_name and not attachment:
raise AppArmorBug('Neither profile name or attachment given')
if profile_name in self.profile_names:
raise AppArmorException(_('Profile %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': profile_name, 'filename': filename, 'filename2': self.profile_names[profile_name]}))
if attachment in self.attachments:
raise AppArmorException(_('Profile for %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': attachment, 'filename': filename, 'filename2': self.attachments[attachment]}))
if profile_name:
self.profile_names[profile_name] = filename
if attachment:
self.attachments[attachment] = filename
self.attachments_AARE[attachment] = AARE(attachment, True)
def filename_from_profile_name(self, name):
''' Return profile filename for the given profile name, or None '''
return self.profile_names.get(name, None)
def filename_from_attachment(self, attachment):
''' Return profile filename for the given attachment/executable path, or None '''
if not attachment.startswith( ('/', '@', '{') ):
raise AppArmorBug('Called filename_from_attachment with non-path attachment: %s' % attachment)
# plain path
if self.attachments.get(attachment):
return self.attachments[attachment]
# try AARE matches to cover profile names with alternations and wildcards
for path in self.attachments.keys():
if self.attachments_AARE[path].match(attachment):
return self.attachments[path] # XXX this returns the first match, not necessarily the best one
return None # nothing found

View File

@@ -26,8 +26,8 @@ _ = init_translation()
network_domain_keywords = [ 'unspec', 'unix', 'inet', 'ax25', 'ipx', 'appletalk', 'netrom', 'bridge', 'atmpvc', 'x25', 'inet6',
'rose', 'netbeui', 'security', 'key', 'netlink', 'packet', 'ash', 'econet', 'atmsvc', 'rds', 'sna',
'irda', 'pppox', 'wanpipe', 'llc', 'can', 'tipc', 'bluetooth', 'iucv', 'rxrpc', 'isdn', 'phonet',
'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'mpls', 'ib', 'kcm', 'smc' ]
'irda', 'pppox', 'wanpipe', 'llc', 'ib', 'mpls', 'can', 'tipc', 'bluetooth', 'iucv', 'rxrpc', 'isdn',
'phonet', 'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'kcm', 'qipcrtr', 'smc', 'xdp' ]
network_type_keywords = ['stream', 'dgram', 'seqpacket', 'rdm', 'raw', 'packet']
network_protocol_keywords = ['tcp', 'udp', 'icmp']

View File

@@ -1,5 +1,6 @@
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
# Copyright (C) 2015-2018 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
@@ -66,12 +67,12 @@ class aa_tools:
profile = fq_path
else:
program = fq_path
profile = apparmor.get_profile_filename(fq_path)
profile = apparmor.get_profile_filename_from_attachment(fq_path, True)
else:
which = apparmor.which(p)
if which is not None:
program = apparmor.get_full_path(which)
profile = apparmor.get_profile_filename(program)
profile = apparmor.get_profile_filename_from_attachment(program, True)
elif os.path.exists(os.path.join(apparmor.profile_dir, p)):
program = None
profile = apparmor.get_full_path(os.path.join(apparmor.profile_dir, p)).strip()
@@ -190,7 +191,7 @@ class aa_tools:
apparmor.check_qualifiers(program)
if os.path.exists(apparmor.get_profile_filename(program)) and not self.force:
if os.path.exists(apparmor.get_profile_filename_from_attachment(program, True)) and not self.force:
aaui.UI_Info(_('Profile for %s already exists - skipping.') % program)
else:
apparmor.autodep(program)
@@ -198,7 +199,7 @@ class aa_tools:
apparmor.reload(program)
def clean_profile(self, program):
filename = apparmor.get_profile_filename(program)
filename = apparmor.get_profile_filename_from_attachment(program, True)
import apparmor.cleanprofile as cleanprofile
prof = cleanprofile.Prof(filename)
cleanprof = cleanprofile.CleanProf(True, prof, prof)
@@ -220,14 +221,14 @@ class aa_tools:
while ans != 'CMD_SAVE_CHANGES':
ans, arg = q.promptUser()
if ans == 'CMD_SAVE_CHANGES':
apparmor.write_profile_ui_feedback(program)
apparmor.write_profile_ui_feedback(program, True)
self.reload_profile(filename)
elif ans == 'CMD_VIEW_CHANGES':
#oldprofile = apparmor.serialize_profile(apparmor.original_aa[program], program, '')
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, '')
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, {'is_attachment': True})
aaui.UI_Changes(filename, newprofile, comments=True)
else:
apparmor.write_profile_ui_feedback(program)
apparmor.write_profile_ui_feedback(program, True)
self.reload_profile(filename)
else:
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.') % program)

View File

@@ -5,7 +5,7 @@ import sys
if len(sys.argv) != 2:
raise Exception('wrong number of arguments in fake_ldd')
if sys.argv[1] == '/AATest/bin/bash' or sys.argv[1] == '/bin/bash':
if sys.argv[1] in ['/AATest/bin/bash', '/bin/bash', '/usr/bin/bash']:
print(' linux-vdso.so.1 (0x00007ffcf97f4000)')
print(' libreadline.so.6 => /AATest/lib64/libreadline.so.6 (0x00007f2c41324000)')
print(' libtinfo.so.6 => /AATest/lib64/libtinfo.so.6 (0x00007f2c410f9000)')

View File

@@ -135,6 +135,9 @@ class AaTest_create_new_profile(AATest):
apparmor.aa.load_include('abstractions/bash')
exp_interpreter_path, exp_abstraction = expected
# damn symlinks!
if exp_interpreter_path:
exp_interpreter_path = os.path.realpath(exp_interpreter_path)
program = self.writeTmpfile('script', params)
profile = create_new_profile(program)
@@ -178,11 +181,8 @@ class AaTest_get_interpreter_and_abstraction(AATest):
interpreter_path, abstraction = get_interpreter_and_abstraction(program)
# damn symlinks!
if exp_interpreter_path and os.path.islink(exp_interpreter_path):
dirname = os.path.dirname(exp_interpreter_path)
exp_interpreter_path = os.readlink(exp_interpreter_path)
if not exp_interpreter_path.startswith('/'):
exp_interpreter_path = os.path.join(dirname, exp_interpreter_path)
if exp_interpreter_path:
exp_interpreter_path = os.path.realpath(exp_interpreter_path)
self.assertEqual(interpreter_path, exp_interpreter_path)
self.assertEqual(abstraction, exp_abstraction)

View File

@@ -1,7 +1,7 @@
#! /usr/bin/python3
# ------------------------------------------------------------------
#
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
# Copyright (C) 2015-2018 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
@@ -17,6 +17,7 @@ from apparmor.common import open_file_read
import apparmor.aa
from apparmor.logparser import ReadLog
from apparmor.profile_list import ProfileList
class TestLibapparmorTestMulti(AATest):
'''Parse all libraries/libapparmor/testsuite/test_multi tests and compare the result with the *.out files'''
@@ -222,9 +223,15 @@ class TestLogToProfile(AATest):
if '//' in profile:
profile, hat = profile.split('//')
apparmor.aa.existing_profiles = {profile: profile_dummy_file}
apparmor.aa.active_profiles = ProfileList()
log_reader = ReadLog(dict(), logfile, apparmor.aa.existing_profiles, '')
# optional for now, might be needed one day
# if profile.startswith('/'):
# apparmor.aa.active_profiles.add(profile_dummy_file, profile, profile)
# else:
apparmor.aa.active_profiles.add(profile_dummy_file, profile, '')
log_reader = ReadLog(dict(), logfile, apparmor.aa.active_profiles, '')
log = log_reader.read_log('')
for root in log:

View File

@@ -17,9 +17,9 @@ import unittest
from collections import namedtuple
from common_test import AATest, setup_all_loops
from apparmor.rule.network import NetworkRule, NetworkRuleset
from apparmor.rule.network import NetworkRule, NetworkRuleset, network_domain_keywords
from apparmor.rule import BaseRule
from apparmor.common import AppArmorException, AppArmorBug
from apparmor.common import AppArmorException, AppArmorBug, cmd
from apparmor.logparser import ReadLog
from apparmor.translations import init_translation
_ = init_translation()
@@ -27,6 +27,30 @@ _ = init_translation()
exp = namedtuple('exp', ['audit', 'allow_keyword', 'deny', 'comment',
'domain', 'all_domains', 'type_or_protocol', 'all_type_or_protocols'])
# --- check if the keyword list is up to date --- #
class NetworkKeywordsTest(AATest):
def test_network_keyword_list(self):
rc, output = cmd('../../common/list_af_names.sh')
self.assertEqual(rc, 0)
af_names = []
af_pairs = output.replace('AF_', '').strip().lower().split(",")
for af_pair in af_pairs:
af_name = af_pair.lstrip().split(" ")[0]
# skip max af name definition
if len(af_name) > 0 and af_name != "max":
af_names.append(af_name)
missing_af_names = []
for keyword in af_names:
if keyword not in network_domain_keywords:
# keywords missing in the system are ok (= older kernel), but network_domain_keywords needs to have the full list
missing_af_names.append(keyword)
self.assertEqual(missing_af_names, [], 'Missing af_names in NetworkRule network_domain_keywords. This test is likely running '
'on an newer kernel and will require updating the list of network domain keywords in utils/apparmor/rule/network.py')
# --- tests for single NetworkRule --- #
class NetworkTest(AATest):

View File

@@ -40,11 +40,6 @@ skip_startswith = (
# testcases that should raise an exception, but don't
exception_not_raised = [
# most abi/bad_* aren't detected as bad by the basic implementation in the tools
'abi/bad_1.sd',
'abi/bad_2.sd',
'abi/bad_3.sd',
'abi/bad_4.sd',
'abi/bad_5.sd',
'abi/bad_10.sd',
'abi/bad_11.sd',
'abi/bad_12.sd',
@@ -155,13 +150,9 @@ exception_not_raised = [
'unix/bad_regex_04.sd',
'unix/bad_shutdown_1.sd',
'unix/bad_shutdown_2.sd',
'vars/boolean/boolean_bad_1.sd',
'vars/boolean/boolean_bad_2.sd',
'vars/boolean/boolean_bad_3.sd',
'vars/boolean/boolean_bad_4.sd',
'vars/boolean/boolean_bad_6.sd',
'vars/boolean/boolean_bad_7.sd',
'vars/boolean/boolean_bad_8.sd',
'vars/vars_bad_3.sd',
'vars/vars_bad_4.sd',
'vars/vars_bad_5.sd',
@@ -200,7 +191,6 @@ exception_not_raised = [
'vars/vars_recursion_2.sd',
'vars/vars_recursion_3.sd',
'vars/vars_recursion_4.sd',
'vars/vars_simple_assignment_10.sd',
'vars/vars_simple_assignment_3.sd',
'vars/vars_simple_assignment_8.sd',
'vars/vars_simple_assignment_9.sd',

View File

@@ -0,0 +1,114 @@
#! /usr/bin/python3
# ------------------------------------------------------------------
#
# Copyright (C) 2018 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 unittest
from common_test import AATest, setup_all_loops
from apparmor.common import AppArmorBug, AppArmorException
from apparmor.profile_list import ProfileList
class TestAdd(AATest):
def AASetup(self):
self.pl = ProfileList()
def testEmpty(self):
self.assertEqual(self.pl.profile_names, {})
self.assertEqual(self.pl.attachments, {})
def testAdd_1(self):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
def testAdd_2(self):
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
self.assertEqual(self.pl.profile_names, {})
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
def testAdd_3(self):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.attachments, {})
def testAddError_1(self):
with self.assertRaises(AppArmorBug):
self.pl.add('', 'foo', '/bin/foo') # no filename
def testAddError_2(self):
with self.assertRaises(AppArmorBug):
self.pl.add('/etc/apparmor.d/bin.foo', None, None) # neither attachment or profile name
def testAddError_twice_1(self):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
with self.assertRaises(AppArmorException):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
def testAddError_twice_2(self):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
with self.assertRaises(AppArmorException):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
def testAddError_twice_3(self):
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
with self.assertRaises(AppArmorException):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
def testAddError_twice_4(self):
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
with self.assertRaises(AppArmorException):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
def testAddError_twice_5(self):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
with self.assertRaises(AppArmorException):
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
class TestFilename_from_profile_name(AATest):
tests = [
('foo', '/etc/apparmor.d/bin.foo'),
('/bin/foo', None),
('bar', None),
]
def AASetup(self):
self.pl = ProfileList()
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
def _run_test(self, params, expected):
self.assertEqual(self.pl.filename_from_profile_name(params), expected)
class TestFilename_from_attachment(AATest):
tests = [
('/bin/foo', '/etc/apparmor.d/bin.foo'),
('/bin/baz', '/etc/apparmor.d/bin.baz'),
('/bin/foobar', '/etc/apparmor.d/bin.foobar'),
('@{foo}', None), # XXX variables not supported yet (and @{foo} isn't defined in this test)
('/bin/404', None),
]
def AASetup(self):
self.pl = ProfileList()
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
self.pl.add('/etc/apparmor.d/bin.baz', 'baz', '/bin/ba*')
self.pl.add('/etc/apparmor.d/bin.foobar', 'foobar', '/bin/foo{bar,baz}')
def _run_test(self, params, expected):
self.assertEqual(self.pl.filename_from_attachment(params), expected)
def test_non_path_attachment(self):
with self.assertRaises(AppArmorBug):
self.pl.filename_from_attachment('foo')
setup_all_loops(__name__)
if __name__ == '__main__':
unittest.main(verbosity=1)