2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 14:25:52 +00:00

Compare commits

..

272 Commits

Author SHA1 Message Date
Christian Boltz
d4fef5b63f profiles: adjust abstractions/python for python 3.7
Python 3.7 was released yesterday - and to make the abstraction
future-proof, also cover 3.8 and 3.9 in advance ;-)

(cherry picked from commit 01f41fbff8)

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
PR: https://gitlab.com/apparmor/apparmor/merge_requests/139
2018-06-29 11:30:00 -07:00
Christian Boltz
3ae5be33e2 profiles: update samba profiles
- allow smbd to load new shared libraries
- allow winbindd to read and write new kerberos cache location

Based on a patch by "Samuel Cabrero" <scabrero@suse.com>

(cherry picked from commit 23b5f29b80)

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

Acked-by: Steve Beattie <steve@nxnw.org>
PR: https://gitlab.com/apparmor/apparmor/merge_requests/121
2018-05-09 14:19:15 -07:00
Christian Boltz
8c2371a7cd utils: fix writing alias rules
write_pair() ignored the 'tail' parameter, which resulted in writing
invalid alias rules (without the trailing comma).

Also add an alias to test/cleanprof.* to ensure it doesn't break again.

(cherry picked from commit ae4ab62855)

Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
PR: https://gitlab.com/apparmor/apparmor/merge_requests/119
2018-05-08 08:08:55 -07:00
Christian Boltz
43285d69fe utils: fix writing "link subset" rules
Writing a "link subset" rule missed a space, which resulted in something
like
  link subset/foo -> /bar,

Also add a test rule to tests/cleanprof.* to ensure this doesn't break
again.

[Fixed up conflicts in cleanpprof_test.in and .out -- @smb]

(cherry picked from commit 514535608f)

Acked-by: Steve Beattie <steve@nxnw.org>
PR: https://gitlab.com/apparmor/apparmor/merge_requests/117
2018-05-06 23:28:19 -07:00
Steve Beattie
e3e01943d4 mount regression test: convert mount test to use MS_NODEV
The mount regression test passes MS_MANDLOCK to the mount(2) syscall in
the test program. When the kernel is configured without
CONFIG_MANDATORY_FILE_LOCKING set, attempting to mount a filesystem with
this option always fails with EPERM. To fix, convert the test program to
use the MS_NODEV option instead.

(cherry picked from commit 49ba6af2bf)

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>

Bug: https://bugs.launchpad.net/apparmor/+bug/1765025
PR: https://gitlab.com/apparmor/apparmor/merge_requests/109
2018-04-30 13:42:35 -07:00
John Johansen
3f657164f2 Merge branch 'cboltz-dovecot-config' into 'master'
dovecot/config: allow dac_read_search and reading ssl-parameters.dat

See merge request apparmor/apparmor!95

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


(cherry picked from commit 5d973c2657)

c4e60719 dovecot/config: allow dac_read_search and reading ssl-parameters.dat
2018-04-14 21:24:54 +00:00
Christian Boltz
f5c5b80c44 Merge branch 'cboltz-dovecot-profiles' into 'master'
Dovecot profile updates

See merge request apparmor/apparmor!90

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

(cherry picked from commit 6b78daf25b)

36bdd6ea add dovecot/stats profile, and allow dovecot to run it
26a8b722 allow dovecot/auth to write /run/dovecot/old-stats-user
2018-04-13 13:57:46 +00:00
Christian Boltz
3cdc2a4ad0 Merge branch 'master' into 'master'
Fix typo in apparmor_parser.pod

See merge request apparmor/apparmor!85

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

(cherry picked from commit 47da50b7e6)

50ee50f9 Fix typo in apparmor_parser.pod
2018-03-26 19:51:24 +00:00
Christian Boltz
1614db2e78 Merge branch 'cboltz-fix-make-C-profiles' into 'master'
Fix $(PWD) when using "make -C profiles"

See merge request apparmor/apparmor!80

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

(cherry picked from commit 14096cb3a7)

20893382 Fix $(PWD) when using "make -C profiles"
2018-03-18 18:29:25 +00:00
Christian Boltz
f59f6052a2 Merge branch 'cboltz-skip-git-dir' into 'master'
ignore .git in is_skippable_dir()

See merge request apparmor/apparmor!77

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

(cherry picked from commit 3b5683be29)

f9eb3fea ignore .git in is_skippable_dir()
2018-03-16 21:36:50 +00:00
Steve Beattie
6cf7ef9599 mlmmj-sub: fix moderated subscription
Merge branch 'cboltz-mlmmj-sub' into 'master'

See merge request apparmor/apparmor!70

Acked-by: Steve Beattie <steve@nxnw.org>

(cherry picked from commit 41b6182019)

8ef7b594 mlmmj-sub: fix moderated subscription
2018-02-22 23:06:52 +00:00
Christian Boltz
eb32ca1a86 Merge branch 'cboltz-notify-dbus-env' into 'master'
set DBUS_SESSION_BUS_ADDRESS, needed by notify-send

See merge request apparmor/apparmor!53


Acked-by: intrigeri <intrigeri@debian.org> for 2.9..master

(cherry picked from commit 0eefeeb0e7)

cb5cdf26 set DBUS_SESSION_BUS_ADDRESS, needed by notify-send
2018-02-17 16:04:09 +00:00
Christian Boltz
2d7b191575 Merge branch 'fix-nvidia-dir' into 'master'
Allow to create .nv directory

See merge request apparmor/apparmor!69

Acked-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.9..master

(cherry picked from commit 21b0d14ea4)

11e7dab9 Allow to create .nv directory
2018-02-17 15:59:24 +00:00
Christian Boltz
c25c88d06c Merge branch 'cboltz-ntpd' into 'master'
allow access to ntp clockstats

See merge request apparmor/apparmor!54

(cherry picked from commit 85f8cace12)

1b58f226 allow access to ntp clockstats
2018-01-23 23:03:16 +00:00
Christian Boltz
e37782efcd Merge branch 'master' into 'master'
abstractions/gnupg: allow pubring.kbx

See merge request apparmor/apparmor!58

Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.9..trunk

(cherry picked from commit e1929298ac)

8fc3dcb3 abstractions/gnupg: allow pubring.kbx
2018-01-20 23:00:20 +00:00
John Johansen
00d9997cdd aa-decode: add the ability to support PROCTITLE string
buglink: https://bugs.launchpad.net/apparmor/+bug/1736841

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit 3afbfed9ee)
2017-12-24 00:27:39 -08:00
John Johansen
728a622df1 profile: fix syslog-ng startup for some configurations
buglink: https://bugs.launchpad.net/bugs/1739909

Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from commit e55583ff27)
2017-12-24 00:27:30 -08:00
John Johansen
1088961df8 Merge branch 'cboltz-netstat' into 'master'
netstat: allow capability sys_ptrace,

See merge request apparmor/apparmor!46

(cherry picked from commit a3693f56f3)

81ca52d9 netstat: allow capability sys_ptrace,
2017-12-22 21:09:15 +00:00
John Johansen
eaaf23a29c Merge branch 'cboltz-xauth' into 'master'
abstractions/X: add another location for .Xauthority

See merge request apparmor/apparmor!39

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


(cherry picked from commit bcfb735b9a)

bb96e38a abstractions/X: add another location for .Xauthority
2017-12-22 20:21:58 +00:00
John Johansen
39167593ea Merge branch 'cboltz-dovecot' into 'master'
Update /usr/lib/dovecot/* profiles

See merge request apparmor/apparmor!42

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


(cherry picked from commit f8b208ee80)

06928db1 Update /usr/lib/dovecot/* profiles
2017-12-22 20:20:56 +00:00
Christian Boltz
1a35611abc Merge branch 'fix-pulse-config' into 'master'
Fix local pulseaudio config file access

See merge request apparmor/apparmor!38


Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.9..trunk

(cherry picked from commit 6713f9d94a)

f73627cb Fix local pulseaudio config file access
2017-12-17 16:20:26 +00:00
Christian Boltz
bfcb7f8df1 Merge branch 'dovecot-signals' into 'master'
Fix signal sending for usr.sbin.dovecot

See merge request apparmor/apparmor!36

Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.9..trunk

(cherry picked from commit 6db30f8faf)

9f24650e Fix signal sending for usr.sbin.dovecot
2017-12-16 17:27:20 +00:00
Tyler Hicks
93336a5d93 Merge branch 'exit-from-Makefile-shell-snippets-2.9' into 'apparmor-2.9'
[2.9] parser, utils: Exit from Makefile shell snippets

See merge request apparmor/apparmor!30

Acked-by: Christian Boltz <apparmor@cboltz.de>
2017-12-05 18:46:29 +00:00
Tyler Hicks
29c418ae66 parser, utils: Exit from Makefile shell snippets
Exit rather than returning from shell snippets in Makefiles. It is
reported that returning causes the following error message with bash:

 /bin/sh: line 4: return: can only `return' from a function or sourced script

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Christian Boltz <apparmor@cboltz.de>
2017-12-05 17:56:23 +00:00
Steve Beattie
027e9ce7c9 dovecot: allow capability dac_read_search
Merge branch 'cboltz-dovecot-caps' into 'master'

See merge request 
https://gitlab.com/apparmor/apparmor/merge_requests/16

(cherry picked from commit ca983811fb)

4ef505a6 dovecot: allow capability dac_read_search
2017-12-01 21:21:03 +00:00
Christian Boltz
22fb1dbf08 Merge branch 'cboltz-remove-unknown-newline' into 'master'
Don't print a literal '\n' in aa-remove-unknown help

See merge request apparmor/apparmor!21

Acked-by: Tyler Hicks tyhicks@canonical.com for 2.9..trunk

(cherry picked from commit 3d40bc6f23)

4d4228d1 Don't print a literal '\n' in aa-remove-unknown help
2017-12-01 10:10:33 +00:00
Christian Boltz
4dd366c9c3 Merge branch 'cboltz-dovecot-auth' into 'master'
allow dac_read_search and dac_override for dovecot/auth

See merge request apparmor/apparmor!14


Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10, 2.11 and trunk

(cherry picked from commit 42bd81df01)

6f6b3c57 allow dac_read_search and dac_override for dovecot/auth
2017-11-27 21:39:20 +00:00
Christian Boltz
800cc21950 Merge branch 'patch-1' into 'master'
Allow to read pulseaudio config subdirectories

See merge request apparmor/apparmor!12


Acked-by: Christian Boltz <apparmor@cboltz.de> for 2.9, 2.10, 2.11 and trunk

(cherry picked from commit 4b8b08562a)

9658471d Allow to read pulseaudio config subdirectories
2017-11-18 17:27:37 +00:00
Steve Beattie
c498117fbf git conversion: move .bzrignore to .gitignore
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
2017-10-27 22:46:04 -07:00
intrigeri
23868e3eb0 profiles: allow OpenAL HRTF support in audio abstraction
Merge from trunk commit 3726

The files are "head-related transfer function" data sets, used by
OpenAL for better spatialization of sounds when headphones are detected.

Acked-by: Steve Beattie <steve@nxnw.org>

Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874665
2017-10-26 10:31:35 -07:00
Christian Boltz
9b70d50162 Allow reading /etc/netconfig in abstractions/nameservice
/etc/netconfig is required by the tirpc library which nscd and several
other programs use.

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


Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10, 2.11 and trunk
2017-10-20 22:56:21 +02:00
John Johansen
da132a75fb Bump release version to 2.9.5
Signed-off-by: John Johansen <john.johansen@canonical.com>
2017-10-18 22:55:54 -07:00
John Johansen
3aea5913bf Fix af_unix downgrade of network rules
with unix rules we output a downgraded rule compatible with network rules
so that policy will work on kernels that support network socket controls
but not the extended af_unix rules

however this is currently broken if the socket type is left unspecified
(initialized to -1), resulting in denials for kernels that don't support
the extended af_unix rules.

cherry-pick: lp:apparmor r3700
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: timeout
2017-10-18 14:47:41 -07:00
Christian Boltz
6080d9b619 Allow /var/run/dovecot/login-master-notify* in dovecot imap-login profiles
Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.11, 2.10 and 2.9.
2017-09-28 17:49:14 +02:00
Christian Boltz
d62aaf0e1a Merge updated traceroute profile into 2.10 and 2.9 branch
References: https://bugzilla.opensuse.org/show_bug.cgi?id=1057900


------------------------------------------------------------
revno: 3690 [merge]
committer: Steve Beattie <sbeattie@ubuntu.com>
branch nick: apparmor
timestamp: Wed 2017-08-09 08:57:36 -0700
message:
  traceroute profile: support TCP SYN for probes, quite net_admin request
  
  Merge from Vincas Dargis, approved by intrigeri.
  fix traceroute denies in tcp mode
  
  Acked-by: Steve Beattie <steve@nxnw.org>
------------------------------------------------------------


Backport to 2.10 and 2.9 branch

Acked-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-09-12 23:25:37 +02:00
Christian Boltz
051f68a662 abstractions/freedesktop.org: support /usr/local/applications; support subdirs of applications folder
Merge request by Cameron Norman 2015-06-07
https://code.launchpad.net/~cameronnemo/apparmor/abstraction-fdo-applications-fixups/+merge/261336

Acked-by: Christian Boltz <apparmor@cboltz.de> for trunk, 2.11, 2.10 and 2.9
2017-09-10 12:28:54 +02:00
Christian Boltz
85881a877e Samba profile updates for ActiveDirectory / Kerberos
The Samba package used by the INVIS server (based on openSUSE) needs
some additional Samba permissions for the added ActiveDirectory /
Kerberos support.

As discussed with Seth, add /var/lib/sss/mc/initgroups read permissions
to abstractions/nameservice instead of only to the smbd profile because
it's probably needed by more than just Samba if someone uses sss.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10, 2.11 and trunk.
2017-08-29 13:32:57 +02:00
Christian Boltz
05de7e693e update some Postfix profiles
- change abstractions/postfix-common to allow /etc/postfix/*.db k
- add several permissions to postfix/error, postfix/lmtp and postfix/pipe
- remove superfluous abstractions/kerberosclient from all postfix
  profiles - it's included via abstractions/nameservice


Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10, 2.11 and trunk
2017-08-22 12:45:14 +02:00
Christian Boltz
9c36523ca0 remove test_multi unconfined-change_hat.profile from 2.10 and 2.9 branch
2.10 branch r3387 and 2.9 branch r3052 (Ignore change_hat events
with error=-1 and "unconfined can not change_hat") accidently added
unconfined-change_hat.profile to the test_multi directory.

2.9 and 2.10 don't support the test_multi *.profile files and error out
in the tests saying "Found unknown file unconfined-change_hat.profile",
therefore delete this file.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-07-31 21:39:17 +02:00
Jamie Strandboge
8b3c98e044 update aa-status.pod for updated podchecker
Bug-Ubuntu: https://launchpad.net/bugs/1707614

Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2017-07-31 10:23:52 -05:00
Jamie Strandboge
ecab50f62a Adjust python abstraction for python3.6
Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2017-07-26 15:13:24 -05:00
Christian Boltz
e6c890e336 Add --no-reload to various utils manpages
This option exists in several aa-* tools since 2.9, but isn't mentioned
in the manpage.

Also drop some trailing whitespace in the manpages.


Acked-by: John Johansen <john.johansen@canonical.com>
for 2.9, 2.10, 2.11 and trunk.
2017-07-23 21:32:29 +02:00
Christian Boltz
cf9c996cdc dovecot profile: add the attach_disconnected flag
Reported by pfak on IRC

[...] apparmor="DENIED" operation="sendmsg" info="Failed name lookup - disconnected path" error=-13 profile="/usr/sbin/dovecot" name="run/systemd/journal/dev-log" pid=20313 comm="dovecot" requested_mask="w" denied_mask="w" fsuid=0 ouid=0


Acked-by <timeout> for 2.9, 2.10, 2.11 and trunk.
2017-06-29 22:55:18 +02:00
Christian Boltz
69ba59f944 update dovecot-lda profile
dovecot-lda needs
- the attach_disconnected flags
- read access to /usr/share/dovecot/protocols.d/
- rw for /run/dovecot/auth-userdb

References: https://bugs.launchpad.net/bugs/1650827


Acked-by: Steve Beattie <steve@nxnw.org> for 2.9, 2.10 and trunk.
2017-04-07 00:15:40 +02:00
Tyler Hicks
e1415d35db utils: Add aa-remove-unknown utility to unload unknown profiles
https://launchpad.net/bugs/1668892

This patch creates a new utility, with the code previously used in the
init script 'restart' action, that removes unknown profiles which are
not found in /etc/apparmor.d/. The functionality was removed from the
common init script code in the fix for CVE-2017-6507.

The new utility prints a message containing the name of each unknown
profile before the profiles are removed. It also supports a dry run mode
so that an administrator can check which profiles will be removed before
unloading any unknown profiles.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2017-03-24 17:45:41 +00:00
Tyler Hicks
bb6818a8c1 parser: Preserve unknown profiles when restarting apparmor init/job/unit
CVE-2017-6507

https://launchpad.net/bugs/1668892

The common AppArmor 'restart' code used by some init scripts, upstart
jobs, and/or systemd units contained functionality that is no longer
appropriate to retain. Any profiles not found /etc/apparmor.d/ were
assumed to be obsolete and were unloaded. That behavior became
problematic now that there's a growing number of projects that maintain
their own internal set of AppArmor profiles outside of /etc/apparmor.d/.
It resulted in the AppArmor 'restart' code leaving some important
processes running unconfined. A couple examples are profiles managed by
LXD and Docker.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2017-03-24 17:44:38 +00:00
Seth Arnold
c71c36de2c parser: Fix delete after new[] -- patch from Oleg Strikov <oleg.strikov@gmail.com> 2017-03-21 21:46:51 -07:00
Christian Boltz
1e6897f458 Ignore change_hat events with error=-1 and "unconfined can not change_hat"
That's much better than crashing aa-logprof ;-)  (use the log line in
the added testcase if you want to see the crash)

Reported by pfak on IRC.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2017-02-23 01:03:35 +01:00
Christian Boltz
259d925619 Remove re.LOCALE flag
Starting with python 3.6, the re.LOCALE flag can only be used with byte
patterns, and errors out if used with str. This patch removes the flag
in get_translated_hotkey().


References: https://bugs.launchpad.net/apparmor/+bug/1661766


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2017-02-21 18:48:35 +01:00
Steve Beattie
0bcdaa45c0 regression tests: fix environ fail case
merge from trunk commit revision 3630

In the environ regression test, when the exec() of the child process
fails, we don't report FAIL to stdout, so the regression tests consider
it an error rather than a failure and abort, short-circuiting the
test script.

This commit fixes this by emitting the FAIL message when the result
from the wait() syscall indicates the child process did not succeed.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-02-01 21:49:41 -08:00
Christian Boltz
959d062f14 Dovecot profile: change Px to mrPx for /usr/lib/dovecot/*
Some of the /usr/lib/dovecot/* rules already have mrPx permissions,
while others don't.

With a more recent kernel, I noticed that at least auth, config, dict,
lmtp, pop3 and ssl-params need mrPx instead of just Px (confirmed by the
audit.log and actual breakage caused by the missing mr permissions).

The mr additions for anvil, log and managesieve are just a wild guess,
but I would be very surprised if they don't need mr.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2017-01-30 20:46:30 +01:00
Christian Boltz
b33997a2fa Dovecot profile update
Add several permissions to the dovecot profiles that are needed on ubuntu
(surprisingly not on openSUSE, maybe it depends on the dovecot config?)

As discussed some weeks ago, the added permissions use only /run/
instead of /{var/,}run/ (which is hopefully superfluous nowadays).


References: https://bugs.launchpad.net/apparmor/+bug/1512131


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2017-01-26 21:43:54 +01:00
Kees Cook
5a671b05d3 glibc uses /proc/*/auxv and /proc/*/status files, too
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-01-20 17:26:13 -08:00
Kees Cook
b6ae84f27d pache2 profile updates for proper signal handling, optional saslauth,
and OCSP stapling

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-01-20 17:23:50 -08:00
Steve Beattie
b0df52a7e5 utils/aa-unconfined: fix netstat invocation regression
Merge from 2.10 branch commit rev 3380

It was reported that converting the netstat command to examine
processes bound to ipv6 addresses broke on OpenSUSE due to the version
of nettools not supporting the short -4 -6 arguments.

This patch fixes the invocation of netstat to use the "--protocol
inet,inet6" arguments instead, which should return the same results
as the short options.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2017-01-09 09:25:35 -08:00
John Johansen
e0c253176a Bump release version to 2.9.4
Signed-off-by: John Johansen <john.johansen@canonical.com>
2017-01-08 17:09:32 -08:00
Christian Boltz
66280702af Handle ldd $? == 1 in get_reqs()
ldd exits with $? == 1 if a file is 'not a dynamic executable'.
This is correct behaviour of ldd, so we should handle it instead of
raising an exception ;-)

[not in 2.9 and 2.10] Also extend fake_ldd and add a test to test-aa.py to cover this.


Note that 2.10 and 2.9 don't have tests for get_reqs() nor fake_ldd,
so those branches will only get the aa.py changes.


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9.
2016-12-31 00:51:10 +01:00
Christian Boltz
105dfb2a9d Update dovecot profiles
The dovecot/auth profile needs access to /run/dovecot/anvil-auth-penalty
and /var/spool/postfix/private/auth.

The dovecot/log profile needs the attach_disconnected flag.

Refences: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1652131


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-12-27 17:47:59 +01:00
Christian Boltz
ccb9f412b4 Update nmbd profile and abstractions/samba
nmbd needs some additional permissions:
- k for /var/cache/samba/lck/* (via abstractions/samba)
- rw for /var/cache/samba/msg/ (the log only mentioned r, but that
  directory needs to be created first)
- w for /var/cache/samba/msg/* (the log didn't indicate any read access)

Reported by FLD on IRC, audit log on https://paste.debian.net/902010/



Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-12-13 22:16:45 +01:00
Christian Boltz
e11226e9b2 Add change_onexec log example to test_multi
Found in https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1648143 comment 1



Acked-by: John Johansen <john.johansen@canonical.com> for 2.9, 2.10, head

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


Note: the 2.9 and 2.10 branches don't support test_multi/*.profile files,
therefore I don't add the *.profile file to them.
2016-12-12 22:23:50 +01:00
Christian Boltz
5531d0adf1 nscd profile: allow reading libvirt/dnsmasq/*.status
References: https://bugzilla.opensuse.org/show_bug.cgi?id=1014463


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-12-09 17:54:27 +01:00
Christian Boltz
524ff50160 abstractions/php: adjust PHP7 paths for openSUSE
openSUSE uses "php7" (not just "php") in several paths, so also allow that.


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9.
2016-12-07 13:16:27 +01:00
John Johansen
0c687f1876 php abstraction update cherry-pick from 2.10
-r3370
  Update php abstraction

  Signed-off-by: kees cook <kees@outflux.net>
  Acked-by: John Johansen <john.johansen@canonical.com>
    
-r3371
  Add backwards compatibility php5 abstraction

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

Signed-off-by: John Johansen <john.johansne@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-12-07 02:42:09 -08:00
John Johansen
5b1135a833 Merge dev head -r3592 and -r3593
dev head -r3592
  aa-unconfined currently does not check/display ipv6 fix this
and -r3593
  In testing, I did notice one thing not getting turned up, from
  netstat -nlp46 output:

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-12-05 01:26:01 -08:00
Steve Beattie
019d2943d3 abstractions/X: yet another location for Xauthority
Merge from trunk commit 3591

Add access to /{,var/}run/user/*/X11/Xauthority.

Bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=845250

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-12-01 16:11:12 -08:00
Christian Boltz
72637677cf dovecot profile: allow capability sys_resource
On servers with not too much memory ("only" 16 GB), dovecot logins fail:

Nov 25 21:35:15 server dovecot[28737]: master: Fatal: setrlimit(RLIMIT_DATA, 268435456): Permission denied
Nov 25 21:35:15 server dovecot[28731]: master: Error: service(auth): command startup failed, throttling for 2 secs
Nov 25 21:35:15 server dovecot[28737]: auth: Fatal: master: service(auth): child 25976 returned error 89 (Fatal failure)

audit.log messages are:
... apparmor="DENIED" operation="capable" profile="/usr/sbin/dovecot" pid=25000 comm="dovecot" capability=24  capname="sys_resource"
... apparmor="DENIED" operation="setrlimit" profile="/usr/sbin/dovecot" pid=25000 comm="dovecot" rlimit=data value=268435456

After allowing capability sys_resource, dovecot can increase the limit
and works again.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-11-29 21:57:54 +01:00
Christian Boltz
7ecd62fc18 Update abstractions/gnome with versioned gtk paths
References: https://bugs.debian.org/845005


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-11-22 00:35:03 +01:00
Christian Boltz
533fb92e24 Allow /var/lib/nscd in abstractions/nameservice and nscd profile
The latest glibc (including nscd) in openSUSE Tumbleweed comes with
    glibc-2.3.3-nscd-db-path.diff: Move persistent nscd databases to
    /var/lib/nscd

This needs updates (adding /var/lib/nscd/) to abstractions/nameservice
and the nscd profile.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-11-18 20:19:33 +01:00
Christian Boltz
9f2ead4c97 Allow /var/cache/samba/lck/* in abstractions/samba
nmbd, winbindd (and most probably also smbd - but it has a more
permissive profile that already allows this) need rw access to
/var/cache/samba/lck/* on Debian 8.6.

Reported by FLD on IRC.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-11-18 20:13:43 +01:00
Christian Boltz
3882b2fd4a Allow "network unspec dgram," in ntpd profile
A while ago, support for "network unspec" was added. However, nobody
updated the ntpd profile (at least not the profile in upstream bzr)
which was the main reason for adding "unspec".

References: https://bugs.launchpad.net/ubuntu/+source/ntp/+bug/1546455
            (the original bugreport about "unspec")

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1009964
            (about the ntpd profile)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-11-15 00:45:47 +01:00
Christian Boltz
43cba9723a Add m permissions to mlmmj profiles
Newer kernels need m permissions for the binary the profile covers,
so add it before someone hits this problem in the wild ;-)

Also add a note that the mlmmj-recieve profile is probably superfluous
because upstream renamed the misspelled binary.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-11-09 19:45:40 +01:00
Christian Boltz
f6ad591a83 Update mlmmj profiles
This patch updates the mlmmj profiles in the extras directory to the
profiles that are used on lists.opensuse.org now. Besides adding lots
of trailing slashes for directories, several permissions were added.
Also, usr.bin.mlmmj-receive gets added - it seems upstream renamed
mlmmj-recieve to fix a typo.

These profiles were provided by Per Jessen.

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


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-11-08 21:37:02 +01:00
Christian Boltz
95b29546b4 fix typo in "reasonable" in apparmor_parser manpage
(merge request by intrigeri)


Acked-By: <Christian Boltz> for trunk, 2.10 and 2.9
2016-10-15 19:28:32 +02:00
Christian Boltz
23a489256c allow reading /tmp/.X11-unix/* in abstractions/X
This is needed when starting X with "-nolisten local".


References: https://bugs.launchpad.net/apparmor/+bug/1589823


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-10-14 20:36:38 +02:00
Christian Boltz
5ddf027996 syslog-ng profile: allow writing *.qf files
These files are needed for disk-based buffering (added in syslog-ng 3.8).
This was reported to me by Peter Czanik, one of the syslog-ng developers.

Note: I'm not sure about adding @{CHROOT_BASE} to this rule, so for now
I prefer not to do it - adding it later is easy, but finding out if it
could be removed is hard ;-)


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9.
2016-10-13 20:30:55 +02:00
Christian Boltz
674b42702e Add missing permissions to dovecot profiles
- dovecot/auth: allow to read stats-user
- dovecot/config: allow to read /usr/share/dovecot/**
- dovecot/imap: allow to ix doveconf, read /etc/dovecot/ and
  /usr/share/dovecot/**

These things were reported by Félix Sipma in Debian Bug#835826
(with some help from sarnold on IRC)

References: https://bugs.debian.org/835826


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.



Also allow reading ~/.dovecot.svbin (that's the default filename in the
dovecot config) in dovecot/lmtp profile.
(*.svbin files can probably also appear inside @{DOVECOT_MAILSTORE}, but
that's already covered by the existing rules.)

References: https://bugs.debian.org/835826 (again)


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9
2016-10-05 20:54:22 +02:00
Christian Boltz
096c9b5dbc Drop CMD_CONTINUE from ui.py (twice)
The latest version of pyflakes (1.3.0 / python 3.5) complains that
CMD_CONTINUE is defined twice in ui.py (with different texts).

Funnily CMD_CONTINUE isn't used anywhere, so we can just drop both.



Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-10-03 21:02:43 +02:00
Christian Boltz
28b8be7bcb [39/38] Ignore exec events for non-existing profiles
The switch to FileRule made some bugs visible that survived unnoticed
with hasher for years.

If aa-logprof sees an exec event for a non-existing profile _and_ a
profile file matching the expected profile filename exists in
/etc/apparmor.d/, it asks for the exec mode nevertheless (instead of
being silent). In the old code, this created a superfluous entry
somewhere in the aa hasher, and caused the existing profile to be
rewritten (without changes).

However, with FileRule it causes a crash saying

      File ".../utils/apparmor/aa.py", line 1335, in handle_children
        aa[profile][hat]['file'].add(FileRule(exec_target, file_perm, exec_mode, rule_to_name, owner=False, log_event=True))
    AttributeError: 'collections.defaultdict' object has no attribute 'add'

This patch makes sure exec events for unknown profiles get ignored.



Reproducer:

    python3 aa-logprof -f <(echo 'type=AVC msg=audit(1407865079.883:215): apparmor="ALLOWED" operation="exec" profile="/sbin/klogd" name="/does/not/exist" pid=11832 comm="foo" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 target="/sbin/klogd//null-1"')

This causes a crash without this patch because
/etc/apparmor.d/sbin.klogd exists, but has
    profile klogd /{usr/,}sbin/klogd {



References: https://bugs.launchpad.net/bugs/1379874



Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-10-01 20:26:25 +02:00
Christian Boltz
a15aee5490 Allow both paths in traceroute profile
In 2011 (r1803), the traceroute profile was changed to also match
/usr/bin/traceroute.db:
    /usr/{sbin/traceroute,bin/traceroute.db} {

However, permissions for /usr/bin/traceroute.db were never added.
This patch fixes this.


While on it, also change the /usr/sbin/traceroute permissions from
rmix to the less confusing mrix.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-09-30 00:08:37 +02:00
Tyler Hicks
36ad13a9cd libapparmor: Force libtoolize to replace existing files
Fixes build error when attempting to build and test the 2.10.95 release
on Ubuntu 14.04:

 $ (cd libraries/libapparmor/ && ./autogen.sh && ./configure && \
   make && make check) > /dev/null
 ...
 libtool: Version mismatch error.  This is libtool 2.4.6 Debian-2.4.6-0.1, but the
 libtool: definition of this LT_INIT comes from libtool 2.4.2.
 libtool: You should recreate aclocal.m4 with macros from libtool 2.4.6 Debian-2.4.6-0.1
 libtool: and run autoconf again.
 make[2]: *** [grammar.lo] Error 63
 make[1]: *** [all] Error 2
 make: *** [all-recursive] Error 1

The --force option is needed to regenerate the libtool file in
libraries/libapparmor/.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2016-09-14 12:51:33 -05:00
Christian Boltz
cb9c8a41ea Fix aa-logprof "add hat" endless loop
This turned out to be a simple case of misinterpreting the promptUser()
result - it returns the answer and the selected option, and
"surprisingly" something like
    ('CMD_ADDHAT', 0)
never matched
    'CMD_ADDHAT'
;-)

I also noticed that the changed profile doesn't get marked as changed.
This is also fixed by this patch.


References: https://bugs.launchpad.net/apparmor/+bug/1538306


Note: the 2.10 and trunk version of this patch also initializes the
new hat as profile_storage(), but this function doesn't exist in 2.9
(and isn't needed because in 2.9 everything is a big, self-initializing
hasher)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-08-15 22:10:37 +02:00
Christian Boltz
bbcb2727a6 winbindd profile: allow dac_override
This is needed to delete kerberos ccache files, for details see
https://bugzilla.opensuse.org/show_bug.cgi?id=990006#c5


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9.
2016-08-03 21:53:42 +02:00
Christian Boltz
c1d5c659c4 logparser: store network-related params if an event looks like network
Network events can come with an operation= that looks like a file event.
Nevertheless, if the event has a typical network parameter (like
net_protocol) set, make sure to store the network-related flags in ev.

This fixes the test failure introduced in my last commit.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9
2016-07-31 17:16:12 +02:00
Christian Boltz
eddd542b46 logparser.py: ignore network events with 'send receive'
We already ignore network events that look like file events (based on
the operation keyword) if they have a request_mask of 'send' or
'receive' to avoid aa-logprof crashes because of "unknown" permissions.
It turned out that both can happen at once, so we should also ignore
this case.

Also add the now-ignored log event as test_multi testcase.


References: https://bugs.launchpad.net/apparmor/+bug/1577051 #13


Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk, 2.10 and 2.9.
2016-07-30 00:46:09 +02:00
Christian Boltz
d173892c26 Allow mr for /usr/lib*/ldb/*.so in samba abstractions
This is needed for winbindd (since samba 4.4.x), but smbd could also need it.

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


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-07-26 21:14:11 +02:00
Christian Boltz
414f5d6bce Add a note about still enforcing deny rules to aa-complain manpage
This behaviour makes sense (for example to force the confined program to
use a fallback path), but is probably surprising for users, so we should
document it.

References: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=826218#37


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9
2016-06-05 23:44:25 +02:00
Christian Boltz
5f7014af8c honor 'chown' file events in logparser.py
Also add a testcase to libapparmor's log collection


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9
2016-06-05 20:08:08 +02:00
Christian Boltz
95aefde14c aa-genprof: ask about profiles in extra dir (again)
Thanks to reading the wrong directory in read_inactive_profiles()
(profile_dir instead of extra_profile_dir), aa-genprof never asked about
using a profile from the extra_profile_dir.

Sounds like an easy fix, right? ;-)

After fixing this (last chunk), several other errors popped up, one
after the other:
- get_profile() missed a required parameter in a serialize_profile() call
- when saving the profile, it was written to extra_profile_dir, not to
  profile_dir where it (as a now-active profile) should be. This is
  fixed by removing the filename from existing_profiles{} so that it can
  pick up the default name.
- CMD_FINISHED (when asking if the extra profile should be used or a new
  one) behaved exactly like CMD_CREATE_PROFILE, but this is surprising
  for the user. Remove it to avoid confusion.
- displaying the extra profile was only implemented in YaST mode
- get_pager() returned None, not an actual pager. Since we have 'less'
  hardcoded at several places, also return it in get_pager()

Finally, also remove CMD_FINISHED from the get_profile() test in
test-translations.py.


(test-translations.py is only in trunk, therefore this part of the patch
is obviously trunk-only.)




Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk
Acked-by: John Johansen <john.johansen@canonical.com> for trunk + a 50% ACK for 2.10 and 2.9
Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9
2016-06-01 21:07:15 +02:00
Christian Boltz
a708c0dc57 Ignore file events with a request mask of 'send' or 'receive'
Those events are actually network events, so ideally we should map them
as such. Unfortunately this requires bigger changes, so here is a hotfix
that ignores those events and thus avoids crashing aa-logprof.

References: https://bugs.launchpad.net/apparmor/+bug/1577051
            https://bugs.launchpad.net/apparmor/+bug/1582374


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9
2016-05-23 23:32:56 +02:00
Christian Boltz
e5ca1ace1d Document empty quotes ("") as empty value of a variable
Acked-by: Seth Arnold <seth.arnold@canonical.com> for all branches where this makes sense :)
2016-05-22 14:52:25 +02:00
Christian Boltz
0dc638f5af allow inet6 in ping profile
The latest iputils merged ping and ping6 into a single binary that does
both IPv4 and IPv6 pings (by default, it really does both).
This means we need to allow network inet6 raw in the ping profile.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=980596
            (contains more details and example output)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-05-18 21:19:06 +02:00
Seth Arnold
1e0014b4a9 dbus-session-strict: allow access to the user bus socket
From: Simon McVittie <simon.mcvittie@collabora.co.uk>
Date: Wed, 4 May 2016 13:48:36 +0100
Subject: dbus-session-strict: allow access to the user bus socket

If dbus is configured with --enable-user-bus (for example in the
dbus-user-session package in Debian and its derivatives), and the user
session is started with systemd, then the "dbus-daemon --session" will be
started by "systemd --user" and listen on $XDG_RUNTIME_DIR/bus. Similarly,
on systems where dbus-daemon has been replaced with kdbus, the
bridge/proxy used to provide compatibility with the traditional D-Bus
protocol listens on that same socket.

In practice, $XDG_RUNTIME_DIR is /run/user/$uid on all systemd systems,
where $uid represents the numeric uid. I have not used /{var/,}run here,
because systemd does not support configurations where /var/run and /run
are distinct; in practice, /var/run is a symbolic link.

Based on a patch by Sjoerd Simons, which originally used the historical
path /run/user/*/dbus/user_bus_socket. That path was popularized by the
user-session-units git repository, but has never been used in a released
version of dbus and should be considered unsupported.

Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
2016-05-11 17:22:23 -07:00
Seth Arnold
24aa2fcd11 syscall_sysctl test: correctly skip if CONFIG_SYSCTL_SYSCALL=n
From: Simon McVittie <simon.mcvittie@collabora.co.uk>
Date: Wed, 11 May 2016 13:52:56 +0100
Subject: syscall_sysctl test: correctly skip if CONFIG_SYSCTL_SYSCALL=n

This test attempts to auto-skip the sysctl() part if that syscall
was not compiled into the current kernel, via
CONFIG_SYSCTL_SYSCALL=n. Unfortunately, this didn't actually work,
for two reasons:

* Because "${test} ro" wasn't in "&&", "||", a pipeline or an "if",
  and it had nonzero exit status, the trap on ERR was triggered,
  causing execution of the error_handler() shell function, which
  aborts the test with a failed status. The rules for ERR are the
  same as for "set -e", so we can circumvent it in the same ways.
* Because sysctl_syscall.c prints its diagnostic message to stderr,
  but the $() operator only captures stdout, it never matched
  in the string comparison. This is easily solved by redirecting
  its stderr to stdout.

Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
2016-05-11 16:34:28 -07:00
Christian Boltz
561a0c0e3b accept hostname with dots
Some people have the full hostname in their syslog messages, so
libapparmor needs to accept hostnames that contain dots.


References: https://bugs.launchpad.net/apparmor/+bug/1453300 comments
            #1 and #2 (the log samples reported by scrx in #apparmor)



Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
for trunk, 2.10 and 2.9.
2016-05-05 12:04:28 +02:00
Steve Beattie
ccea109dfc libapparmor testsuite: add missing empty test_multi/testcase_syslog_read.err
Fixes make check warning:

  ERROR: Missing file ./test_multi/testcase_syslog_read.err

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-04-15 10:49:05 -07:00
Christian Boltz
d96b06e56d smbd profile needs capability sys_admin
smbd stores ACLS in the security.NTACL namespace, which means it needs
capability sys_admin.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=964971
            http://samba-technical.samba.narkive.com/eHtOW8DE/nt-acls-using-the-security-namespace-for-ntacl-considered-improper



Acked-by: Steve Beattie <steve@nxnw.org> for 2.10 and 2.9
(trunk got this and other changes via a merge request from Simon already)
2016-04-13 23:22:07 +02:00
Tyler Hicks
5cb3fb29f6 profiles: Add attach_disconnected flag to dnsmasq profile
https://launchpad.net/bugs/1569316

When Ubuntu made the jump from network-manager 1.0.4 to 1.1.93, the
dnsmasq process spawned from network-manager started hitting a
disconnected path denial:

  audit: type=1400 audit(1460463960.943:31702): apparmor="ALLOWED"
    operation="connect" info="Failed name lookup - disconnected path"
    error=-13 profile="/usr/sbin/dnsmasq"
    name="run/dbus/system_bus_socket" pid=3448 comm="dnsmasq"
    requested_mask="wr" denied_mask="wr" fsuid=65534 ouid=0

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-04-12 16:39:40 -05:00
Christian Boltz
21a61c8501 dovecot/auth: allow access to /var/run/dovecot/stats-user
Since the latest openSUSE Tumbleweed update (dovecot 2.2.21 -> 2.2.22),
dovecot/auth writes to /var/run/dovecot/stats-user.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-04-07 00:53:53 +02:00
Christian Boltz
ddb73a9c1d Update abstractions/ssl_* for acmetool-generated certificates
acmetool is an alternative client for Let's Encrypt.
(https://github.com/hlandau/acme/)

It stores the certificates etc. in the following directory layout:

    /var/lib/acme/live/<domain> -> ../certs/<hash>
    /var/lib/acme/certs/<hash>/cert
    /var/lib/acme/certs/<hash>/chain
    /var/lib/acme/certs/<hash>/privkey -> ../../keys/<hash>/privkey
    /var/lib/acme/certs/<hash>/url
    /var/lib/acme/certs/<hash>/fullchain
    /var/lib/acme/keys/<hash>/privkey

This patch adds the needed permissions to the ssl_certs and ssl_keys
abstractions so that the certificates can be used.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-03-28 21:43:49 +02:00
Christian Boltz
cac4fd95c9 nscd profile: allow paranoia mode
In /etc/nscd.conf there is an option allowing to restart nscd after a
certain time. However, this requires reading /proc/self/cmdline -
otherwise nscd will disable paranoia mode.


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


Acked-By: Jamie Strandboge <jamie@canonical.com> for trunk, 2.10 and 2.9
2016-03-21 21:31:54 +01:00
Christian Boltz
9620c54d01 Fix missing import in 2.9 test-aa.py
Since 2.9 r2978, test-aa.py fails thanks to a missing import of
'var_transform'. This patch adds the missing import.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-03-01 22:53:13 +01:00
Christian Boltz
44bf19257b Fix wrong usage of write_prof_data in serialize_profile_from_old_profile()
write_prof_data[hat] is correct (it only contains one profile, see bug 1528139),
write_prof_data[profile][hat] is not and returns an empty (sub)hasher.

This affects RE_PROFILE_START and RE_PROFILE_BARE_FILE_ENTRY.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.9 and 2.10
2016-03-01 21:26:13 +01:00
Christian Boltz
84b045b89f dovecot-lda profile: allow tempfiles and executing sendmail
dovecot-lda needs to read and write /tmp/dovecot.lda.*.

It also needs to be able to execute sendmail to send sieve vacation
mails.

For now, I'm using a child profile for sendmail to avoid introducing a
new profile with possible regressions. This child profile is based on
the usr.sbin.sendmail profile in extras and should cover both postfix'
and sendmail's sendmail.
I also mixed in some bits that were needed for (postfix) sendmail on my
servers, and dropped some rules that were obsolete (directory rules not
ending with a /) or covered by an abstraction.

In the future, we might want to provide a stand-alone profile for
sendmail (based on this child profile) and change the rule in the
dovecot-lda profile to Px.


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



Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-02-20 01:17:36 +01:00
Tyler Hicks
ae9d172f7e parser: Allow AF_UNSPEC family in network rules
https://launchpad.net/bugs/1546455

Don't filter out AF_UNSPEC from the list of valid protocol families so
that the parser will accept rules such as 'network unspec,'.

There are certain syscalls, such as socket(2), where the LSM hooks are
called before the protocol family is validated. In these cases, AppArmor
was emitting denials even though socket(2) will eventually fail. There
may be cases where AF_UNSPEC sockets are accepted and we need to make
sure that we're mediating those appropriately.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Suggested-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-02-18 12:33:20 -06:00
Christian Boltz
580d49cbf0 Fix aa-mergeprof crash with files containing multiple profiles
If a profile file contains multiple profiles, aa-mergeprof crashes on
saving in write_profile() because the second profile in the file is not
listed in 'changed'. (This happens only if the second profile didn't
change.)

This patch first checks if 'changed' contains the profile before
pop()ing it.

Reproducer: copy utils/test/cleanprof_test.in to your profile directory
and run   aa-mergeprof utils/test/cleanprof_test.out. Then just press
's' to save the profile.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9
2016-02-12 22:10:20 +01:00
Christian Boltz
7397ca0148 Remove pname to bin_name mapping in autodep()
If autodep() is called with a pname starting with / (which can happen
for (N)amed exec depending on the user input), this pname is mapped to
bin_name.

This might look like a good idea, however if the given pname doesn't
exist as file on-disk, autodep() returns None instead of a (mostly
empty) profile. (Reproducer: choose (N)amed, enter "/foo/bar")

Further down the road, this results in two things:
a) the None result gets written as empty profile file (with only a "Last
   modified" line)
b) a crash if someone chooses to add an abstraction to the None, because
   None doesn't support the delete_duplicates() method for obvious
   reasons ;-)


Unfortunately this patch also introduces a regression - aa-logprof now
fails to follow the exec and doesn't ask about the log events for the
exec target anymore. However this doesn't really matter because of a) -
asking and saving to /dev/null vs. not asking isn't a real difference
;-)


Actually the patch slightly improves things - it creates a profile for
the exec target, but only with the depmod() defaults (abstractions/base)
and always in complain mode.

I'd prefer a patch that also creates a complete profile for the exec
target, but that isn't as easy as fixing the issues mentioned above and
therefore is something for a future fix. To avoid we forget it, I opened
https://bugs.launchpad.net/apparmor/+bug/1545155


Note: 2.9 "only" writes an empty file and doesn't crash - but writing
an empty profile is still an improvement.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9
2016-02-12 21:57:57 +01:00
Christian Boltz
700162143d logparser.py: do sanity check for all file events
Most probably-file log events can also be network events. Therefore
check for request_mask in all events, not only file_perm, file_inherit
and (from the latest bugreport) file_receive.

References: https://bugs.launchpad.net/apparmor/+bug/1540562


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk, 2.10 and 2.9.
2016-02-10 19:10:46 +01:00
Tyler Hicks
e594a321c8 pam_apparmor: Don't leak /dev/urandom fd
If reading /dev/urandom failed, the corresponding file descriptor was
leaked through the error path.

Coverity CID #56012

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2016-02-01 10:44:34 -06:00
Tyler Hicks
fd38788524 libapparmor: Correct meaning of EPERM in aa_change_profile man page
I suspect that the incorrect description of EPERM was copied from
the aa_change_hat man page, where it is possible to see EPERM if the
application is not confined by AppArmor.

This patch corrects the description by documenting that the only
possible way to see EPERM is if a confined application has the
no_new_privs bit set.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-01-27 13:40:49 -06:00
Tyler Hicks
aa11bcf5b3 libapparmor: Open fds may be revalidated after aa_change_profile()
It is possible that file descriptors will be revalidated after an
aa_change_profile() but there is a lot of complexity involved that
doesn't need to be spelled out in the man page. Instead, mention that
revalidation is possible but the only way to ensure that file
descriptors are not passed on is to close them.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-01-27 13:40:49 -06:00
Tyler Hicks
52256d71ff libapparmor: Remove incorrect statement in aa_change_profile man page
The statement was meant to convey the difference between aa_change_hat()
and aa_change_profile(). Unfortunately, it read as if there was
something preventing a program from using aa_change_profile() twice to
move from profile A to profile B and back to profile A, even if profiles
A and B contained the necessary rules.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-01-27 13:40:49 -06:00
Christian Boltz
4cb12733d3 Better error message on unknown profile lines
When hitting an unknown line while parsing a profile, it's a good idea
to include that line in the error message ;-)


Note: 2.9 would print a literal \n because it doesn't have apparmor.fail,
so it will get a slightly different patch with spaces instead of \n.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9.
2016-01-25 23:47:51 +01:00
Steve Beattie
6d55c72764 regression tests: define arch specific bits for s390x
Merge from trunk revision 3342

bug: https://bugs.launchpad.net/bugs/1531325

This patch defines the arch specific registers struct for s390 for the
ptrace regression test.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-01-21 13:25:21 -08:00
Christian Boltz
9950f71d0d AARE: escape exclamation mark
'!' is a reserved symbol and needs to be escaped in AARE.

Note: aare.py only exists in trunk, therefore this part is trunk-only.



Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9 as needed.
2016-01-20 21:52:28 +01:00
Christian Boltz
5138e08372 Fix a missing comma in parser_misc.c capnames
The capnames list missed a comma, which lead to the funny
"mac_overridesyslog" capability name.

__debug_capabilities() seems to be the only user of capnames, which
might explain why this bug wasn't noticed earlier.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-01-16 11:27:47 +01:00
Christian Boltz
25fab7f65c More useful logparser failure reports
If parse_event_for_tree() raises an AppArmorException (for example
because of an invalid/unknown request_mask), catch it in read_log() and
re-raise it together with the log line causing the Exception.



Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9.


Note: 2.9 can't handle \n in exception messages, therefore I'm using spaces.
2016-01-12 19:51:44 +01:00
Christian Boltz
a404f32349 Fix handling of link events in aa-logprof
handle_children() has some special code for handling link events with
denied_mask = 'l'. Unfortunately this special code depends on a regex
that matches the old, obsolete log format - in a not really parsed
format ("^from .* to .*$").

The result was that aa-logprof did not ask about events containing 'l'
in denied_mask.

Fortunately the fix is easy - delete the code with the special handling
for 'l' events, and the remaining code that handles other file
permissions will handle it :-)


References: Bugreport by pfak on IRC


Testcase (with hand-tuned log event):

    aa-logprof -f <( echo 'Jan  7 03:11:24 mail kernel: [191223.562261] type=1400 audit(1452136284.727:344): apparmor="ALLOWED" operation="link" profile="/usr/sbin/smbd" name="/foo" pid=10262 comm=616D617669736420286368362D3130 requested_mask="l" denied_mask="l" fsuid=110 ouid=110 target="/bar"')

should ask to add '/foo l,' to the profile.



Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2016-01-07 21:27:14 +01:00
Jamie Strandboge
43b3a872f2 Merge from trunk
allow read on /run/systemd/resolve/resolv.conf for systems using networkd
(LP: #1529074)

Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-01-05 17:05:37 -06:00
Christian Boltz
40e24e9b29 Write unix rules when saving a profile
r2637 added support for parsing unix rules, but forgot to add write
support. The result was that a profile lost its unix rules when it was
saved.

This patch adds the write_unix_rules() and write_unix() functions (based
on the write_pivot_root() and write_pivot_root_rules() functions) and
makes sure they get called at the right place.

The cleanprof testcase gets an unix rule added to ensure it's not
deleted when writing the profile. (Note that minitools_test.py is not
part of the default "make check", however I always run it.)


References: https://bugs.launchpad.net/apparmor/+bug/1522938
            https://bugzilla.opensuse.org/show_bug.cgi?id=954104



Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk, 2.10 and 2.9.
2015-12-17 23:51:29 +01:00
Christian Boltz
28a64d280c ignore log event if request_mask == ''
We already check for None, but '' != None ;-)


References: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1525119


Acked-by: John Johansen <john.johansen@canonical.com> for 2.9, 2.10 and trunk.
2015-12-12 13:31:50 +01:00
Christian Boltz
f20df05f2d Fix logparser.py crash on change_hat events
'change_hat' events have the target profile in 'name2', not in 'name'
(which is None and therefore causes a crash when checking if it contains
'//')

Also add the log event causing this crash to the libapparmor testsuite.

References: https://bugs.launchpad.net/apparmor/+bug/1523297


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9.
2015-12-12 13:07:57 +01:00
Christian Boltz
f6d84c7af5 Several fixes for variable handling
Parsing variables was broken in several ways:
- empty quotes (representing an intentionally empty value) were lost,
  causing parser failures
- items consisting of only one letter were lost due to a bug in RE_VARS
- RE_VARS didn't start with ^, which means leading garbage (= syntax
  errors) was ignored
- trailing garbage was also ignored

This patch fixes those issues in separate_vars() and changes
var_transform() to write out empty quotes (instead of nothing) for empty
values.

Also add some tests for separate_vars() with empty quotes and adjust
several tests with invalid syntax to expect an AppArmorException.

var_transform() gets some tests added.

Finally, remove 3 testcases from the "fails to raise an exception" list
in test-parser-simple-tests.py.



Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
(which also implies 2.10)


Note: 2.9 doesn't have test-parser-simple-tests.py, therefore it won't
get that part of the patch.
2015-12-12 13:02:06 +01:00
Christian Boltz
620d75600f Add realtime signals to SIGNALS list in apparmor.d
Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.10 and 2.9.
2015-12-02 22:07:13 +01:00
Christian Boltz
1af6055748 Add realtime signal example to the apparmor.d manpage
Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9.
2015-12-02 20:10:54 +01:00
Christian Boltz
88e5b24db2 Add missing variables to the apparmor.d manpage
@{pids} and @{apparmorfs} was not mentioned in the apparmor.d manpage.


Acked-by: John Johansen <john.johansen@canonical.com> for trunk, 2.10 and 2.9
2015-11-28 21:45:44 +01:00
Christian Boltz
3ebd441223 Map c (create) log events to w instead of a
Creating a file is in theory covered by the 'a' permission, however
discussion on IRC brought up that depending on the open flags it might
not be enough (real-world example: creating the apache pid file).

Therefore change the mapping to 'w' permissions. That might allow more
than needed in some cases, but makes sure the profile always works.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9, 2.10 and trunk
2015-11-19 21:24:15 +01:00
Christian Boltz
c7b6454fb0 Also add python 3.5 to logprof.conf
Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9, 2.10 and trunk
2015-11-19 20:23:52 +01:00
Jamie Strandboge
a2a5dc7677 Description: update python abstraction for python 3.
Signed-off-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-11-19 08:53:21 -06:00
Christian Boltz
9c6fae0c02 Update comments in minitools_test.py
After switching to winbindd as test profile, comments about the ntpd
profile don't make sense anymore ;-)

The patch also includes a whitespace fix.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:39:03 +01:00
Christian Boltz
c950c2a358 Fix all tests in minitools_test.py
Change minitools_test.py to use the winbind instead of the ntpd profile
for testing. The tests broke because the ntpd profile has the
attach_disconnected flag set now, and therefore didn't match the
expected flags anymore.

Also replace the usage of filecmp.cmp() in the cleanprof test with
reading the file and using assertEqual - this has the advantage that we
get a full diff instead of just "files differ".


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:37:51 +01:00
Christian Boltz
0a6c17de54 Change minitools_test.py to use aa-* --no-reload
This allows to run minitools_test.py as non-root user.

Also add a check that only creates the force-complain directory if it
doesn't exist yet.


Note: With this patch applied, there are still 4 failing tests, probably
caused by changes in the profiles that are used in the tests.



Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:37:06 +01:00
Christian Boltz
7b3a87ca8f Allow ntpd to read directory listings of $PATH
For some reasons, it needs to do that to find readable, writeable and
executable files.

See also https://bugzilla.opensuse.org/show_bug.cgi?id=945592


Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:30:28 +01:00
Christian Boltz
260c0458a7 aa-notify: also display notifications for complain mode events
Change aa-notify parse_message() to also honor complain mode log events.
This affects both modes - desktop notifications and the summary report.


Acked-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:29:28 +01:00
Christian Boltz
e024dd3ca9 Let aa-complain delete the disable symlink
aa-complain is part of the enforce/complain/disable triple. Therefore
I expect it to actually load a profile in complain mode.

To do this, it has to delete the 'disable' symlink, but set_complain()
in aa.py didn't do this (and therefore kept the profile disabled).


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:28:38 +01:00
Christian Boltz
17f4905b2e Let aa-audit print a warning if a profile is disabled
Users might expect that setting a profile into audit mode also activates
it (which shouldn't happen IMHO because the audit flag is not part of
the enforce/complain/disable triple), so we should at least tell them.

References: https://bugs.launchpad.net/apparmor/+bug/1429448


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9
2015-11-18 20:27:29 +01:00
Christian Boltz
55d325d21b utils/test/Makefile: add libapparmor to PYTHONPATH
The last utils/test/Makefile change switched to using the in-tree
libapparmor by default (unless USE_SYSTEM=1 is given). However, I missed
to add the swig/python parts of libapparmor to PYTHONPATH, so the
system-wide LibAppArmor/__init__.py was always used.

This patch adds the in-tree libapparmor python module to PYTHONPATH.

I'm sorry for the interesting[tm] way to find out that path, but
a) I don't know a better / less ugly way and
b) a similar monster already works in libapparmor/swig/python/test/ ;-)


Acked-by: John Johansen <john.johansen@canonical.com> for 2.9 and trunk
(that also implies 2.10 ;-)
2015-11-18 13:46:26 +01:00
Christian Boltz
e23168bc60 Add python to the "no Px rule" list in logprof.conf
To make things more interesting, /usr/bin/python and /usr/bin/python[23]
are symlinks to /usr/bin/python[23].[0-9], so we have to explicitely
list several versions.


Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9, 2.10 and trunk
2015-11-18 13:40:44 +01:00
Christian Boltz
778a92f9a3 syslog-ng profile: allow /run/log/journal/
syslog-ng needs to access both the permanent /var/log/journal/ and the
non-permanent /run/journal/.

I also included /var/run/journal/ to stay consistent with supporting
both /run/ and /var/run/.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-11-11 16:45:46 +01:00
Christian Boltz
a741ce1ee6 let logparser.py ignore file_inherit events without request_mask
That's not nice, but still better than a crash ;-)

References: https://bugs.launchpad.net/apparmor/+bug/1466812/


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.9
2015-10-28 21:01:45 +01:00
Christian Boltz
7fb34ede01 Add several files created during libapparmor build to .bzrignore
Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-10-21 21:44:39 +02:00
Christian Boltz
400da57849 Change utils/test/Makefile to use the in-tree libapparmor
Also add support for the USE_SYSTEM variable, which means:
- test against the in-tree libapparmor and python modules by default
- test against the system libapparmor and python modules if USE_SYSTEM
  is set

The old behaviour was a mix of both - it always used the in-tree python
modules and the system libapparmor.

For obvious reasons, you'll need to build libapparmor before running the
tests (unless you specify USE_SYSTEM=1 as parameter to make check).


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-10-20 23:32:50 +02:00
Christian Boltz
cbe5cd44e7 Change /bin/ paths in profiles to also match on /usr/bin/
oftc_ftw reported on IRC that Arch Linux has a symlink /bin -> /usr/bin.
This means we have to update paths for /bin/ in several profiles to also
allow /usr/bin/


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-10-20 23:13:29 +02:00
Christian Boltz
eff8f2a211 dnsmasq profile update: allow /dev/tty
This patch is based on a SLE12 patch to allow executing the
--dhcp-script. We already have most parts of that patch since r2841,
except /dev/tty rw which is needed for the shell's stdout and stderr.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=940749 (non-public)


Acked by Seth Arnold on IRC (with "owner" added)
2015-10-16 21:52:58 +02:00
Christian Boltz
144a16baf1 several additions for the syslog-ng profiles
The latest syslog-ng version needs some more permissions:
- abstractions/openssl (for reading openssl.conf)
- reading /etc/syslog-ng/conf.d/
- reading the journal
- reading /etc/machine-id (it's unclear why this is needed, therefore
  I don't want abstractions/dbus-session-strict for now)
- write access to /run/syslog-ng.ctl

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


Acked-By: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9
2015-10-07 22:19:55 +02:00
Christian Boltz
223322ef47 Accept more log formats in logparser.py
logparser.py does a regex check on log lines as performance improvement
so that it only hands over lines that look like AppArmor events to
LibAppArmor parsing. Those regexes were incomplete and didn't cover all
log formats LibAppArmor accepts, with the end result of "overlooking"
events.

This patch splits off common parts of the regex, adds more regexes for
several log types and finally merges everything into one regex.

test-logparser.py gets adjusted to the merged RE_LOG_ALL regex.

Finally, add a new test that was posted on IRC to the test_multi set.


As already threatened nearly a month ago,
   Acked by <timeout> for trunk and 2.9


Note: 2.9 doesn't have test-libapparmor-test_multi.py, therefore I can't
add the check to verify all test_multi log lines against the regex to
ensure logparser.py doesn't silently ignore events.

Bug: https://launchpad.net/bugs/1569316
2015-10-03 20:24:24 +02:00
Christian Boltz
afe74c6faa dnsmasq profile - also allow /bin/sh
This patch is based on a SLE12 patch to allow executing the
--dhcp-script. We already have most parts of that patch since r2841,
however the SLE bugreport indicates that /bin/sh is executed (which is
usually a symlink to /bin/bash or /bin/dash), so we should also allow
/bin/sh

References: https://bugzilla.opensuse.org/show_bug.cgi?id=940749 (non-public)


Acked-by: Seth Arnold <seth.arnold@canonicalc.com> for trunk and 2.9
2015-09-18 19:07:28 +02:00
Christian Boltz
6eb3d719c1 Update the /sbin/dhclient profile
Add some permissions that I need on my system:
- execute nm-dhcp-helper
- read and write /var/lib/dhcp6/dhclient.leases
- read /var/lib/NetworkManager/dhclient-*.conf
- read and write /var/lib/NetworkManager/dhclient-*.conf


Looks-good-by: Steve Beattie <steve@nxnw.org>
Acked-by: <timeout> for trunk and 2.9
2015-09-09 00:01:16 +02:00
Christian Boltz
8011b9d9b6 Dovecot imap needs to read /run/dovecot/mounts
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-09-03 18:27:31 +02:00
Steve Beattie
301731ef34 utils/aa-logprof.pod: fix typo in manpage
Merge from trunk commit 3228

Bug: https://bugs.launchpad.net/bugs/1485855
2015-08-25 15:18:48 -07:00
Christian Boltz
b885d62a8a add /usr/share/locale-bundle/ to abstractions/base
/usr/share/locale-bundle/ contains translations packaged in
bundle-lang-* packages in openSUSE.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-08-23 15:21:41 +02:00
Steve Beattie
49e82df101 regression tests: make sysctl(2) test a bit more resiliant
Merge from trunk commit rev 3219

In testing against the 4.1 kernel, the syscall_sysctl testcase started
failing even in the unconfined case. What the test program does is
attempt to adjust the kernel.threads-max sysctl to be slightly larger
and see if the operation succeeds by reading the value back out. It
also attempts to save the original value and restore it. The test
was failing because (in VMs at least) the default value chosen by
the kernel for the kernel.threads-max setting was high enough that
attempts to increase it would be ignored (likely to prevent too much
use of kernel memory by threads), helpfully without any message being
report to dmesg. Thus, the initial read of the current value would
succeed, the write of that value + 1024 would appear to succeed,
but then reading the value back out and comparing it to the expected
value would fail, as it would still be the original value, not the
expected new value.

This patch attempts to address this by first attempting to raise
the value, and if that does not appear to work, to then attempt
to lower it.  It also refactors the code a bit by creating helper
functions to perform the actual sysctl(2) calls to make the code a
bit easier to read.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-08-10 14:13:04 -07:00
Christian Boltz
247d3fc22e map socket_create events to 'net' events
See libapparmor test_multi testcase24.* and testcase33.* for example logs.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-08-10 21:30:54 +02:00
Christian Boltz
480c83343b Fix name_to_prof_filename() error behaviour
In some cases, the return value of name_to_prof_filename() is undefined.
This happens when deleting the to-be-confined binary while running
aa-genprof and leads to a not-too-helpful
    File "/usr/lib/python3/dist-packages/apparmor/aa.py", line 265, in enforce
	      prof_filename, name = name_to_prof_filename(path)
	TypeError: 'NoneType' object is not iterable

(reported by maslen on IRC)

This patch makes sure name_to_prof_filename() always returns None, None
(instead of undefined aka just None) so that at least the caller can
successfully split it into two None values.

For the exotic aa-genprof usecase given above, this at least improves
the error message to
    Can't find $binary_name
(raised by enforce() via fatal_error())


The patch also changes fatal_error() to display the traceback first, and
the human-readable message at the end, which makes it more likely that
the user actually notices the human-readable message.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for both trunk and 2.9.
2015-08-03 01:16:04 +02:00
Christian Boltz
92b528b6db winbindd profile: allow k for /etc/samba/smbd.tmp/msg/*
References: https://bugzilla.opensuse.org/show_bug.cgi?id=921098 starting at comment 15


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-07-30 22:05:05 +02:00
Christian Boltz
7876f356bf skype profile: allow reading @{PROC}/@{pid}/net/dev
References: https://bugzilla.opensuse.org/show_bug.cgi?id=939568


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9
2015-07-28 01:16:47 +02:00
Jamie Strandboge
a70167db0e profiles/apparmor.d/usr.sbin.avahi-daemon: allow write access to
/run/systemd/notify which is needed on systems with systemd

Signed-off-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-07-24 15:04:17 -05:00
Jamie Strandboge
b7a8b6a689 profiles/apparmor.d/abstractions/X: also allow unix connections to
@/tmp/.ICE-unix/[0-9]*, needed by (at least) firefox and thunderbird

Signed-off-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-07-24 15:02:54 -05:00
Jamie Strandboge
641b25d88f profiles/apparmor.d/usr.sbin.dnsmasq: allow /bin/dash in addition to /bin/bash
Signed-off-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-07-24 13:57:47 -05:00
Christian Boltz
27664acf9a Fix aa_log_end_msg() in rc.apparmor.suse
"rcapparmor kill" results in a funny error message:
    /lib/apparmor/rc.apparmor.functions: line 441: return: -v: invalid option
    return: usage: return [n]

SLE12 includes a patch that prevents this error message, but also
prevents that $? is handed over correctly to rc_status. This means that
"rcapparmor kill" will happily display "done" even with a compiled-in
apparmor module that can't be unloaded.

This patch is the improved version - it adds a small helper function to
set $? (as handed over to aa_log_end_msg()) and then calls rc_status -v.
This means that "rcapparmor kill" now shows "failed" because it's
impossible to unload something that is compiled directly into the
kernel.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=862170 (non-public)


Acked-by: Seth Arnold <seth.arnold@canonical.com> for 2.9 and trunk
2015-07-24 00:08:50 +02:00
Steve Beattie
dccd5a18cb regression tests: more ptrace adjustments for arm64 upstream changes
Merge from trunk commit 3201

In the commit "Rev 3169: regression tests: have
ptrace use PTRACE_GETREGSET by default", I created
some ifdef magic to use the per arch general purpose
register data structures for various architectures,
including arm64.  Unfortunately, in the upstream glibc commit
7d05a8168b
<bits/ptrace.h> is no longer included in the arm64 specific user.h,
which defined the structure as 'struct user_pt_regs'; instead user.h
was converted to define 'struct user_regs_struct'. Because of this,
the ptrace test fails to compile on arm64 when glibc is 2.20 or newer.

This patch adjusts the ptrace test to use the newer structure on arm64
if it's detected that a newer glibc is detected and reverts to using
the older one for older glibcs. It also adds an error when compiling
on architectures that haven't been incorporated yet.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-07-14 10:58:05 -07:00
Christian Boltz
6ae4a3c2f0 Add cux and CUx to PROFILE_MODE_RE
cux and CUx are valid exec permissions, so they should be accepted
by validate_profile_mode() ;-)


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
2015-07-11 22:58:24 +02:00
Christian Boltz
39ebf164de Avoid raising an exception for hats in includes in aa-logprof
aa-logprof raises an exception if
- an include file contains a hat
- that file is included in a profile and
- aa-logprof hits an audit log entry for this profile

Reproducer ("works" on 2.9 and trunk):
python3 aa-logprof -f <(echo 'Jun 19 11:50:36 piorun kernel: [4474496.458789] audit: type=1400 audit(1434707436.696:153): apparmor="DENIED" operation="open" profile="/usr/sbin/apache2" name="/etc/gai.conf" pid=2910 comm="apache2" requested_mask="r" denied_mask="r" fsuid=0 ouid=0') -d ../profiles/apparmor.d/

This happens because profiles/apparmor.d/apache2.d/phpsysinfo was
already read when pre-loading the include files.

This patch changes aa.py parse_profile_data() to only raise the
exception if it is not handling includes currently.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-07-09 15:13:19 +02:00
Christian Boltz
16e6d5ffd9 Ignore file_perm events without request_mask
For some (not yet known) reason, we get file_perm events without
request_mask set, which causes an aa-logprof crash.

Reproducer log entry:
Jun 19 12:00:55 piorun kernel: [4475115.459952] audit: type=1400 audit(1434708055.676:19629): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2" pid=3512 comm="apache2" laddr=::ffff:193.0.236.159 lport=80 faddr=::ffff:192.168.103.80 fport=61985 family="inet6" sock_type="stream" protocol=6

This patch changes logparser.py to ignore those events.

References: https://bugs.launchpad.net/apparmor/+bug/1466812/


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-07-08 22:34:38 +02:00
Christian Boltz
56ac5c3e5a Allow boolean definitions outside profiles, not inside
According to the parser test profiles (which are the only
"documentation" I found about this), definition of boolean variables
is only allowed outside profiles, not inside them.

parse_profile_data() got it the wrong way round, therefore this patch
fixes the condition and updates the error message.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-07-08 13:16:57 +02:00
Christian Boltz
bc8c770e3f [2.9] Fix crash in profile_known_network() and profile_known_capability() with #include <directory>
Ignore include files that were not read before (= don't exist in
include[], which typically happens for #include <directory>) so that
the profile_known_*() functions don't crash.

Note: Since the 2.9 code is too different, this patch only avoids the
crash, but doesn't ensure that the files in the included directory are
honored (which would need in a rewrite of the profile_known_*()
functions).

BTW: I tested with a network log entry and hope the best for
profile_known_capability() ;-)

References: https://bugs.launchpad.net/apparmor/+bug/1471425


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 13:14:01 +02:00
Christian Boltz
da7719a717 Improve validate_profile_mode() and drop PROFILE_MODE_NT_RE
The only difference between PROFILE_MODE_RE and PROFILE_MODE_NT_RE
was that the latter one additionally allowed 'x', which looks wrong.
(Standalone 'x' is ok for deny rules, but those are handled by
PROFILE_MODE_DENY_RE.)

This patch completely drops PROFILE_MODE_NT_RE and the related code in
validate_profile_mode().

Also wrap the two remaining regexes in '^(...)+$' instead of doing it
inside validate_profile_mode(). This makes the code more readable and
also results in a 2% performance improvement when parsing profiles.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-07-06 14:46:28 +02:00
Christian Boltz
56e7b70dd7 Move file mode regexes and add "pux"
Add the missing "pux" to PROFILE_MODE_RE and PROFILE_MODE_NT_RE.

Also move those regexes and PROFILE_MODE_DENY_RE directly above
validate_profile_mode() which is the only user.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-07-06 14:45:25 +02:00
Christian Boltz
8e065f85c1 Fix parsing of boolean assignments
Parsing of boolean assignments failed with
    TypeError: '_sre.SRE_Match' object is not subscriptable
because of a missing ".groups()"


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-07-06 14:43:40 +02:00
Christian Boltz
473bf9c164 Fix some parser test syntax errors
Errors include typos ("DESCRIPT__ON"), missing value after #=EXRESULT
and #=EXRESULT=PASS (= instead of space).


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-07-06 13:27:12 +02:00
Steve Beattie
7a82798f6b regression tests: have ptrace use PTRACE_GETREGSET by default
Merge from trunk revision 3169

Bug: https://bugs.launchpad.net/apparmor/+bug/1470985

The ptrace regression test fails to compile on the arm64 platform,
because it uses PTRACE_GETREGS and not the newer PTRACE_GETREGSET
interface for getting access to arch-specific register information[0].
However, fixing it is complicated by the fact that the struct name
for for the general purpose registers is not named consistently
across architectures. This patch attempts to address those issues,
and compiles at least on i386, amd64, arm64, arm (armhf), ppc64,
and ppc64el. The test is verified to continue to function correctly
on i386 and amd64.

[0] https://sourceware.org/ml/archer/2010-q3/msg00193.html

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-07-02 23:28:44 -07:00
Christian Boltz
b5a7142652 profiles: postfix/master also needs lock permissions for master.pid
reported by darix some weeks ago, and also confirmed on my own servers.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9
2015-06-25 13:17:52 +02:00
Steve Beattie
967e50c2b3 parser: fix make parser_regex missing dependency
Merge from trunk commit 3159

parser_regex.c includes libapparmor_re/aare_rules.h and thus it
should depend on it in the Makefile.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-24 16:55:26 -07:00
Tyler Hicks
c79588b1f6 utils: Don't use access() to determine readability of profiles file
LSMs, such as AppArmor, aren't consulted when a program calls access(2).
This can result in access(2) returning 0 but a subsequent open(2)
failing.

The aa-status utility was doing the access() -> open() sequence and we
became aware of a large number of tracebacks due to open() failing for
lack of permissions. This patch catches any IOError exceptions thrown by
open(). It continues to print the same error message as before when
access() failed but also prints that error message when AppArmor blocks
the open of the apparmorfs profiles file.

https://launchpad.net/bugs/1466768

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-22 10:15:01 -05:00
Christian Boltz
e3e77409a3 Ignore change hat declarations when parsing a profile
Hat declarations ("^hat,") were added in 2.3 for declaring external
hats, but in the meantime aren't supported by the parser anymore (tested
with 2.9.2 parser).

Additionally, if a profile contains both a hat declaration and the hat
("^hat { ...}"), the hat declaration can overwrite the content of the
hat on a "last one wins" base.

This is caused by setting 'declared' to True, which means write_piece()
will only write the "^hat," line, but not the "^hat { ... }" block.

Therefore no longer set 'declared' to True, print a warning that hat
declarations are no longer supported, and ignore the rule. This also
means that running aa-cleanprof can make the profile valid again :-)

Also no longer change 'hat' when hitting a profile declaration, which
also looks wrong.


Note: This change removes the only usage of 'declared'. A follow-up
patch (trunk only) will completely remove the 'declared' handling.


Reproducer profile (run aa-cleanprof on it):
(will crash in remove_duplicate_rules() 80% of the time - if so, try
multiple times. One of the next patches will fix that. Or just try 2.9,
which doesn't have the crash in remove_duplicate_rules().)

/usr/bin/true {

  ^FOO {
    capability setgid,
  }

  # deletes the content of ^FOO when saving the profile! (last one wins)
  # additionally, the parser says this is invalid syntax
  ^FOO,

}


See also the "Hat declarations" thread on the ML,
https://lists.ubuntu.com/archives/apparmor/2015-June/008107.html



Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for both 2.9 and trunk.
2015-06-19 21:18:53 +02:00
John Johansen
76e975a0c5 Set cache file tstamp to the mtime of most recent policy file tstamp
Currently the cache file has its mtime set at creation time, but this
can lead to cache issues when a policy file is updated separately from
the cache. This makes it possible for an update to ship a policy file
that is newer than the what the cache file was generated from, but
result in a cache hit because the cache file was local compiled after
the policy file was package into an update (this requires the update
to set the mtime of the file when locally installed to the mtime of
the file in its update archive but this is commonly done, especially
in image based updates).

http://bugs.launchpad.net/bugs/1460152

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-18 11:11:08 -07:00
Felix Geyer
5d9d26d1da Respect $CPPFLAGS
Merged from trunk revision 3117

Some parts of the AppArmor build system don't respect $CPPFLAGS.
The attached patch fixes this.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-10 22:55:53 -07:00
Kshitij Gupta
946f586747 Fix indentation for return command in cleanprofile.py
The following patch:
- Brings the return to the correct indentation
- Adds a sorted call over the set keys of hat in the profile

Acked-by: Christian Boltz <apparmor@cboltz.de> for trunk and 2.9.
2015-06-07 23:18:05 +05:30
Christian Boltz
9ba11eb14a Allow aa-complain etc. to change profiles for non-existing binaries
aa-complain, aa-enforce, aa-disable and aa-audit refused to change
profiles for non-existing binaries. This patch also allows paths
starting with /. This also makes it possible to use
    aa-complain '/{usr/,}bin/ping'
and
    aa-complain /etc/apparmor.d/bin.ping


This patch fixes https://bugs.launchpad.net/apparmor/+bug/1416346

Well, mostly - we still need to decide how we handle wildcards in
profile names:
    aa-complain ping
    aa-complain /usr/bin/ping
will still error out with "Profile not found" because it isn't an exact
match (and matching the wildcard would change more than the user wants).


Oh, and this patch also fixes the last failure in minitools_test.py.



Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-06-06 14:26:40 +02:00
Christian Boltz
c2777bb25a Add --no-reload parameter to minitools
Add a --no-reload parameter to aa-audit, aa-cleanprof, aa-complain,
aa-disable and aa-enforce. This makes it possible to change the
profile flags without reloading the profile.

Also change tools.py to honor the --no-reload parameter.

References: https://bugs.launchpad.net/apparmor/+bug/1458480


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-06-06 14:22:17 +02:00
Christian Boltz
431bce2a85 Fix available buttons after switching audit flag in aa-logprof
When switching the audit flag for network events in aa-logprof
(technically, it happens in aa.py ask_the_question()), the "(I)gnore"
button gets "lost".

This patch fixes the list of available buttons.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-06-06 14:13:00 +02:00
Christian Boltz
2c63bd020a fix aa-mergeprof capability handling
Thanks to a broken optimization (which missed a "not" in the if
condition), aa-mergeprof never asked to merge capability rules.

Also fix a syntax / parameter error uncovered after fixing the
condition.

This patch is only meant for the 2.9 branch.


Acked-by: Steve Beattie <steve@nxnw.org>

Bug: https://launchpad.net/bugs/1210514
2015-06-02 13:56:32 +02:00
Christian Boltz
6ae047d0c1 Let set_profile_flags() change the flags for all hats
It did this in the old 2.8 code, but didn't in 2.9.x (first there was a
broken hat regex, then I commented out the hat handling to avoid
breakage caused by the broken regex).

This patch makes sure the hat flags get set when setting the flags for
the main profile.

Also change RE_PROFILE_HAT_DEF to use more named matches
(leadingwhitespace and hat_keyword). Luckily all code that uses the
regex uses named matches already, which means adding another (...) pair
doesn't hurt.

Finally adjust the tests:
- change _test_set_flags to accept another optional parameter
  expected_more_rules (used to specify the expected hat definition)
- add tests for hats (with '^foobar' and 'hat foobar' syntax)
- add tests for child profiles, one of them commented out (see below)


Remaining known issues (also added as TODO notes):

- The hat and child profile flags are *overwritten* with the flags used
  for the main profile. (That's well-known behaviour from 2.8 :-/ but we
  have more flags now, which makes this more annoying.)
  The correct behaviour would be to add or remove the specified flag,
  while keeping other flags unchanged.

- Child profiles are not handled/changed if you specify the 'program'
  parameter. This means:
  - 'aa-complain smbldap-useradd' or 'aa-complain /usr/sbin/smbldap-useradd'
    _will not_ change the flags for the nscd child profile
  - 'aa-complain /etc/apparmor.d/usr.sbin.smbldap-useradd' _will_ change
    the flags for the nscd child profile (and any other profile and
    child profile in that file)


Even with those remaining issues (which need bigger changes in
set_profile_flags() and maybe also in the whole flags handling), the
patch improves things and fixes the regression from the 2.8 code.



Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9

Bug: https://launchpad.net/bugs/1501913
2015-05-28 22:16:36 +02:00
Christian Boltz
e20463df79 Update Samba profiles for Samba 4.2
Samba 4.2 needs some more permissions for nmbd and winbindd.

To avoid overcomplicated profiles, change abstractions/samba to allow
/var/lib/samba/** rwk, (instead of **.tdb rwk) - this change already
fixes the nmbd profile.

winbindd additionally needs some more write permissions in /etc/samba/
(and also in /var/lib/samba/, which is covered by the abstractions/samba
change)


References: https://bugzilla.opensuse.org/show_bug.cgi?id=921098 and
            https://bugzilla.opensuse.org/show_bug.cgi?id=923201


Note: this commit differs from trunk r3038 - the 2.9 version keeps the
/var/lib/samba/ lines in the winbindd profile avoid problems if for
some reason abstractions/samba isn't updated (*.rpmnew etc.)


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 01:27:03 +02:00
Christian Boltz
1d29db0cd7 Add the attach_disconnected flag to the ntpd profile
I noticed "disconnected path" (run/nscd/*) events for ntpd while
updating to the latest openSUSE Tumbleweed.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9.
2015-05-19 01:21:37 +02:00
Christian Boltz
3adde7290e Fix raising AppArmorException in aa-mergeprof
aa-mergeprof failed to fail ;-) when it should raise an AppArmorException.
Instead, it failed with

    AttributeError: 'module' object has no attribute 'AppArmorException'

I confirmed this bug in trunk and 2.9.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-05-18 01:37:18 +02:00
Christian Boltz
ea72078cc4 Split off RE_PROFILE_NAME and RE_PROFILE_PATH from RE_PROFILE_START
(might get re-used later ;-)

Also add two tests for profile names not starting with / - the quoted
version wasn't catched as invalid before, so this change is actually
also a bugfix.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-05-09 01:10:59 +02:00
Christian Boltz
43a8d7703d usr.lib.dovecot.lmtp: add openssl and ssl_keys abstractions
reported by darix on IRC. This is needed if you have a bigger setup with
dovecot on a different (or multiple) machines


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-27 21:34:27 +02:00
Steve Beattie
b4b6af96c9 common/Version: prepare for a 2.9.3 release 2015-04-23 22:26:32 -07:00
Steve Beattie
b37bd8a1aa Point makefile at correct launchpad branch to generate tarball from. 2015-04-23 12:46:45 -07:00
Christian Boltz
ead71a306a Enable testloops for nosetests
Ensure nosetests sees all tests in the tests[] tuples. This requires
some name changes because nosetests thinks all function names containing
"test" are tests. (A "not a test" docorator would be an alternative, but
that would require some try/except magic to avoid a dependency on nose.)

To avoid nosetests thinks the functions are a test,
- rename setup_all_tests() to setup_all_loops()
- rename regex_test() to _regex_test() (in test-regex_matches.py)

Also add the module_name as parameter to setup_all_loops and always run
it (not only if __name__ == '__main__').

Known issue: nosetests errors out with
    ValueError: no such test method in <class ...>: stub_test
when trying to run a single test generated out of tests[].
(debugging hint: stub_test is the name used in setup_test_loop().)
But that's still an improvement over not seeing those tests at all ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-22 22:03:36 +02:00
Christian Boltz
aa45be1c10 Fix crash in serialize_profile_from_old_profiles()
Assume you have a profile like

    /bin/foo {
      /etc/ r,
      network,
      /usr/ r,
    }

(important: there must be be a non-path rule between the two path blocks)

Then run aa-logprof and add another path event. When choosing (V)iew changes,
it will crash with a misleading

  File ".../utils/apparmor/aamode.py", line 205, in split_mode
      other = mode - user
      TypeError: unsupported operand type(s) for -: 'collections.defaultdict' and 'set'

The reason for this is our beloved hasher, which is playing funny games
another time.

The patch wraps the hasher usage with a check for the parent element to
avoid auto-creation of empty childs, which then lead to the above crash.


BTW: This is another issue uncovered by the LibreOffice profile ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-16 13:11:39 +02:00
Steve Beattie
c1c5192532 profiles: update postfix-common abstraction
Merge from trunk revision 3012

Update the postfix-common abstraction to cope with signal and unix
socket mediation, update the access to the sasl library locations
in a multiarch compliant way, and allow access to limited bits
of the filesystem paths under which postfix chroots itself to
(/var/spool/postfix/ on Ubuntu).

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-04-15 23:35:52 -07:00
Christian Boltz
2b9260f27a Fix serialize_profile_from_old_profiles() to not crash on "@{var} +="
serialize_profile_from_old_profiles() calls store_list_var() with an
empty hasher. This fails for "+=" because in this case store_list_var()
expects a non-empty hasher with the variable already defined, and raises
an exception because of the empty hasher.

This patch sets "correct = False" if a "+=" operation appears, which
means the variable will be written in "clean" mode instead.

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).



Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-16 02:02:02 +02:00
Christian Boltz
4063647a5f fix handling of adding to variables
the LibreOffice profile uncovered that handling of @{var} += is broken:

  File ".../utils/apparmor/aa.py", line 3272, in store_list_var
    var[list_var] = set(var[list_var] + vlist)
TypeError: unsupported operand type(s) for +: 'set' and 'list'

This patch fixes it:
- change separate_vars() to use and return a set instead of a list
  (FYI: separate_vars() is only called by store_list_var())
- adoptstore_list_var() to expect a set
- remove some old comments in these functions
- explain the less-intuitive parameters of store_list_var()

Also add some tests for separate_vars() and store_list_var().
The tests were developed based on the old code, but not all of them
succeed with the old code.

As usual, the tests uncovered some interesting[tm] behaviour in
separate_vars() (see the XXX comments and tell me what the really
expected behaviour is ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-16 01:59:10 +02:00
Christian Boltz
b4048cf3de logparser.py: change mask only for path events
Move the code that does the c -> a and d -> w replacement in denied_mask
and requested_mask so that it only runs for path and exec events, but not
for other events (like dbus and ptrace). The validate_log_mode() and
log_str_to_mode() calls are also moved.

Technically, this means moving code from parse_event() to the path
and exec sections in add_event_to_tree().

This also means aa-logprof no longer crashes if it hits a ptrace or
dbus event in the log.

The "if dmask:" and "if rmask:" checks are removed - if a path event
doesn't have these two, it is totally broken and worth a aa-logprof
crash ;-)

Also adjust the parse_event() tests to expect the "raw" mask instead of
a set.

Note: the 2.9 branch doesn't contain test-capability.py, therefore I
skipped this part of the patch for obvious reasons ;-)

This patch fixes
https://bugs.launchpad.net/apparmor/+bug/1426651 and
https://bugs.launchpad.net/apparmor/+bug/1243932


I manually tested that
- c and d log events are still converted to a and w
- aa-logprof handles exec events correctly
- ptrace events no longer crash aa-logprof

Note: add_event_to_tree() is not covered by tests.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-16 01:53:39 +02:00
Christian Boltz
8a475341e8 utils: simplify serialize_parse_profile_start()
Merge from trunk revision 3001

Change serialize_parse_profile_start() to use parse_profile_start()
instead of using duplicated code.

The behaviour is mostly kept, with the exception that the function is
more strict now and raises exceptions instead of ignoring errors.

In practise, this won't change anything because the profiles are parsed
with parse_profile() (which calls parse_profile_start()) - and that
already errors out.

The tests are updated to match the more strict behaviour.

The next step would be to drop serialize_parse_profile_start()
completely, but this isn't urgent and can/should be done when we have
test coverage for serialize_profile_from_old_profile() one day ;-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 19:07:47 -07:00
Christian Boltz
5ca6986b43 utils: fix is_skippable_dir() and add tests
Merge from trunk revision 3000

Fix is_skippable_dir() - the regex also matched things like
/etc/apparmor.d/dont_disable, while it should match on the full
directory name.

Also add some tests based on a real-world aa-logprof run (with "print (path)"
in is_skippable_dir()) and some additional "funny"[tm] dirs.

Needless to say that the tests
        ('dont_disable',                False),
        ('/etc/apparmor.d/cache_foo',   False),
will fail with the old is_skippable_dir().

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 19:00:47 -07:00
Christian Boltz
4b58cf3bc4 utils: replace RE_PROFILE_START
Merge from trunk revision 2999

Replace RE_PROFILE_START with RE_PROFILE_START_2 and adjust all
code sections that used RE_PROFILE_START_2.

The only real change is that test_get_flags_invalid_01 and
test_get_flags_invalid_02 now expect AppArmorException instead of
AppArmorBug.

Acked-by: Steve Beattie <steve@nxnw.org> for trunk
2015-04-13 18:58:25 -07:00
Christian Boltz
a373b4ee93 utils: implement attachment handling after rewriting set_profile_flags()
to use write_header(), and making set_profile_flags
more strict.

Merge from trunk revisions 2996, 2997, and 2998.

Changes in set_profile_flags():
- rewrite set_profile_flags to use parse_profile_start_line() and
  write_header().
- replace the silent failure for non-existing files with a proper
  exception (using lazy programming - the check is done by removing the
  "if os.path.isfile()" check, open_file_read then raises the
  exception ;-)
- comment out regex_hat_flag and the code that was supposed to handle
  hat flags, which were totally broken. We'll need another patch to fix
  it, and we also need to decide if we want to do that because it
  introduces a behaviour change (currently, aa-complain etc. don't
  change hat flags).

The tests for set_profile_flags() are also updated:
- prepend a space to comments because write_header always adds a space
  between '{' and the comment
- remove a test with superfluous quotes that are no longer kept
  (that's
  just a profile cleanup, so dropping that test is the easiest way)
- update test_set_flags_10 and test_set_flags_12 to use the correct
  profile name
- enable the tests for invalid (empty) flags
- update the test for a non-existing file

this patch makes set_profile_flags more strict:
- raise AppArmorBug if newflags contains only whitespace
- raise AppArmorBug if the file doesn't contain the specified profile or
  no profile at all

The tests are adjusted to expect AppArmorBug instead of a silent
failure. Also, some tests are added for profile=None, which means to
change the flags for all profiles in a file.
- test_set_flags_08 is now test_set_flags_invalid_04
- test_set_flags_invalid_03 is changed to only contain one reason for
  a failure, not two ;-)

Finally implement attachment handling

This patch implements attachment handling - aa-logprof now works with
profiles that have an attachment defined, instead of ignoring audit.log
entries for those profiles.

Changes:
- parse_profile_start_line(): remove workaround that merged the
  attachment into the profile name
- parse_profile_data(): store attachment when parsing a profile
- update test_parse_profile_start_03,
  test_serialize_parse_profile_start_03,
  test_set_flags_nochange_09 and some parse_profile_start_line() tests -
  they now expect correct attachment handling

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:53:59 -07:00
Christian Boltz
8d5569f20b utils: rewrite parse_profile_start()
Merge from trunk revision 2990

Rewrite parse_profile_start() in aa.py to a more readable version.
The behaviour remains unchanged (and is covered by tests).

Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-13 18:49:37 -07:00
Christian Boltz
5390777e45 utils: add tests for RE_PROFILE_START_2 and parse_profile_start_line()
Merge from trunk revision 2989

Also add AANamedRegexTest class that can be used to test a regex with
named match groups.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:47:12 -07:00
Christian Boltz
79240e7ddd utils: test new parameters of write_header()
Merge from trunk revision 2988

Change the write_header tests so that the 'profile_keyword' and
'header_comment' parameters can be (and are) tested:
- add a None for both to the existing tests
- add some tests that come with the profile keyword and/or a comment

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:45:05 -07:00
Christian Boltz
494daee246 utils: extend and partially rewrite write_header()
Merge from trunk revision 2987

- add support for prof_data['header_comment'] (comment after '{')
  and prof_data['profile_keyword'] (to force the 'profile' keyword, even
  if it isn't needed) to write_header().
  (set_profile_flags() will be the only user of these two for now)

- fix a crash if depth is not an integer - for example,
      len('   ')/2   # 3 spaces = 1.5
  would cause a crash.
  Also add a test for 1.5 and 1.3 spaces.

- rewrite the handling of flags to avoid we have to maintain two
  different template lines.

- update the tests to set 'profile_keyword' and 'header_comment' to None.
  This avoids big changes in the test code. I'll send another patch that
  makes sure profile_keyword and header_comment are tested ;-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:41:59 -07:00
Christian Boltz
194cbfa94c utils: add attachment to parse_profile_start() return values
Merge from trunk revision 2986

Add the attachment to the parse_profile_start() and
serialize_parse_profile_start() return values, and adjust the functions
calling the *parse_profile_start() functions to save the attachment in
the "attachment" variable (which isn't used yet).

Also adjust the tests for the added return value.

(Sorry for not getting the resultset right from the beginning!)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:36:42 -07:00
Christian Boltz
9452e1e2af utils: Add support for attachments to write_header()
Merge from trunk revision 2985

Also fix a little bug that added the profile keyword if the path needed
quotes (profile "/foo bar" - but "/foo bar" is enough). This was caused
by a regex that always matched on quoted paths (hint: "/ matches
^[^/] ;-)

Also add some tests with attachments and update the test for the bugfix
mentioned above.

Now the remaining part is to make sure that prof_data['attachment'] gets
set when parsing the profiles :-)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:34:33 -07:00
Christian Boltz
1556f782e3 utils: add tests for set_profile_flags() (and some fun)
Merge from trunk commit 2983

Add various tests for set_profile_flags, and document various
interesting[tm] things I discovered while writing the tests (see
the inline comments for details).

Also adds a read_file() function to common_test.py.

The most interesting[tm] thing I found is:
    regex_hat_flag = re.compile('^([a-z]*)\s+([A-Z]*)\s*(#.*)?$')
which matches various unexpected things - but not a hat :-/
(see mailinglist for all funny details)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:31:53 -07:00
Christian Boltz
7d1ff607fe utils: add and use parse_profile_start_line(); convert
serialize_parse_profile_start() to use parse_profile_start_line();
update test-aa.py to match parse_profile_start() and
get_profile_flags() changes

Merge from trunk commits 2978, 2979, and 2982

Add the parse_profile_start_line() function to regex.py, which is
a wrapper for RE_PROFILE_START_2 and returns an array with named matches.

Also change some places in aa.py from using RE_PROFILE_START to
the parse_profile_start_line() function.

Notes: - until everything is migrated to the new function, I'll
keep the old
  RE_PROFILE_START unchanged - that's the reason to add the new
  regex as RE_PROFILE_START_2
- the patch changes only aa.py sections that are covered by tests
  already (which means some users of RE_PROFILE_START are remaining)
- parse_profile_start_line() merges 'profile' and 'attachment' into
  'profile' (aka the old, broken behaviour) until aa.py can handle
  the attachment properly. The alternative would be to ignore
'attachment', which would be worse.

Convert serialize_parse_profile_start() to use
parse_profile_start_line(), and adjust a test to expect an AppArmorBug
instead of an AttributeError exception.

Also add two tests (they succeed with the old and the new code).
Note that these tests document interesting[tm] behaviour - I tend to
think that those cases should raise an exception, but I'm not sure about
this because serialize_profile_from_old_profile() is a good example for
interesting[tm] code :-/

I couldn't come up with a real-world test profile that would hit those
cases without erroring out aa-logprof earlier - maybe the (more
sane-looking) parse_profiles() / serialize_parse_profile_start()
protects us from hitting this interesting[tm] behaviour.

The previous patch slightly changed the behaviour of parse_profile_start()
and get_profile_flags() - they raise AppArmorBug instead of
AppArmorException when specifying a line that is not the start of a
profile and therefore doesn't match RE_PROFILE_START_2.

This patch updates test-aa.py to expect the correct exceptions, and adds
another test with quoted profile name to ensure that stripping the
quotes works as expected.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 18:24:20 -07:00
Steve Beattie
242ece320a utils: merge test-only changes from trunk
Merge from trunk revisions 2976+2980, 2977, 2981, and 2984.
2015-04-13 18:03:55 -07:00
Christian Boltz
dc1d8e5253 add tests for write_header()
Merge from trunk revision 2984

Also add loop support to test-aa.py.

BTW: In case you wonder - the need to replace unittest.TestCase with
AATest is intentional. It might look annoying, but it makes sure that
a test-*.py file doesn't contain a test class where tests = [...] is
ignored because it's still unittest.TestCase.
(Technically, setup_all_tests() will error out if a test class doesn't
contain tests = [...] - either explicit or via its parent AATest.)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:42:40 -07:00
Christian Boltz
0ac23ee34a add tests for serialize_parse_profile_start() to test-aa.py
to document the function's behaviour.
Merge from trunk revision 2981.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:38:08 -07:00
Christian Boltz
5bc15cda41 Convert test-regex_matches.py to the new tests[] loop.
Merge from trunk revision 2977

The test behaviour is the same with and without this patch - 166 tests
run, all successful.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:32:15 -07:00
Christian Boltz
9ebb1913bd add better loop support to common_test.py
Merge from trunk revisions 2976 and 2980

Add better support for looping over a tests[] array to common_test.py:
- class AATest - a base class we can use for all tests, and that will
  probably get more features in the future (for example tempdir
  handling)
- setup_all_tests() - a function that iterates over all classes in the
  given file and calls setup_test_loops() for each of them
- setup_tests_loop() - a function that creates tests based on tests[]
  in the given class. Those tests call the class' _run_test() method for
  each test specified in tests[]  (inspired by setup_regex_tests() ;-)

This means we can get rid of the manually maintained tests list in
test-regex_matches.py and just need to call setup_all_tests() once in
each file.

The patch also adds test-example.py, which is
- a demo of the code added to common_test.py
- a template file that we can copy for future test-*.py

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-13 14:28:48 -07:00
Christian Boltz
720f6624e6 write_net_rules() fixes, part 3
Thanks to the used data structure, write_net_rules() replaces bare
'network,' rules with the invalid 'network all,' when saving a profile.
This patch makes sure a correct 'network,' rule is written.

Also reset 'audit' to avoid all (remaining) rules get the audit flag
after writing an audit network rule.

Note: The first section of the function (that claims to be responsible
for bare 'network,' rules) is probably never hit - but I'm not too keen
to remove it and try it out ;-)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-11 02:21:05 +02:00
Christian Boltz
387de4458f Fix doubled arrow in exec rules
When parsing a profile with named exec rules, the exec target included
the arrow. This resulted in two arrows when writing the profile (and one
more each time the profile was updated).

Fix this by using the match group that only contains the exec target
without the arrow in parse_profile_data() and
serialize_profile_from_old_profile().

References: https://bugs.launchpad.net/apparmor/+bug/1437901


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-04-11 02:16:08 +02:00
Steve Beattie
38a69f5ebc profiles: allow ubuntu-helpers to generate texlive fonts
Merge from trunk revision 3004

When evince opens a dvi file, it updates the user fonts using
texlive commands in /usr/share/texlive/texmf-dist/web2c/ (or possibly
/usr/share/texlive/texmf/web2c/ in older releases). This patch adjusts
the sanitized_helper profile to allow these tools to run.

Bug: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1010909

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2015-04-10 09:52:36 -07:00
Christian Boltz
7d84c61b6c Fix writing network rules, part 2
write_net_rules() doesn't add a space after 'audit' in two of three
cases, leading to invalid network rules.
This patch adds the missing spaces.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9
2015-04-10 01:53:42 +02:00
Christian Boltz
f836ebd42b Fix writing network rules
write_net_rules() creates invalid rules for network rules with one
parameter (for example "network bluetooth").
Add a trailing comma to create valid rules.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9.
2015-04-09 13:29:09 +02:00
Christian Boltz
52b6aeb04c logparser.py: merge path handling in add_event_to_tree()
Merge path handling for 'inode_*' in add_event_to_tree() with the
handling for other path events.

The code is slightly more strict now - 'inode_' in e['operation'] is
replaced with e['operation'].startswith('inode_').

This patch is a cleanup and also a preparation to fix
https://bugs.launchpad.net/apparmor/+bug/1426651 and
https://bugs.launchpad.net/apparmor/+bug/1243932


Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked for both 2.9 and trunk.
2015-04-03 17:45:48 +02:00
Christian Boltz
475a9bc691 honor 'chmod' events in logparser.py / aa-logprof
aa-logprof doesn't ask anything for

type=AVC msg=audit(1427633461.202:281): apparmor="DENIED" operation="chmod" profile="/usr/lib64/firefox/plugin-container" name="/home/cb/.config/ibus/bus/" pid=7779 comm="plugin-containe" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000

This patch fixes this by adding 'chmod' to the list of file operation
types in logparser.py.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
for both trunk and 2.9.
2015-04-03 17:44:38 +02:00
Christian Boltz
0f7bf53afb Tell python2 about math
if 3/2 == 1:
    print("python2 inside")

Add "from __future__ import division" so that python2 returns the
correct result (if needed, as float)

On related news: At least python3 knows how to calculate correctly.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-04-02 23:40:15 +02:00
Jamie Strandboge
8dcd54e365 cherrypick from trunk:
add --include-templates-dir and --include-policy-groups-dir options to easyprof
  to support framework policy on Snappy for Ubuntu Core

  Signed-off-by: Jamie Strandboge <jamie@canonical.com>
  Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-31 16:24:31 -05:00
Steve Beattie
097eb4258f fix two issues for older linux releases
Merge from trunk revision 2975

The following patch addresses two issues on older releases:

1) In trunk commit 2911, the line 'undefine VERBOSE' was added to
   parser/tst/Makefile so that the equality tests would not generate
   verbose output when $VERBOSE != 1. Unfortunately, the 'undefine'
   keyword was not introduced in GNU Make until version 3.82. On
   distro releases like Ubuntu 12.04 LTS that include versions of Make
   older than that, make check and make clean abort when VERBOSE is
   not set to 1. The patch fixes that by setting VERBOSE to a zero
   length string if does not already equal 1.

2) In trunk commit 2923, a workaround for systemd as init was added
   to the pivot_root regression test. The workaround included a
   call to ps(1) to determine if systemd is pid 1. Unfortunately,
   in older versions of the procps package (such as the version in
   Ubuntu 12.04 LTS), 'ps -hp1' emits the warning

     Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html

   The patch below converts the ps call to 'ps hp1' which does not
   generate the warning.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-31 02:50:40 -07:00
Cameron Norman
9bc15eb6b8 profiles: update dnsmasq profile for lxc support
Merge from trunk revision 2974

Patch from Cameron Norman <camerontnorman@gmail.com> based on a patch
from Christian Boltz <apparmor@cboltz.de>.

This patch allows /var/lib/misc/dnsmasq.*.leases rw and
/{,var/}run/lxc/dnsmasq.pid rw for LXC networking setup.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-30 22:26:32 -07:00
Seth Arnold
9d6f7f53cb Add new gdm path for Xauthority file
Bruce Pieterse reports that AppArmor denied evince, among other
applications, from starting properly:
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1432126

He tested a slight variant of the attached patch and reported success. I
propose this patch for both trunk and 2.9.

Signed-off-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 15:32:29 -07:00
Steve Beattie
c1ae887576 tests: work around systemd mounting / shared in pivot_root tests
Merge from trunk revision 2923


The systemd init daemon mounts the / filesystem as shared [1], which
breaks pivot_root(2). The following patch adjusts the pivot_root
test script to remount / as private if it detects that its shared,
allowing the tests to run successfully, and then undoes it once the
tests are complete.

[1] http://cgit.freedesktop.org/systemd/systemd/commit/?id=b3ac5f8cb98757416d8660023d6564a7c411f0a0

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-24 17:12:18 -07:00
Steve Beattie
0ec6ce96d2 parser: fix compilation failure of deny link rules, expand equality tests
Merge from trunk commits 2909, 2910, 2911, and 2912

BugLink: http://bugs.launchpad.net/bugs/1433829

The apparmor_parser fails to compile deny rules with only link
permissions.

  Eg.
       deny /f l,
       deny l /f,
       deny link /f -> /d,

Will all fail to compile with the following assert

  apparmor_parser: aare_rules.cc:99: Node* convert_file_perms(int, uint32_t, uint32_t, bool): Assertion `perms != 0' failed.

NOTE: this is a minimal patch a bigger patch that cleans-up and separates
      and reorganizes file, link, exec, and change_profile rules is needed

parser: Expand Equality tests

This adds several new equality tests and turned up a couple of more
bugs
https://launchpad.net/bugs/1433829
https://launchpad.net/bugs/1434018

- add link/link subset tests
- add pix, Pix, cix, Cix, pux, Pux, cux, Cux and specified profile
  transitions (/f px -> b ...)
- test equality of leading and trailing permission file rules
  ie.   /foo rw, == rw /foo,
- test that specific x match overrides generic x rule. ie.
  /** ix, /foo px, is different than /** ix, /foo ix,
- test that deny removes permission
  /f[abc] r, deny /fb r,  is differnt than /f[abc] r,

In addition to adding the new tests, it changes the output of the
equality tests, so that if the $verbose variable is not set successful
tests only output a period, with failed tests outputing the full
info.  If verbose is set the full test info is output as before.

It also does:

- make the verbose output of equality.sh honor whether or not
  the environment variable VERBOSE is set
- thereby making the output verbose when 'make check V=1' or 'make
  check VERBOSE=1' is given from within the parser/ directory. This
  will make distribution packagers happy when diagnosing build
  failures caused by test failures.
- if verbose output is not emitted and the tests were successful, emit
  a newline before printing PASS.
- verify audit and audit allow is equal
- verify audit differs from deny and audit deny
- verify deny differs from audit deny
- make the verbose text a little more useful for some cases
- correct overlap exec tests to substitute in looped perms

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-23 12:43:57 -07:00
Christian Boltz
8c19eb5521 dovecot auth needs to read openssl.cnf
Darix' guess is that this is needed by libpq because he uses a postgresql
database with dovecot and has ssl enabled in postgresql.

Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.9
2015-03-19 13:58:11 +01:00
Steve Beattie
21a41deabe parser: fix equality and valgrind test scripts to use features file
Merge from trunk commit revision 2907

This patch fixes the equality test script and the valgrind wrapper
script to make the parser under test use the features.all features file
from the features_files/ subdirectory. Otherwise, the equality tests
will fail on systems where the not all of the current language features
are supported. The equality fix does so in a way to make the script work
correctly regardless of the directory it is run from.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-19 04:37:25 -07:00
Steve Beattie
576e8fe33b parser: fix warning in net_find_af_name
Merge from trunk commit 2906

The fix to prevent the compiler from SEGV'ing when dumping network
rules in commit 2888 introduced the following compiler warning:

  network.c: In function ‘const char* net_find_af_name(unsigned int)’:
  network.c:331:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {

The problem is that the counter i is an int, but sizeof returns size_t
which is unsigned. The following patch fixes the issue by converting the
type of i to size_t.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-19 00:14:12 -07:00
Tyler Hicks
3c928c04e1 parser: Test the 'allow' modifier
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-18 12:34:49 -05:00
Tyler Hicks
37b872b155 parser: Test the 'audit allow' modifier
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:44 -05:00
Tyler Hicks
5ab8b7a483 parser: Verify policies change with the audit and deny modifiers
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:41 -05:00
Tyler Hicks
b813f4ba53 parser: Add ability to test the inequality of binary policies
Previously, we only had the ability to test that binary policy files
were equal. This patch allows for the testing of binary policy files
that are not equal.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-18 12:34:38 -05:00
John Johansen
05ab11fec4 Fix compilation of audit modifiers
cherry-pick: -r2901

This fixes the incorrect compilation of audit modifiers for exec and
pivot_root as detailed in

https://launchpad.net/bugs/1431717
https://launchpad.net/bugs/1432045

The permission accumulation routine on the backend was incorrectly setting
the audit mask based off of the exec type bits (info about the exec) and
not the actual exec permission.

This bug could have also caused permissions issues around overlapping exec
generic and exact match exec rules, except the encoding of EXEC_MODIFIERS
ensured that the
  exact_match_allow & AA_USER/OTHER_EXEC_TYPE
  test would never fail for a permission accumulation with the exec permission
  set.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-18 10:22:31 -07:00
Christian Boltz
2d7ba0871f Split off serialize_parse_profile_start_line() from
serialize_profile_from_old_profile() in aa.py, as a preparation to add
tests and then switch to the upcoming RE_PROFILE_START wrapper function.

Besides moving the code, I replaced write_prof_data[profile][hat]['profile']
and write_prof_data[profile][hat]['external'] with function parameters
to avoid that I have to pass around the full write_prof_data.

Note: The "lineno" parameter is technically superfluous - I kept it to
have the parameters as close to parse_profile_start() as possible and
hope that I can merge those functions later (when we have test coverage).


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-03-10 19:09:16 +01:00
Christian Boltz
c98b26069a tools.py: add functions to unload and reload profiles
and change the code to use them

Also add a comment to act() that it's only used by aa-cleanprof.

Note: The new functions add the --base parameter to the apparmor_parser
calls, which also means the disable directory inside the given profile
dir (and not always /etc/apparmor.d/disable) is now honored.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-03-07 20:32:11 +01:00
Christian Boltz
70dc81c4fd merge 'path' if conditions in logparser.py / add_event_to_tree()
logparser.py / add_event_to_tree() has 5 places to handle 'path' events.
This patch merges most if conditions to reduce that to 2 places.

It also makes the matching a bit more strict - instead of using 'in',
'xattr' has to be an exact match and 'file_' is matched with startswith().

Also, 'getattr' is added to the list of file events.


Acked-by: Steve Beattie <steve@nxnw.org> (also for 2.9)



---------- trunk only, unclear for 2.9 --------------
2015-03-07 20:26:32 +01:00
Christian Boltz
1b68baf7a3 let load_include raise an exception if an include file can't be found
instead of ignoring the error silently

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-03-07 13:28:41 +01:00
Christian Boltz
6af7faa2b7 add read_profiles() call to cmd_disable()
Without it, aa-disable
- didn't error out when hitting a broken profile directory
- didn't find a profile if it doesn't use the default naming scheme
  (for example /bin/true profile hiding in bin.false)


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-03-07 13:27:57 +01:00
Steve Beattie
a1529a16bd profiles: add mir abstraction
Merge from trunk revision 2893

As mir has come into use in Ubuntu touch and is available for testing on
Ubuntu desktop, confined apps need access to a few mir specific things.
This patch adds a mir abstraction.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-05 11:51:16 -08:00
Steve Beattie
321a2c1dcb regression tests: fix gcc-5 inline confusion
Merge from trunk revision 2889

Parts of the regression tests that use the do_open() inline function
from changehat.h fail to build under gcc-5 like so:

  cc -g -O0 -Wall -Wstrict-prototypes    changeprofile.c  -lapparmor -o changeprofile /tmp/ccT6GE6k.o: In function `main':
    /home/ubuntu/bzr/apparmor/tests/regression/apparmor/changeprofile.c:43: undefined reference to `do_open'
    collect2: error: ld returned 1 exit status
    <builtin>: recipe for target 'changeprofile' failed

This patch converts the do_open function declaration to be static
inline, which apparently keeps gcc-5 from getting confused.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-03 23:32:26 -08:00
Alain BENEDETTI
735ef5d32b utils/aa-status: don't crash when non-ASCII mountpoints are in use
Merge from trunk revision 2892

aa-status was crashing when parsing through /proc/mounts looking
to see if and where the securityfs synthetic file system is mounted
if there was a mount point that contained characters outside of the
charset in use in the environment of aa-status. This patch fixes the
issue by converting the read of /proc/mounts into a binary read and
then uses decode on the elements.

Patch by Alain BENEDETTI.
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-03 22:25:32 -08:00
Tyler Hicks
9428498d90 parser: Fix error checking of file opening in features_dir_cb()
The error path was being taken when openat() return 0 but openat()
returns -1 on error.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-03 20:28:22 -06:00
Christian Boltz
3ea1e541c7 Add test for disconnected path
As a follow-up to the logparser.py change that converts disconnected
path events to an error, add a testcase to test-logparser.py.


Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-03-03 22:18:24 +01:00
Philip Withnall
29b0634f34 parser: net_find_af_name: do not assume that address families are consecutive,
remove unused net_find_af_val function, and network_families array
Merge from trunk commit 2888.

net_find_af_name: do not assume that address families are consecutive

The network_families array is automatically built from AF_NAMES, which is
extracted from the defines in <bits/socket.h>. The code assumes that
network_families is indexed by the AF defines. However, since the
defines are sparse, and the gaps in the array are not packed with
zeroes, the array is shorter than expected, and the indexing is wrong.

When this function was written, the network families that were
covered might well have been consecutive, but this is no longer true:
there's a gap between AF_LLC (26) and AF_CAN (29).

This assumption caused a crash in our testing while parsing the rule
"network raw".

Remove unused net_find_af_val function, and network_families array

Like net_find_af_name, this assumed that AF_* values were consecutive.

Patches from Philip Withnall and Simon McVittie.
2015-03-03 12:04:13 -08:00
Christian Boltz
586222c94e move strip_quotes() from aa.py to regex.py
The upcoming function parse_profile_start() (which is a wrapper around
the updated RE_PROFILE_START, and will live in regex.py) needs
strip_profile(), but importing it from aa.py fails with an import loop.
Therefore this patch moves strip_quotes() from aa.py to regex.py and
re-imports it into aa.py.

As a bonus, the patch also adds some tests for strip_quotes() ;-)


Also add TestStripQuotes to the test_suite list because it won't run
otherwise.

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9
2015-03-03 20:18:30 +01:00
Christian Boltz
232b51504c let logparser.py parse_event() change disconnected path events to 'ERROR'
This means that aa-logprof will ignore the event instead of crashing with
    AppArmorException: 'Unexpected rank input: var/run/nscd/passwd'

Note that I made the check as specific as possible to be sure it doesn't
hide other events.

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



Acked-by: Steve Beattie <steve@nxnw.org> for 2.9



(This is a backport of trunk r2877, but without the test-capability.py
adjustment because that file doesn't exist in 2.9)
2015-03-03 12:34:47 +01:00
Christian Boltz
df099620dd aa.py: split off parse_profile_start() from parse_profile_data() and add tests
Move the code for parsing the profile start ("/foo {") from aa.py
parse_profile_data() to a separate function parse_profile_start().

Most of the changes are just moving around code, with some small
exceptions:
- instead of handing over profile_data to parse_profile_start() to
  modify it, it sets two variables (pps_set_profile and
  pps_set_hat_external) as part of its return value, which are then
  used in parse_profile_data() to set the flags in profile_data.
- existing_profiles[profile] = file   is executed later, which means
  it used the strip_quotes() version of profile now
- whitespace / tab level changes

The patch also adds some tests for the parse_profile_start() function.



Acked-by: Steve Beattie <steve@nxnw.org> for 2.9 as well.
2015-03-02 21:46:45 +01:00
Christian Boltz
22d647ecb1 Add some tests for aa.py get_profile_flags().
Also adds a check to get_profile_flags() to catch an invalid syntax:
    /foo (  ) {
was accepted by get_profile_flags, while
    /foo () {
failed.

When testing with the parser, both result in a syntax error, therefore
the patch makes sure it also fails in get_profile_flags().


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-03-02 19:38:34 +01:00
Tyler Hicks
07b0886796 parser: Fix "PDEBUG" redefined warning
Only present when building with DEBUG=1.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-02 09:59:17 -06:00
Tyler Hicks
9da31bf281 parser: Fix -Wformat-extra-args warning
Only present when building with DEBUG=1.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 09:59:14 -06:00
Tyler Hicks
c5ff27a91b parser: Send PDEBUG() to stderr
PDEBUG() and PERROR() should both go to stderr.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-02 09:59:11 -06:00
Tyler Hicks
cf4afcb860 parser: Fix return value of dirat_for_each()
Seth pointed out that dirat_for_each() didn't correctly handle the
return value from readdir_r(). On error, it directly returns a positive
errno value. This would have resulted in that positive errno value being
returned, with an undefined errno value set, from dirat_for_each().
However, the dirat_for_each() documentation states that -1 is returned,
with errno set, on error.

This patch results in readdir_r()'s return value being handled
appropriately. In addition, it ensures that 0 is always returned on
success.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 09:54:57 -06:00
Cameron Norman
75a186fa9f profiles: add geary email client to ubuntu-email abstraction
Merge from trunk revision 2876

Merge from Cameron Norman <camerontnorman@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-27 23:28:05 -08:00
Felix Geyer
05bef291d7 profiles: allow aspell access to /usr/share/aspell/
Merge from trunk revision 2875

From: Felix Geyer <debfx@ubuntu.com>

At least Debian/Ubuntu started shipping some aspell files in
/usr/share/aspell/.
For example:
/usr/share/aspell/iso-8859-1.cmap
/usr/share/aspell/iso-8859-1.cset

The abstraction should allow read access to these files.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-27 23:16:32 -08:00
Steve Beattie
76f71f7d84 profiles: add support for /etc/pki/ in ssl certs abstraction
Merge from trunk revision 2874.

These appear to be related to the update-ca-trust tool.

Thanks to Gregor Dschung <dschung@cs.uni-kl.de>
2015-02-27 22:57:41 -08:00
Christian Boltz
34f2c1c6ea cleanup aa-disable handling in tools.py
Remove the check if the disable directory exists. If it's really
missing, it will be auto-created by create_symlink(), so we
automagically fix things instead of annoying the user with an
error message ;-)

Acked-by: Steve Beattie <steve@nxnw.org> for both trunk and 2.9.
2015-02-28 00:25:45 +01:00
Christian Boltz
67dae2f1cf Fix the minitools (aa-audit, aa-complain, aa-enforce, aa-autodep)
to work with multiple profiles at once.

References: https://bugs.launchpad.net/apparmor/+bug/1378095

Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
2015-02-27 14:21:05 +01:00
Seth Arnold
bbaaa00249 parser: fix dbus.cc issue when building with gcc 5
Merge from trunk revision 2868.

This should fix a gcc 5 build failure (untested) with os << .. << os

This build failure was discovered by doko's archive rebuild:
http://people.ubuntuwire.org/~wgrant/rebuild-ftbfs-test/test-rebuild-20150202-gcc5-vivid.html

Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-26 16:18:15 -08:00
Steve Beattie
9ed8789918 parser: fix more gcc 5 compilation problems
Merge from trunk revision 2871

Don't pass an ostream reference into another ostream via <<.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-02-26 15:20:19 -08:00
Christian Boltz
f45628d749 delete traces of program-chunks directory from apparmor.d(5)
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-02-26 18:45:41 +01:00
Christian Boltz
602decfbfc Update is_skippable_file() to match all extensions that are listed in
libapparmor _aa_is_blacklisted() - some extensions were missing in the
python code.

Also make the code more readable and add some testcases.

Notes:
- the original code additionally ignored *.swp. I didn't include that -
  *.swp looks like vim swap files which are also dot files
- the python code ignores README files, but the C code doesn't
  (do we need to add README in the C code?)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for 2.9 and trunk
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-04 13:18:47 +01:00
Christian Boltz
9aa1efd744 Fix aa-unconfined to work with profile names that don't start with / or null
Reported by u on the debian pkg-apparmor-team ML.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-02 20:53:29 +01:00
Jamie Strandboge
c51a68eaaf Description: Allow writes to /{,var}/run/systemd/journal/dev-log, the systemd
journal socket. On Debian and Ubuntu systems, /dev/log is a symlink to
 /run/systemd/journal/dev-log, so this access is now required in the base
 abstraction to maintain current behavior.
Bug: https://bugs.launchpad.net/apparmor/+bug/1413232

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-21 13:37:49 -06:00
Christian Boltz
49b739b184 Add some tests for logparser.py based on the log lines from
https://bugs.launchpad.net/apparmor/+bug/1399027

Also move some existing tests from aa_test.py to test-logparser.py and
adds checks for RE_LOG_v2_6_audit and RE_LOG_v2_6_syslog to them.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-01-18 14:57:10 +01:00
Christian Boltz
53d071adf5 update logparser.py to support the changed syslog format by adding
(audit:\s+)?   to RE_LOG_v2_6_syslog

References: https://bugs.launchpad.net/apparmor/+bug/1399027


Acked-by: Seth Arnold <seth.arnold@canonical.com> (for trunk)

Acked-by: Steve Beattie <steve@nxnw.org> for 2.9 as well
2015-01-17 14:35:38 +01:00
Christian Boltz
70cda06789 Fix the dnsmasq profile to allow executing bash to run the --dhcp-script
argument. Also fixed /usr/lib -> /usr/{lib,lib64} to get libvirt
leasehelper script to run even on x86_64.

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

Patch by "Cédric Bosdonnat" <cbosdonnat@suse.com>

Note: the original patch used {lib,lib64} - I changed it to lib{,64} to
match the style we typically use.

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

(backport of trunk r2841)
2014-12-22 17:57:40 +01:00
Christian Boltz
e8ffc1c4e8 update and cleanup usr.sbin.dovecot profile
Add #include <abstractions/dovecot-common> to the usr.sbin.dovecot
profile. Effectively this adds "deny capability block_suspend," which
is the only missing part from
https://bugs.launchpad.net/apparmor/+bug/1296667/

Also remove "capability setgid," (covered by
abstractions/dovecot-common) and "@{PROC}/filesystems r," (part of
abstractions/base).

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

(backport of trunk r2840)
2014-12-22 17:51:02 +01:00
Christian Boltz
09c93be47c Add some missing /run/dovecot/* to usr.lib.dovecot.imap{, -login}
Add the needed permissions as reported in
https://bugs.launchpad.net/apparmor/+bug/1296667/ comment #1
to the usr.lib.dovecot.imap and imap-login profiles.

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

(backport of trunk r2839)
2014-12-22 17:43:54 +01:00
Christian Boltz
ac8d886645 update the mysqld profile in the extras directory to
something that works on my servers ;-)

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

(backport of trunk r2838)
2014-12-22 17:39:29 +01:00
Christian Boltz
ec1dda24d0 fix network rule description in apparmor.d.pod
(backport from trunk r2837)

Acked-by: John Johansen <john.johansen@canonical.com> (for trunk)

Acked-by: Steve Beattie <steve@nxnw.org> (for 2.9)
2014-12-19 13:57:12 +01:00
Steve Beattie
e7e9053598 Update version in preparation for 2.9.2 development. 2014-12-16 13:37:58 -08:00
2630 changed files with 35637 additions and 133285 deletions

148
.gitignore vendored
View File

@@ -1,22 +1,7 @@
apparmor-*
cscope.*
binutils/aa-enabled
binutils/aa-enabled.1
binutils/aa-exec
binutils/aa-exec.1
binutils/aa-features-abi
binutils/aa-features-abi.1
binutils/aa-load
binutils/aa-status
binutils/aa-status.8
binutils/cJSON.o
binutils/po/*.mo
parser/po/*.mo
parser/af_names.h
parser/cap_names.h
parser/generated_cap_names.h
parser/generated_af_names.h
parser/tst_lib
parser/tst_misc
parser/tst_regex
parser/tst_symtab
@@ -27,57 +12,19 @@ parser/parser_version.h
parser/parser_yacc.c
parser/parser_yacc.h
parser/pod2htm*.tmp
parser/af_rule.o
parser/af_unix.o
parser/all_rule.o
parser/common_optarg.o
parser/dbus.o
parser/default_features.o
parser/lib.o
parser/libapparmor_re/aare_rules.o
parser/libapparmor_re/chfa.o
parser/libapparmor_re/expr-tree.o
parser/libapparmor_re/hfa.o
parser/libapparmor_re/libapparmor_re.a
parser/libapparmor_re/parse.o
parser/mount.o
parser/mqueue.o
parser/network.o
parser/parser_alias.o
parser/parser_common.o
parser/parser_include.o
parser/parser_interface.o
parser/parser_lex.o
parser/parser_main.o
parser/parser_merge.o
parser/parser_misc.o
parser/parser_policy.o
parser/parser_regex.o
parser/parser_symtab.o
parser/parser_variable.o
parser/parser_yacc.o
parser/policy_cache.o
parser/profile.o
parser/ptrace.o
parser/rule.o
parser/signal.o
parser/userns.o
parser/io_uring.o
parser/*.7
parser/*.5
parser/*.8
parser/*.7.html
parser/*.5.html
parser/*.8.html
parser/common
parser/apparmor_parser
parser/libapparmor_re/parse.cc
parser/libapparmor_re/regexp.cc
parser/techdoc.aux
parser/techdoc.log
parser/techdoc.pdf
parser/techdoc.toc
profiles/apparmor.d/local/*
!profiles/apparmor.d/local/README
libraries/libapparmor/Makefile
libraries/libapparmor/Makefile.in
libraries/libapparmor/aclocal.m4
@@ -94,41 +41,28 @@ libraries/libapparmor/install-sh
libraries/libapparmor/libtool
libraries/libapparmor/ltmain.sh
libraries/libapparmor/missing
libraries/libapparmor/test-driver
libraries/libapparmor/ylwrap
libraries/libapparmor/doc/Makefile
libraries/libapparmor/doc/Makefile.in
libraries/libapparmor/doc/*.2
libraries/libapparmor/doc/aa_*.3
libraries/libapparmor/include/Makefile
libraries/libapparmor/include/Makefile.in
libraries/libapparmor/include/sys/Makefile
libraries/libapparmor/include/sys/Makefile.in
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
libraries/libapparmor/src/features.o
libraries/libapparmor/src/grammar.lo
libraries/libapparmor/src/grammar.o
libraries/libapparmor/src/kernel.lo
libraries/libapparmor/src/kernel.o
libraries/libapparmor/src/kernel_interface.lo
libraries/libapparmor/src/kernel_interface.o
libraries/libapparmor/src/libaalogparse.lo
libraries/libapparmor/src/libaalogparse.o
libraries/libapparmor/src/libimmunix_warning.lo
libraries/libapparmor/src/policy_cache.lo
libraries/libapparmor/src/policy_cache.o
libraries/libapparmor/src/private.lo
libraries/libapparmor/src/private.o
libraries/libapparmor/src/scanner.lo
libraries/libapparmor/src/scanner.o
libraries/libapparmor/src/libapparmor.pc
libraries/libapparmor/src/libapparmor.la
libraries/libapparmor/src/libimmunix.la
@@ -136,19 +70,7 @@ libraries/libapparmor/src/grammar.c
libraries/libapparmor/src/grammar.h
libraries/libapparmor/src/scanner.c
libraries/libapparmor/src/scanner.h
libraries/libapparmor/src/test-suite.log
libraries/libapparmor/src/tst_aalogmisc
libraries/libapparmor/src/tst_aalogmisc.log
libraries/libapparmor/src/tst_aalogmisc.o
libraries/libapparmor/src/tst_aalogmisc.trs
libraries/libapparmor/src/tst_features
libraries/libapparmor/src/tst_features.log
libraries/libapparmor/src/tst_features.o
libraries/libapparmor/src/tst_features.trs
libraries/libapparmor/src/tst_kernel
libraries/libapparmor/src/tst_kernel.log
libraries/libapparmor/src/tst_kernel.o
libraries/libapparmor/src/tst_kernel.trs
libraries/libapparmor/swig/Makefile
libraries/libapparmor/swig/Makefile.in
libraries/libapparmor/swig/perl/LibAppArmor.bs
@@ -157,34 +79,20 @@ libraries/libapparmor/swig/perl/Makefile
libraries/libapparmor/swig/perl/Makefile.PL
libraries/libapparmor/swig/perl/Makefile.in
libraries/libapparmor/swig/perl/Makefile.perl
libraries/libapparmor/swig/perl/Makefile.perle
libraries/libapparmor/swig/perl/MYMETA.json
libraries/libapparmor/swig/perl/MYMETA.yml
libraries/libapparmor/swig/perl/blib
libraries/libapparmor/swig/perl/libapparmor_wrap.c
libraries/libapparmor/swig/perl/libapparmor_wrap.o
libraries/libapparmor/swig/perl/pm_to_blib
libraries/libapparmor/swig/python/LibAppArmor.py
libraries/libapparmor/swig/python/LibAppArmor.egg-info/
libraries/libapparmor/swig/python/__init__.py
libraries/libapparmor/swig/python/build/
libraries/libapparmor/swig/python/libapparmor_wrap.c
libraries/libapparmor/swig/python/Makefile
libraries/libapparmor/swig/python/Makefile.in
libraries/libapparmor/swig/python/setup.py
libraries/libapparmor/swig/python/test/Makefile
libraries/libapparmor/swig/python/test/Makefile.in
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.bak
libraries/libapparmor/swig/ruby/Makefile.ruby
libraries/libapparmor/swig/ruby/mkmf.log
libraries/libapparmor/testsuite/.deps
libraries/libapparmor/testsuite/.libs
libraries/libapparmor/testsuite/Makefile
@@ -200,32 +108,18 @@ libraries/libapparmor/testsuite/lib/Makefile.in
libraries/libapparmor/testsuite/libaalogparse.test/Makefile
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
libraries/libapparmor/testsuite/test_multi/out
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
changehat/mod_apparmor/.libs
changehat/mod_apparmor/common
changehat/pam_apparmor/common
changehat/tomcat_apparmor/common
utils/common
utils/*.8
utils/*.8.html
utils/*.5
utils/*.5.html
utils/*.tmp
utils/po/*.mo
utils/apparmor/*.pyc
utils/apparmor/rule/*.pyc
utils/apparmor.egg-info/
utils/build/
utils/htmlcov/
utils/test/common_test.pyc
utils/test/.coverage
utils/test/coverage-report.txt
utils/test/htmlcov/
utils/vim/apparmor.vim
utils/vim/apparmor.vim.5
utils/vim/apparmor.vim.5.html
utils/vim/pod2htmd.tmp
tests/regression/apparmor/*.o
tests/regression/apparmor/aa_policy_cache
tests/regression/apparmor/access
tests/regression/apparmor/at_secure
tests/regression/apparmor/attach_disconnected
tests/regression/apparmor/changehat
tests/regression/apparmor/changehat_fail
tests/regression/apparmor/changehat_fork
@@ -240,10 +134,6 @@ tests/regression/apparmor/chgrp
tests/regression/apparmor/chmod
tests/regression/apparmor/chown
tests/regression/apparmor/clone
tests/regression/apparmor/dbus_eavesdrop
tests/regression/apparmor/dbus_message
tests/regression/apparmor/dbus_service
tests/regression/apparmor/dbus_unrequested_reply
tests/regression/apparmor/deleted
tests/regression/apparmor/env_check
tests/regression/apparmor/environ
@@ -254,40 +144,26 @@ tests/regression/apparmor/fchdir
tests/regression/apparmor/fchgrp
tests/regression/apparmor/fchmod
tests/regression/apparmor/fchown
tests/regression/apparmor/fd_inheritance
tests/regression/apparmor/fd_inheritor
tests/regression/apparmor/fork
tests/regression/apparmor/introspect
tests/regression/apparmor/io_uring
tests/regression/apparmor/link
tests/regression/apparmor/link_subset
tests/regression/apparmor/mkdir
tests/regression/apparmor/mmap
tests/regression/apparmor/mount
tests/regression/apparmor/move_mount
tests/regression/apparmor/named_pipe
tests/regression/apparmor/net_finegrained_rcv
tests/regression/apparmor/net_finegrained_snd
tests/regression/apparmor/net_raw
tests/regression/apparmor/open
tests/regression/apparmor/openat
tests/regression/apparmor/pipe
tests/regression/apparmor/pivot_root
tests/regression/apparmor/posix_mq_rcv
tests/regression/apparmor/posix_mq_snd
tests/regression/apparmor/ptrace
tests/regression/apparmor/ptrace_helper
tests/regression/apparmor/pwrite
tests/regression/apparmor/query_label
tests/regression/apparmor/readdir
tests/regression/apparmor/rename
tests/regression/apparmor/rw
tests/regression/apparmor/socketpair
tests/regression/apparmor/swap
tests/regression/apparmor/symlink
tests/regression/apparmor/syscall_chroot
tests/regression/apparmor/syscall_ioperm
tests/regression/apparmor/syscall_iopl
tests/regression/apparmor/syscall_mknod
tests/regression/apparmor/syscall_mlockall
tests/regression/apparmor/syscall_ptrace
@@ -298,20 +174,10 @@ tests/regression/apparmor/syscall_setpriority
tests/regression/apparmor/syscall_setscheduler
tests/regression/apparmor/syscall_sysctl
tests/regression/apparmor/sysctl_proc
tests/regression/apparmor/sysv_mq_rcv
tests/regression/apparmor/sysv_mq_snd
tests/regression/apparmor/tcp
tests/regression/apparmor/transition
tests/regression/apparmor/unix_fd_client
tests/regression/apparmor/unix_fd_server
tests/regression/apparmor/unix_socket
tests/regression/apparmor/unix_socket_client
tests/regression/apparmor/unlink
tests/regression/apparmor/userns
tests/regression/apparmor/userns_setns
tests/regression/apparmor/uservars.inc
tests/regression/apparmor/xattrs
tests/regression/apparmor/xattrs_profile
tests/regression/apparmor/coredump
**/__pycache__/
*.orig
./utils/apparmor/__pycache__

View File

@@ -1,166 +0,0 @@
---
image: ubuntu:latest
# XXX - add a deploy stage to publish man pages, docs, and coverage
# reports
stages:
- build
- test
.ubuntu-before_script:
before_script:
- export DEBIAN_FRONTEND=noninteractive
- apt-get update -qq
- apt-get install --no-install-recommends -y gcc perl liblocale-gettext-perl linux-libc-dev lsb-release make
- lsb_release -a
- uname -a
.install-c-build-deps: &install-c-build-deps
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf autoconf-archive automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
build-all:
stage: build
extends:
- .ubuntu-before_script
artifacts:
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
expire_in: 30 days
untracked: true
paths:
- libraries/libapparmor/
- parser/
- binutils/
- utils/
- changehat/mod_apparmor/
- changehat/pam_apparmor/
- profiles/
script:
- *install-c-build-deps
- cd libraries/libapparmor && ./autogen.sh && ./configure --with-perl --with-python --prefix=/usr && make && cd ../.. || { cat config.log ; exit 1 ; }
- make -C parser
- make -C binutils
- make -C utils
- make -C changehat/mod_apparmor
- make -C changehat/pam_apparmor
- make -C profiles
test-libapparmor:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- *install-c-build-deps
- make -C libraries/libapparmor check
test-parser:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- *install-c-build-deps
- make -C parser check
test-binutils:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- make -C binutils check
test-utils:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter pyflakes3 python3-coverage python3-notify2 python3-psutil python3-setuptools
# See apparmor/apparmor#221
- make -C parser/tst gen_dbus
- make -C parser/tst gen_xtrans
- make -C utils check
- make -C utils/test coverage-regression
artifacts:
paths:
- utils/test/htmlcov/
when: always
test-mod-apparmor:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- make -C changehat/mod_apparmor check
test-profiles:
stage: test
needs: ["build-all"]
extends:
- .ubuntu-before_script
script:
- make -C profiles check-parser
- make -C profiles check-abstractions.d
- make -C profiles check-extras
shellcheck:
stage: test
needs: []
extends:
- .ubuntu-before_script
script:
- apt-get install --no-install-recommends -y file shellcheck xmlstarlet
- shellcheck --version
- './tests/bin/shellcheck-tree --format=checkstyle
| xmlstarlet tr tests/checkstyle2junit.xslt
> shellcheck.xml'
artifacts:
when: always
reports:
junit: shellcheck.xml
# Disabled due to aa-logprof dependency on /sbin/apparmor_parser existing
# - make -C profiles check-profiles
# test-pam_apparmor:
# - stage: test
# - script:
# - cd changehat/pam_apparmor && make check
include:
- template: SAST.gitlab-ci.yml
- template: Secret-Detection.gitlab-ci.yml
variables:
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
.send-to-coverity: &send-to-coverity
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
--form file=@$(ls apparmor-*-cov-int.tar.gz) --form version="$(git describe --tags)"
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
coverity:
stage: .post
extends:
- .ubuntu-before_script
only:
refs:
- master
script:
- apt-get install --no-install-recommends -y curl git texlive-latex-recommended
- *install-c-build-deps
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
- tar xfz /tmp/cov-analysis-linux64.tgz
- COV_VERSION=$(ls -dt cov-analysis-linux64-* | head -1)
- PATH=$PATH:$(pwd)/$COV_VERSION/bin
- make coverity
- *send-to-coverity
artifacts:
paths:
- "apparmor-*.tar.gz"

View File

@@ -1,10 +0,0 @@
# Don't follow source'd scripts
disable=SC1090
disable=SC1091
# dash supports 'local'
disable=SC2039
disable=SC3043
# dash supports 'echo -n'
disable=SC3037

View File

@@ -1,36 +1,31 @@
#
#
.PHONY: all
all:
@echo "*** See README for information how to build AppArmor ***"
exit 1
OVERRIDE_TARBALL=yes
COMMONDIR=common
include ${COMMONDIR}/Make.rules
include common/Make.rules
DIRS=libraries/libapparmor \
binutils \
parser \
DIRS=parser \
profiles \
utils \
libraries/libapparmor \
changehat/mod_apparmor \
changehat/pam_apparmor \
profiles \
tests
# with conversion to git, we don't export from the remote
REPO_URL?=git@gitlab.com:apparmor/apparmor.git
REPO_BRANCH?=master
#REPO_URL?=lp:apparmor
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.9
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"
COVERITY_DIR=cov-int
RELEASE_DIR=apparmor-${VERSION}
__SETUP_DIR?=.
# We create a separate version for tags because git can't handle tags
# with embedded ~s in them. No spaces around '-' or they'll get
# embedded in ${VERSION}
# apparmor version tag format 'vX.Y.ZZ'
# apparmor branch name format 'apparmor-X.Y'
TAG_VERSION="v$(subst ~,-,${VERSION})"
TAG_VERSION=$(subst ~,-,${VERSION})
# Add exclusion entries arguments for tar here, of the form:
# --exclude dir_to_exclude --exclude other_dir
@@ -38,53 +33,38 @@ TAR_EXCLUSIONS=
.PHONY: tarball
tarball: clean
REPO_VERSION=`$(value REPO_VERSION_CMD)` && \
$(MAKE) export_dir __EXPORT_DIR=${RELEASE_DIR} __REPO_VERSION=$${REPO_VERSION} && \
$(MAKE) setup __SETUP_DIR=${RELEASE_DIR} && \
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
make export_dir __EXPORT_DIR=${RELEASE_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
make setup __SETUP_DIR=${RELEASE_DIR} ; \
tar ${TAR_EXCLUSIONS} -cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
.PHONY: snapshot
snapshot: clean
$(eval REPO_VERSION:=$(shell $(value REPO_VERSION_CMD)))
$(eval SNAPSHOT_NAME=apparmor-$(VERSION)~$(shell echo $(REPO_VERSION) | cut -d '-' -f 2-))
$(MAKE) export_dir __EXPORT_DIR=${SNAPSHOT_NAME} __REPO_VERSION=${REPO_VERSION} && \
$(MAKE) setup __SETUP_DIR=${SNAPSHOT_NAME} && \
tar ${TAR_EXCLUSIONS} -cvzf ${SNAPSHOT_NAME}.tar.gz ${SNAPSHOT_NAME}
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
SNAPSHOT_DIR=apparmor-${VERSION}~$${REPO_VERSION} ;\
make export_dir __EXPORT_DIR=$${SNAPSHOT_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
make setup __SETUP_DIR=$${SNAPSHOT_DIR} ; \
tar ${TAR_EXCLUSIONS} -cvzf $${SNAPSHOT_DIR}.tar.gz $${SNAPSHOT_DIR} ;
.PHONY: coverity
coverity: snapshot
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
$(foreach dir, libraries/libapparmor utils, \
cov-build --dir $(COVERITY_DIR) --no-command --fs-capture-search $(SNAPSHOT_NAME)/$(dir); \
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
cov-build --dir $(COVERITY_DIR) -- sh -c \
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
$(MAKE) -C $(SNAPSHOT_NAME)/$(dir);) "
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
.PHONY: export_dir
export_dir:
mkdir $(__EXPORT_DIR)
/usr/bin/git archive --prefix=$(__EXPORT_DIR)/ --format tar $(__REPO_VERSION) | tar xv
echo "$(REPO_URL) $(REPO_BRANCH) $(__REPO_VERSION)" > $(__EXPORT_DIR)/common/.stamp_rev
/usr/bin/bzr export --per-file-timestamps -r $(__REPO_VERSION) $(__EXPORT_DIR) $(REPO_URL)
echo "$(REPO_URL) $(__REPO_VERSION)" > $(__EXPORT_DIR)/common/.stamp_rev
.PHONY: clean
clean:
-rm -rf ${RELEASE_DIR} ./apparmor-${VERSION}~* ${COVERITY_DIR}
-rm -rf ${RELEASE_DIR} ./apparmor-${VERSION}~*
for dir in $(DIRS); do \
$(MAKE) -C $$dir clean; \
make -C $$dir clean; \
done
.PHONY: setup
setup:
cd $(__SETUP_DIR)/libraries/libapparmor && ./autogen.sh
# parser has an extra doc to build
$(MAKE) -C $(__SETUP_DIR)/parser extra_docs
# libraries/libapparmor needs configure to have run before
# building docs
$(foreach dir, $(filter-out libraries/libapparmor tests, $(DIRS)), \
$(MAKE) -C $(__SETUP_DIR)/$(dir) docs;)
.PHONY: tag
tag:
git tag -m 'AppArmor $(VERSION)' -s $(TAG_VERSION)
bzr tag apparmor_${TAG_VERSION}

211
README Normal file
View File

@@ -0,0 +1,211 @@
------------
Introduction
------------
AppArmor protects systems from insecure or untrusted processes by
running them in restricted confinement, while still allowing processes
to share files, exercise privilege and communicate with other processes.
AppArmor is a Mandatory Access Control (MAC) mechanism which uses the
Linux Security Module (LSM) framework. The confinement's restrictions
are mandatory and are not bound to identity, group membership, or object
ownership. The protections provided are in addition to the kernel's
regular access control mechanisms (including DAC) and can be used to
restrict the superuser.
The AppArmor kernel module and accompanying user-space tools are
available under the GPL license (the exception is the libapparmor
library, available under the LGPL license, which allows change_hat(2)
and change_profile(2) to be used by non-GPL binaries).
For more information, you can read the techdoc.pdf (available after
building the parser) and by visiting the http://apparmor.net/ web
site.
-------------
Source Layout
-------------
AppArmor consists of several different parts:
changehat/ source for using changehat with Apache, PAM and Tomcat
common/ common makefile rules
desktop/ empty
kernel-patches/ compatibility patches for various kernel versions
libraries/ libapparmor source and language bindings
parser/ source for parser/loader and corresponding documentation
profiles/ configuration files, reference profiles and abstractions
tests/ regression and stress testsuites
utils/ high-level utilities for working with AppArmor
--------------------------------------
Important note on AppArmor kernel code
--------------------------------------
While most of the kernel AppArmor code has been accepted in the
upstream Linux kernel, a few important pieces were not included. These
missing pieces unfortunately are important bits for AppArmor userspace
and kernel interaction; therefore we have included compatibility
patches in the kernel-patches/ subdirectory, versioned by upstream
kernel (2.6.37 patches should apply cleanly to 2.6.38 source).
Without these patches applied to the kernel, the AppArmor userspace
will not function correctly.
------------------------------------------
Building and Installing AppArmor Userspace
------------------------------------------
To build and install AppArmor userspace on your system, build and install in
the following order.
libapparmor:
$ cd ./libraries/libapparmor
$ sh ./autogen.sh
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
$ make
$ make check
$ make install
[an additional optional argument to libapparmor's configure is --with-ruby, to
generate Ruby bindings to libapparmor.]
Utilities:
$ cd utils
$ make
$ make check
$ make install
parser:
$ cd parser
$ make # depends on libapparmor having been built first
$ make check
$ make install
Apache mod_apparmor:
$ cd changehat/mod_apparmor
$ make # depends on libapparmor having been built first
$ make install
PAM AppArmor:
$ cd changehat/pam_apparmor
$ make # depends on libapparmor having been built first
$ make install
Profiles:
$ cd profiles
$ make
$ make check # depends on the parser having been built first
$ make install
[Note that for the parser and the utils, if you only with to build/use
some of the locale languages, you can override the default by passing
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
-------------------
AppArmor Testsuites
-------------------
A number of testsuites are in the AppArmor sources. Most have documentation on
usage and how to update and add tests. Below is a quick overview of their
location and how to run them.
Regression tests
----------------
For details on structure and adding tests, see
tests/regression/apparmor/README.
To run:
$ cd tests/regression/apparmor (requires root)
$ make
$ sudo make tests
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
Parser tests
------------
For details on structure and adding tests, see parser/tst/README.
To run:
$ cd parser/tst
$ make
$ make tests
Libapparmor
-----------
For details on structure and adding tests, see libraries/libapparmor/README.
$ cd libraries/libapparmor
$ make check
Utils
-----
Tests for the Python utilities exist in the test/ subdirectory.
$ cd utils
$ make check
The aa-decode utility to be tested can be overridden by
setting up environment variable APPARMOR_DECODE; e.g.:
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
Profile checks
--------------
A basic consistency check to ensure that the parser and aa-logprof parse
successfully the current set of shipped profiles. The system or other
parser and logprof can be passed in by overriding the PARSER and LOGPROF
variables.
$ cd profiles
$ make && make check
Stress Tests
------------
To run AppArmor stress tests:
$ make all
Use these:
$ ./change_hat
$ ./child
$ ./kill.sh
$ ./open
$ ./s.sh
Or run all at once:
$ ./stress.sh
Please note that the above will stress the system so much it may end up
invoking the OOM killer.
To run parser stress tests (requires /usr/bin/ruby):
$ ./stress.sh
(see stress.sh -h for options)
-----------------------------------------------
Building and Installing AppArmor Kernel Patches
-----------------------------------------------
TODO
-----------------
Required versions
-----------------
The AppArmor userspace utilities are written with some assumptions about
installed and available versions of other tools. This is a (possibly
incomplete) list of known version dependencies:
The Python utilities require a minimum of Python 2.7 or Python 3.3.
Some utilities (aa-exec, aa-notify and aa-decode) require Perl 5.10.1 or newer.
Most shell scripts are written for POSIX-compatible sh. aa-decode expects
bash, probably version 3.2 and higher.

362
README.md
View File

@@ -1,362 +0,0 @@
# AppArmor
[![Build status](https://gitlab.com/apparmor/apparmor/badges/master/build.svg)](https://gitlab.com/apparmor/apparmor/commits/master)
[![Overall test coverage](https://gitlab.com/apparmor/apparmor/badges/master/coverage.svg)](https://gitlab.com/apparmor/apparmor/pipelines)
[![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/1699/badge)](https://bestpractices.coreinfrastructure.org/projects/1699)
------------
Introduction
------------
AppArmor protects systems from insecure or untrusted processes by
running them in restricted confinement, while still allowing processes
to share files, exercise privilege and communicate with other processes.
AppArmor is a Mandatory Access Control (MAC) mechanism which uses the
Linux Security Module (LSM) framework. The confinement's restrictions
are mandatory and are not bound to identity, group membership, or object
ownership. The protections provided are in addition to the kernel's
regular access control mechanisms (including DAC) and can be used to
restrict the superuser.
The AppArmor kernel module and accompanying user-space tools are
available under the GPL license (the exception is the libapparmor
library, available under the LGPL license, which allows change_hat(2)
and change_profile(2) to be used by non-GPL binaries).
For more information, you can read the techdoc.pdf (available after
building the parser) and by visiting the https://apparmor.net/ web
site.
----------------
Getting in Touch
----------------
Please send all complaints, feature requests, rants about the software,
and questions to the
[AppArmor mailing list](https://lists.ubuntu.com/mailman/listinfo/apparmor).
Bug reports can be filed against the AppArmor project on
[GitLab](https://gitlab.com/apparmor/apparmor/-/issues) or reported to the mailing
list directly for those who wish not to register for an account on
GitLab. See the
[wiki page](https://gitlab.com/apparmor/apparmor/wikis/home#reporting-bugs)
for more information.
Security issues can be filed in GitLab by opening up a new [issue](https://gitlab.com/apparmor/apparmor/-/issues) and selecting the tick box ```This issue is confidential and should only be visible to team members with at least Reporter access.``` or directed to `security@apparmor.net`. Additional details can be found
in the [wiki](https://gitlab.com/apparmor/apparmor/wikis/home#reporting-security-vulnerabilities).
--------------
Privacy Policy
--------------
The AppArmor security project respects users privacy and data and does not collect data from or on its users beyond what is required for a given component to function.
The AppArmor kernel security module will log violations to the audit subsystem, and those will be logged/forwarded/recorded on the user's system(s) according to how the administrator has logging configured. Again this is not forwarded to or collected by the AppArmor project.
The AppArmor userspace tools do not collect information on the system user beyond the logs and information needed to interact with the user. This is not forwarded to, nor collected by the AppArmor project.
Users may submit information as part of an email, bug report or merge request, etc. and that will be recorded as part of the mailing list, bug/issue tracker, or code repository but only as part of a user initiated action.
The AppArmor project does not collect information from contributors beyond their interactions with the AppArmor project, code, and community. However contributors are subject to the terms and conditions and privacy policy of the individual platforms (currently GitLab) should they choose to contribute through those platforms. And those platforms may collect data on the user that the AppArmor project does not.
Currently GitLab requires a user account to submit patches or report bugs and issues. If a contributor does not wish to create an account for these platforms the mailing list is available. Membership in the list is not required. Content from non-list members will be sent to moderation, to ensure that it is on topic, so there may be a delay in choosing to interact in this way.
-------------
Source Layout
-------------
AppArmor consists of several different parts:
```
binutils/ source for basic utilities written in compiled languages
changehat/ source for using changehat with Apache, PAM and Tomcat
common/ common makefile rules
desktop/ empty
kernel-patches/ compatibility patches for various kernel versions
libraries/ libapparmor source and language bindings
parser/ source for parser/loader and corresponding documentation
profiles/ configuration files, reference profiles and abstractions
tests/ regression and stress testsuites
utils/ high-level utilities for working with AppArmor
```
--------------------------------------
Important note on AppArmor kernel code
--------------------------------------
While most of the kernel AppArmor code has been accepted in the
upstream Linux kernel, a few important pieces were not included. These
missing pieces unfortunately are important bits for AppArmor userspace
and kernel interaction; therefore we have included compatibility
patches in the kernel-patches/ subdirectory, versioned by upstream
kernel (2.6.37 patches should apply cleanly to 2.6.38 source).
Without these patches applied to the kernel, the AppArmor userspace
will not function correctly.
------------------------------------------
Building and Installing AppArmor Userspace
------------------------------------------
To build and install AppArmor userspace on your system, build and install in
the following order. Some systems may need to export various python-related
environment variables to complete the build. For example, before building
anything on these systems, use something along the lines of:
```
$ export PYTHONPATH=$(realpath libraries/libapparmor/swig/python)
$ export PYTHON=/usr/bin/python3
$ export PYTHON_VERSION=3
$ export PYTHON_VERSIONS=python3
```
### libapparmor:
```
$ cd ./libraries/libapparmor
$ sh ./autogen.sh
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
$ make
$ make check
$ make install
```
[an additional optional argument to libapparmor's configure is --with-ruby, to
generate Ruby bindings to libapparmor.]
### Binary Utilities:
```
$ cd binutils
$ make
$ make check
$ make install
```
### Parser:
```
$ cd parser
$ make # depends on libapparmor having been built first
$ make check
$ make install
```
### Utilities:
```
$ cd utils
$ make
$ make check PYFLAKES=/usr/bin/pyflakes3
$ make install
```
### Apache mod_apparmor:
```
$ cd changehat/mod_apparmor
$ make # depends on libapparmor having been built first
$ make install
```
### PAM AppArmor:
```
$ cd changehat/pam_apparmor
$ make # depends on libapparmor having been built first
$ make install
```
### Profiles:
```
$ cd profiles
$ make
$ make check # depends on the parser having been built first
$ make install
```
Note that the empty local/* profile sniplets no longer get created by default.
If you want them, run `make local` before running `make check`.
[Note that for the parser, binutils, and utils, if you only wish to build/use
some of the locale languages, you can override the default by passing
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
-------------------
AppArmor Testsuites
-------------------
A number of testsuites are in the AppArmor sources. Most have documentation on
usage and how to update and add tests. Below is a quick overview of their
location and how to run them.
Regression tests
----------------
For details on structure and adding tests, see
tests/regression/apparmor/README.
To run:
### Regression tests - using apparmor userspace installed on host
```
$ cd tests/regression/apparmor (requires root)
$ make USE_SYSTEM=1
$ sudo make tests USE_SYSTEM=1
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
```
### Regression tests - using apparmor userspace from the tree.
- [build libapparmor](#libapparmor)
- [build binutils](#binary-utilities)
- [build apparmor parser](#parser)
- [build Pam apparmor](#pam-apparmor)
```
$ cd tests/regression/apparmor (requires root)
$ make
$ sudo make tests
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
```
Parser tests
------------
For details on structure and adding tests, see parser/tst/README.
To run:
```
$ cd parser/tst
$ make
$ make tests
```
Libapparmor
-----------
For details on structure and adding tests, see libraries/libapparmor/README.
```
$ cd libraries/libapparmor
$ make check
```
Utils
-----
Tests for the Python utilities exist in the test/ subdirectory.
```
$ cd utils
$ make check
```
The aa-decode utility to be tested can be overridden by
setting up environment variable APPARMOR_DECODE; e.g.:
```
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
```
Profile checks
--------------
A basic consistency check to ensure that the parser and aa-logprof parse
successfully the current set of shipped profiles. The system or other
parser and logprof can be passed in by overriding the PARSER and LOGPROF
variables.
```
$ cd profiles
$ make && make check
```
Stress Tests
------------
To run AppArmor stress tests:
```
$ make all
```
Use these:
```
$ ./change_hat
$ ./child
$ ./kill.sh
$ ./open
$ ./s.sh
```
Or run all at once:
```
$ ./stress.sh
```
Please note that the above will stress the system so much it may end up
invoking the OOM killer.
To run parser stress tests (requires /usr/bin/ruby):
```
$ ./stress.sh
```
(see stress.sh -h for options)
Coverity Support
----------------
Coverity scans are available to AppArmor developers at
https://scan.coverity.com/projects/apparmor.
In order to submit a Coverity build for analysis, the cov-build binary
must be discoverable from your PATH. See the "To Setup" section of
https://scan.coverity.com/download?tab=cxx to obtain a pre-built copy of
cov-build.
To generate a compressed tarball of an intermediate Coverity directory:
```
$ make coverity
```
The compressed tarball is written to
apparmor-<SNAPSHOT_VERSION>-cov-int.tar.gz, where <SNAPSHOT_VERSION>
is something like 2.10.90~3328, and must be uploaded to
https://scan.coverity.com/projects/apparmor/builds/new for analysis. You must
include the snapshot version in Coverity's project build submission form, in
the "Project Version" field, so that it is quickly obvious to all AppArmor
developers what snapshot of the AppArmor repository was used for the analysis.
-----------------------------------------------
Building and Installing AppArmor Kernel Patches
-----------------------------------------------
TODO
-----------------
Required versions
-----------------
The AppArmor userspace utilities are written with some assumptions about
installed and available versions of other tools. This is a (possibly
incomplete) list of known version dependencies:
The Python utilities require a minimum of Python 3.3.
The aa-notify tool's Python dependencies can be satisfied by installing the
following packages (Debian package names, other distros may vary):
* python3-notify2
* python3-psutil
Perl is no longer needed since none of the utilities shipped to end users depend
on it anymore.
Most shell scripts are written for POSIX-compatible sh. aa-decode expects
bash, probably version 3.2 and higher.

View File

@@ -1,178 +0,0 @@
# ----------------------------------------------------------------------
# Copyright (c) 2015
# Canonical Ltd. (All rights reserved)
#
# 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.
#
# 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.
# ----------------------------------------------------------------------
NAME=aa-binutils
all:
COMMONDIR=../common/
include $(COMMONDIR)/Make.rules
DESTDIR=/
BINDIR=${DESTDIR}/usr/bin
SBINDIR=${DESTDIR}/usr/sbin
LOCALEDIR=/usr/share/locale
MANPAGES=aa-enabled.1 aa-exec.1 aa-features-abi.1 aa-status.8
WARNINGS = -Wall
CPP_WARNINGS =
ifndef CFLAGS
CFLAGS = -g -O2 -pipe
ifdef DEBUG
CFLAGS += -pg -D DEBUG
endif
ifdef COVERAGE
CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
endif
endif #CFLAGS
EXTRA_CFLAGS = ${CFLAGS} ${CPPFLAGS} ${EXTRA_CXXFLAGS} ${CPP_WARNINGS} $(EXTRA_WARNINGS)
#INCLUDEDIR = /usr/src/linux/include
INCLUDEDIR =
ifdef INCLUDEDIR
CFLAGS += -I$(INCLUDEDIR)
endif
# Internationalization support. Define a package and a LOCALEDIR
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
SRCS = aa_enabled.c aa_load.c
HDRS =
BINTOOLS = aa-enabled aa-exec aa-features-abi
SBINTOOLS = aa-status aa-load
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
ifdef WITH_LIBINTL
AALIB += -lintl
endif
ifdef USE_SYSTEM
# Using the system libapparmor so Makefile dependencies can't be used
LIBAPPARMOR_A =
INCLUDE_APPARMOR =
APPARMOR_H =
LIBAPPARMOR_LDFLAGS =
else
LIBAPPARMOR_SRC = ../libraries/libapparmor/
LOCAL_LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include
LOCAL_LIBAPPARMOR_LDPATH = $(LIBAPPARMOR_SRC)/src/.libs
LIBAPPARMOR_A = $(LOCAL_LIBAPPARMOR_LDPATH)/libapparmor.a
INCLUDE_APPARMOR = -I$(LOCAL_LIBAPPARMOR_INCLUDE)
APPARMOR_H = $(LOCAL_LIBAPPARMOR_INCLUDE)/sys/apparmor.h
LIBAPPARMOR_LDFLAGS = -L$(LOCAL_LIBAPPARMOR_LDPATH)
endif
EXTRA_CFLAGS += $(INCLUDE_APPARMOR)
LDFLAGS += $(LIBAPPARMOR_LDFLAGS)
ifdef V
VERBOSE = 1
endif
ifndef VERBOSE
VERBOSE = 0
endif
ifeq ($(VERBOSE),1)
BUILD_OUTPUT =
Q =
else
BUILD_OUTPUT = > /dev/null 2>&1
Q = @
endif
export Q VERBOSE BUILD_OUTPUT
po/%.pot: %.c
$(MAKE) -C po $(@F) NAME=$* SOURCES=$*.c
# targets arranged this way so that people who don't want full docs can
# pick specific targets they want.
arch: $(BINTOOLS) $(SBINTOOLS)
manpages: $(MANPAGES)
docs: manpages
indep: docs
$(Q)$(MAKE) -C po all
all: arch indep
.PHONY: coverage
coverage:
$(MAKE) clean $(BINTOOLS) $(SBINTOOLS) COVERAGE=1
ifndef USE_SYSTEM
$(LIBAPPARMOR_A):
@if [ ! -f $@ ]; then \
echo "error: $@ is missing. Pick one of these possible solutions:" 1>&2; \
echo " 1) Build against the in-tree libapparmor by building it first and then trying again. See the top-level README for help." 1>&2; \
echo " 2) Build against the system libapparmor by adding USE_SYSTEM=1 to your make command." 1>&2;\
exit 1; \
fi
endif
aa-features-abi: aa_features_abi.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
aa-load: aa_load.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
aa-exec: aa_exec.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
aa-status: aa_status.c cJSON.o $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB) cJSON.o
cJSON.o: cJSON.c cJSON.h
$(CC) $(EXTRA_CFLAGS) -c -o $@ $<
.SILENT: check
.PHONY: check
check: check_pod_files tests
.SILENT: tests
tests: $(BINTOOLS) $(SBINTOOLS) $(TESTS)
echo "no tests atm"
.PHONY: install
install: install-indep install-arch
.PHONY: install-arch
install-arch: arch
install -m 755 -d ${BINDIR}
install -m 755 ${BINTOOLS} ${BINDIR}
install -m 755 -d ${SBINDIR}
ln -sf aa-status ${SBINDIR}/apparmor_status
install -m 755 ${SBINTOOLS} ${SBINDIR}
.PHONY: install-indep
install-indep: indep
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
ifndef VERBOSE
.SILENT: clean
endif
.PHONY: clean
clean: pod_clean
rm -f core core.* *.o *.s *.a *~ *.gcda *.gcno
rm -f gmon.out
rm -f $(BINTOOLS) $(SBINTOOLS) $(TESTS)
$(MAKE) -s -C po clean

View File

@@ -1,103 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd
# essentially adheres to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa-enabled - test whether AppArmor is enabled
=head1 SYNOPSIS
B<aa-enabled> [options]
=head1 DESCRIPTION
B<aa-enabled> is used to determine if AppArmor is enabled.
=head1 OPTIONS
B<aa-enabled> accepts the following arguments:
=over 4
=item -h, --help
Display a brief usage guide.
=item -q, --quiet
Do not output anything to stdout. This option is intended to be used by
scripts that simply want to use the exit code to determine if AppArmor is
enabled.
=item -x, --exclusive
Require AppArmor to have exclusive access to shared LSM interfaces to
be considered enabled.
=back
=head1 EXIT STATUS
Upon exiting, B<aa-enabled> will set its exit status to the following values:
=over 4
=item B<0>
if AppArmor is enabled.
=item B<1>
if AppArmor is not enabled/loaded.
=item B<2>
intentionally not used as an B<aa-enabled> exit status.
=item B<3>
if the AppArmor control files aren't available under /sys/kernel/security/.
=item B<4>
if B<aa-enabled> doesn't have enough privileges to read the apparmor control files.
=item B<10>
AppArmor is enabled but does not have access to shared LSM interfaces.
=item B<64>
if any unexpected error or condition is encountered.
=back
=head1 BUGS
If you find any bugs, please report them at
L<https://gitlab.com/apparmor/apparmor/-/issues>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), aa_is_enabled(2), and L<https://wiki.apparmor.net>.
=cut

View File

@@ -1,97 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd
# essentially adheres to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa-features-abi - Extract, validate and manipulate AppArmor feature abis
=head1 SYNOPSIS
B<aa-features-abi> [OPTIONS] <SOURCE> [OUTPUT OPTIONS]
=head1 DESCRIPTION
B<aa-features-abi> is used to extract a features abi and output to
either stdout or a specified file. A SOURCE_OPTION must be specified.
If an output option is not specified the features abi is written to
stdout.
=head1 OPTIONS
B<aa-features-abi> accepts the following arguments:
=over 4
=item -h, --help
Display a brief usage guide.
=item -d, --debug
show messages with debugging information
=item -v, --verbose
show messages with stats
=back
=head1 SOURCE
=over 4
=item -x, --extract
Extract the features abi for the kernel
=item -f FILE, --file=FILE
Load the features abi from FILE and send it to OUTPUT OPTIONS.
=back
=head1 OUTPUT OPTIONS
=over 4
=item --stdout
Write the features abi to I<stdout>, this is the default if no output option
is specified.
=item -w FILE, --write FILE
Write the features abi to I<FILE>.
=back
=head1 BUGS
If you find any bugs, please report them at
L<https://gitlab.com/apparmor/apparmor/-/issues>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), aa_features(3), and L<https://wiki.apparmor.net>.
=cut

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2015 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*/
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#define _(s) gettext(s)
#include <sys/apparmor.h>
void print_help(const char *command)
{
printf(_("%s: [options]\n"
" options:\n"
" -x | --exclusive Shared interfaces must be available\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"),
command);
exit(1);
}
/* Exit statuses and meanings are documented in the aa-enabled.pod file */
static void exit_with_error(int saved_errno, int quiet)
{
switch(saved_errno) {
case ENOSYS:
if (!quiet)
printf(_("No - not available on this system.\n"));
exit(1);
case ECANCELED:
if (!quiet)
printf(_("No - disabled at boot.\n"));
exit(1);
case ENOENT:
if (!quiet)
printf(_("Maybe - policy interface not available.\n"));
exit(3);
case EPERM:
case EACCES:
if (!quiet)
printf(_("Maybe - insufficient permissions to determine availability.\n"));
exit(4);
case EBUSY:
if (!quiet)
printf(_("Partially - public shared interfaces are not available.\n"));
exit(10);
}
if (!quiet)
printf(_("Error - %s\n"), strerror(saved_errno));
exit(64);
}
int main(int argc, char **argv)
{
int i, enabled;
int quiet = 0;
int require_shared = 0;
setlocale(LC_MESSAGES, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc > 3) {
printf(_("unknown or incompatible options\n"));
print_help(argv[0]);
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--quiet") == 0 ||
strcmp(argv[i], "-q") == 0) {
quiet = 1;
} else if (strcmp(argv[i], "--exclusive") == 0 ||
strcmp(argv[i], "-x") == 0) {
require_shared = 1;
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
print_help(argv[0]);
} else {
printf(_("unknown option '%s'\n"), argv[1]);
print_help(argv[0]);
}
}
enabled = aa_is_enabled();
if (!enabled) {
if (require_shared || errno != EBUSY)
exit_with_error(errno, quiet);
}
if (!quiet)
printf(_("Yes\n"));
exit(0);
}

View File

@@ -1,232 +0,0 @@
/*
* Copyright (c) 2015
* Canonical, Ltd. (All rights reserved)
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <errno.h>
#include <getopt.h>
#include <libintl.h>
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/apparmor.h>
#include <sys/types.h>
#include <unistd.h>
#define _(s) gettext(s)
static const char *opt_profile = NULL;
static const char *opt_namespace = NULL;
static bool opt_debug = false;
static bool opt_immediate = false;
static bool opt_verbose = false;
static pid_t pid = 0;
static void usage(const char *name, bool error)
{
FILE *stream = stdout;
int status = EXIT_SUCCESS;
if (error) {
stream = stderr;
status = EXIT_FAILURE;
}
fprintf(stream,
_("USAGE: %s [OPTIONS] <prog> <args>\n"
"\n"
"Confine <prog> with the specified PROFILE.\n"
"\n"
"OPTIONS:\n"
" -p PROFILE, --profile=PROFILE PROFILE to confine <prog> with\n"
" -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine <prog> in\n"
" -d, --debug show messages with debugging information\n"
" -i, --immediate change profile immediately instead of at exec\n"
" -v, --verbose show messages with stats\n"
" -h, --help display this help\n"
"\n"), name);
exit(status);
}
#define error(fmt, args...) _error(_("[%ld] aa-exec: ERROR: " fmt "\n"), (long)pid, ## args)
static void _error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
#define debug(fmt, args...) _debug(_("[%ld] aa-exec: DEBUG: " fmt "\n"), (long)pid, ## args)
static void _debug(const char *fmt, ...)
{
va_list args;
if (!opt_debug)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#define verbose(fmt, args...) _verbose(_("[%ld] " fmt "\n"), (long)pid, ## args)
static void _verbose(const char *fmt, ...)
{
va_list args;
if (!opt_verbose)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static void verbose_print_argv(char **argv)
{
if (!opt_verbose)
return;
fprintf(stderr, _("[%ld] exec"), (long)pid);
for (; *argv; argv++)
fprintf(stderr, " %s", *argv);
fprintf(stderr, "\n");
}
static char **parse_args(int argc, char **argv)
{
int opt;
struct option long_opts[] = {
{"debug", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"profile", required_argument, 0, 'p'},
{"namespace", required_argument, 0, 'n'},
{"immediate", no_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
};
while ((opt = getopt_long(argc, argv, "+dhp:n:iv", long_opts, NULL)) != -1) {
switch (opt) {
case 'd':
opt_debug = true;
break;
case 'h':
usage(argv[0], false);
break;
case 'p':
if (opt_profile)
error("Multiple -p/--profile parameters given");
opt_profile = optarg;
break;
case 'n':
if (opt_namespace)
error("Multiple -n/--namespace parameters given");
opt_namespace = optarg;
break;
case 'i':
opt_immediate = true;
break;
case 'v':
opt_verbose = true;
break;
default:
usage(argv[0], true);
break;
}
}
if (optind >= argc)
usage(argv[0], true);
return argv + optind;
}
static void build_name(char *name, size_t name_len,
const char *namespace, const char *profile)
{
size_t required_len = 1; /* reserve 1 byte for NUL-terminator */
if (namespace)
required_len += 1 + strlen(namespace) + 3; /* :<NAMESPACE>:// */
if (profile)
required_len += strlen(profile);
if (required_len > name_len)
error("name too long (%zu > %zu)", required_len, name_len);
name[0] = '\0';
if (namespace) {
strcat(name, ":");
strcat(name, namespace);
strcat(name, "://");
}
if (profile)
strcat(name, profile);
}
int main(int argc, char **argv)
{
char name[PATH_MAX];
int rc = 0;
/* IMPORTANT: pid must be initialized before doing anything else since
* it is used in a global context when printing messages
*/
pid = getpid();
argv = parse_args(argc, argv);
if (opt_namespace || opt_profile)
build_name(name, sizeof(name), opt_namespace, opt_profile);
else
goto exec;
if (opt_immediate) {
verbose("aa_change_profile(\"%s\")", name);
rc = aa_change_profile(name);
debug("%d = aa_change_profile(\"%s\")", rc, name);
} else {
verbose("aa_change_onexec(\"%s\")", name);
rc = aa_change_onexec(name);
debug("%d = aa_change_onexec(\"%s\")", rc, name);
}
if (rc) {
if (errno == ENOENT) {
error("%s '%s' does not exist",
opt_profile ? "profile" : "namespace", name);
} else if (errno == EACCES) {
error("insufficient permissions to change to the %s '%s'",
opt_profile ? "profile" : "namespace", name);
} else if (errno == EINVAL) {
error("AppArmor interface not available");
} else {
error("%m");
}
}
exec:
verbose_print_argv(argv);
execvp(argv[0], argv);
error("Failed to execute \"%s\": %m", argv[0]);
}

View File

@@ -1,207 +0,0 @@
/*
* Copyright (c) 2020
* Canonical, Ltd. (All rights reserved)
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Canonical Ltd.
*/
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <libintl.h>
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/apparmor.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define _(s) gettext(s)
#include "../libraries/libapparmor/src/private.h"
static const char *progname = NULL;
static const char *opt_file = NULL;
static const char *opt_write = NULL;
static bool opt_debug = false;
static bool opt_verbose = false;
static bool opt_extract = false;
static void usage(const char *name, bool error)
{
FILE *stream = stdout;
int status = EXIT_SUCCESS;
if (error) {
stream = stderr;
status = EXIT_FAILURE;
}
fprintf(stream,
_("USAGE: %s [OPTIONS] <SOURCE> [OUTPUT OPTIONS]\n"
"\n"
"Output AppArmor feature abi from SOURCE to OUTPUT"
"\n"
"OPTIONS:\n"
#if 0
" -d, --debug show messages with debugging information\n"
" -v, --verbose show messages with stats\n"
#endif
" -h, --help display this help\n"
"SOURCE:\n"
" -f F, --file=F load features abi from file F\n"
" -x, --extract extract features abi from the kernel\n"
"OUTPUT OPTIONS:\n"
" --stdout default, write features to stdout\n"
" -w F, --write=F write features abi to the file F instead of stdout\n"
"\n"), name);
exit(status);
}
#define error(fmt, args...) _error(_("%s: ERROR: " fmt " - %m\n"), progname, ## args)
static void _error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
#if 0
#define debug(fmt, args...) _debug(_("%s: DEBUG: " fmt "\n"), progname, ## args)
static void _debug(const char *fmt, ...)
{
va_list args;
if (!opt_debug)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#define verbose(fmt, args...) _verbose(_(fmt "\n"), ## args)
static void _verbose(const char *fmt, ...)
{
va_list args;
if (!opt_verbose)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#endif
#define ARG_STDOUT 128
static char **parse_args(int argc, char **argv)
{
int opt;
struct option long_opts[] = {
{"debug", no_argument, 0, 'd'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"extract", no_argument, 0, 'x'},
{"file", required_argument, 0, 'f'},
{"write", required_argument, 0, 'w'},
{"stdout", no_argument, 0, ARG_STDOUT},
};
while ((opt = getopt_long(argc, argv, "+dvhxf:l:w:", long_opts, NULL)) != -1) {
switch (opt) {
case 'd':
opt_debug = true;
break;
case 'v':
opt_verbose = true;
break;
case 'h':
usage(argv[0], false);
break;
case 'x':
opt_extract = true;
break;
case 'f':
opt_file = optarg;
break;
case 'w':
opt_write = optarg;
break;
case ARG_STDOUT:
opt_write = NULL;
break;
default:
usage(argv[0], true);
break;
}
}
return argv + optind;
}
/* TODO: add features intersection and testing */
int main(int argc, char **argv)
{
struct aa_features *features;
autoclose int in = -1;
autoclose int out = -1;
int rc = 0;
progname = argv[0];
argv = parse_args(argc, argv);
if (!opt_extract && !opt_file)
usage(argv[0], true);
if (opt_extract && opt_file) {
error("options --extract and --file are mutually exclusive");
}
if (opt_extract) {
rc = aa_features_new_from_kernel(&features);
if (rc == -1)
error("failed to extract features abi from the kernel");
}
if (opt_file) {
in = open(opt_file, O_RDONLY);
if (in == -1)
error("failed to open file '%s'", opt_file);
rc = aa_features_new_from_file(&features, in);
if (rc == -1)
error("failed to load features abi from file '%s'", opt_file);
}
if (opt_write) {
out = open(opt_write, O_WRONLY | O_CREAT, 00600);
if (out == -1)
error("failed to open output file '%s'", opt_write);
} else {
out = fileno(stdout);
if (out == -1)
error("failed to get stdout");
}
rc = aa_features_write_to_fd(features, out);
if (rc == -1)
error("failed to write features abi");
return 0;
}

View File

@@ -1,408 +0,0 @@
/*
* Copyright (C) 2020 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*/
#define _GNU_SOURCE /* for asprintf() */
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/apparmor.h>
#include <libintl.h>
#define _(s) gettext(s)
/* TODO: implement config locations - value can change */
#define DEFAULT_CONFIG_LOCATIONS "/etc/apparmor/parser.conf"
#define DEFAULT_POLICY_LOCATIONS "/var/cache/apparmor:/etc/apparmor.d/cache.d:/etc/apparmor.d/cache"
#define CACHE_FEATURES_FILE ".features"
bool opt_debug = false;
bool opt_verbose = false;
bool opt_dryrun = false;
bool opt_force = false;
bool opt_config = false;
#define warning(fmt, args...) _error(_("aa-load: WARN: " fmt "\n"), ## args)
#define error(fmt, args...) _error(_("aa-load: ERROR: " fmt "\n"), ## args)
static void _error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#define verbose(fmt, args...) _debug(opt_verbose, _(fmt "\n"), ## args)
#define debug(fmt, args...) _debug(opt_debug, _("aa-load: DEBUG: " fmt "\n"), ## args)
static void _debug(bool opt_displayit, const char *fmt, ...)
{
va_list args;
if (!opt_displayit)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static int have_enough_privilege(const char *command)
{
uid_t uid, euid;
uid = getuid();
euid = geteuid();
if (uid != 0 && euid != 0) {
error("%s: Sorry. You need root privileges to run this program.\n",
command);
return EPERM;
}
if (uid != 0 && euid == 0) {
error("%s: Aborting! You've set this program setuid root.\n"
"Anybody who can run this program can update "
"your AppArmor profiles.\n", command);
exit(EXIT_FAILURE);
}
return 0;
}
static int load_config(const char *file)
{
/* TODO */
return ENOENT;
}
/**
* load a single policy cache file to the kernel
*/
static int load_policy_file(const char *file)
{
int rc = 0;
struct aa_kernel_interface *kernel_interface;
if (aa_kernel_interface_new(&kernel_interface, NULL, NULL)) {
rc = -errno;
error("Failed to open kernel interface '%s': %m", file);
return rc;
}
if (!opt_dryrun &&
aa_kernel_interface_replace_policy_from_file(kernel_interface,
AT_FDCWD, file)) {
rc = -errno;
error("Failed to load policy into kernel '%s': %m", file);
}
aa_kernel_interface_unref(kernel_interface);
return rc;
}
static void validate_features(const char *dir_path)
{
aa_features *kernel_features;
if (aa_features_new_from_kernel(&kernel_features) == -1) {
error("Failed to obtain features: %m");
return;
}
if (aa_features_check(AT_FDCWD, dir_path, kernel_features) == -1) {
if (errno == ENOENT) {
/* features file does not exist
* not an issue when loading cache policies from dir
*/
}
else if (errno == EEXIST) {
warning("Overlay features do not match kernel features");
}
}
aa_features_unref(kernel_features);
}
/**
* load a directory of policy cache files to the kernel
* This does not do a subdir search to find the kernel match but
* tries to load the dir regardless of whether its features match
*
* The hierarchy looks like
*
* dir/
* .features
* profile1
* ...
*/
static int load_policy_dir(const char *dir_path)
{
DIR *d;
struct dirent *dir;
int rc = 0;
char *file;
size_t len;
validate_features(dir_path);
d = opendir(dir_path);
if (!d) {
rc = -errno;
error("Failed to open directory '%s': %m", dir_path);
return rc;
}
while ((dir = readdir(d)) != NULL) {
/* Only check regular files for now */
if (dir->d_type == DT_REG) {
len = strnlen(dir->d_name, PATH_MAX);
/* Ignores .features */
if (strncmp(dir->d_name, CACHE_FEATURES_FILE, len) == 0) {
continue;
}
if (asprintf(&file, "%s/%s", dir_path, dir->d_name) == -1) {
error("Failure allocating memory");
closedir(d);
return -1;
}
load_policy_file(file);
free(file);
file = NULL;
}
}
closedir(d);
return 0;
}
/**
* load_hashed_policy - find policy hashed dir and load it
*
* load/replace all policy from a policy hierarchy directory
*
* Returns: 0 on success < -errno
*
* It will find the subdir that matches the kernel and load all
* precompiled policy files from it.
*
* The hierarchy looks something like
*
* location/
* kernel_hash1.0/
* .features
* profile1
* ...
* kernel_hash2.0/
* .features
* profile1
* ...
*/
static int load_policy_by_hash(const char *location)
{
aa_policy_cache *policy_cache = NULL;
int rc;
if ((rc = aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, location, 0))) {
rc = -errno;
error("Failed to open policy cache '%s': %m", location);
return rc;
}
if (opt_debug) {
/* show hash directory under location that matches the
* current kernel
*/
char *cache_loc = aa_policy_cache_dir_path_preview(NULL, AT_FDCWD, location);
if (!cache_loc) {
rc = -errno;
error("Failed to find cache location '%s': %m", location);
goto out;
}
debug("Loading cache from '%s'\n", cache_loc);
free(cache_loc);
}
if (!opt_dryrun) {
if ((rc = aa_policy_cache_replace_all(policy_cache, NULL)) < 0) {
error("Failed to load policy cache '%s': %m", location);
} else {
verbose("Success - Loaded policy cache '%s'", location);
}
}
out:
aa_policy_cache_unref(policy_cache);
return rc;
}
/**
* load_arg - calls specific load functions for files and directories
*
* load/replace all policy files/dir in arg
*
* Returns: 0 on success, 1 on failure.
*
* It will load by hash subtree first, and fallback to a cache dir
* If not a directory, it will try to load it as a cache file
*/
static int load_arg(char *arg)
{
char **location = NULL;
int i, n, rc = 0;
/* arg can specify an overlay of multiple cache locations */
if ((n = aa_split_overlay_str(arg, &location, 0, true)) == -1) {
error("Failed to parse overlay locations: %m");
return 1;
}
for (i = 0; i < n; i++) {
struct stat st;
debug("Trying to open %s", location[i]);
if (stat(location[i], &st) == -1) {
error("Failed stat of '%s': %m", location[i]);
rc = 1;
continue;
}
if (S_ISDIR(st.st_mode)) {
/* try hash dir subtree first */
if (load_policy_by_hash(location[i]) < 0) {
error("Failed load policy by hash '%s': %m", location[i]);
rc = 1;
}
/* fall back to cache dir */
if (load_policy_dir(location[i]) < 0) {
error("Failed load policy by directory '%s': %m", location[i]);
rc = 1;
}
} else if (load_policy_file(location[i]) < 0) {
rc = 1;
}
}
for (i = 0; i < n; i++)
free(location[i]);
free(location);
return rc;
}
static void print_usage(const char *command)
{
printf("Usage: %s [OPTIONS] (cache file|cache dir|cache base dir)]*\n"
"Load Precompiled AppArmor policy from a cache location or \n"
"locations.\n\n"
"Options:\n"
" -f, --force load policy even if abi does not match the kernel\n"
" -d, --debug display debug messages\n"
" -v, --verbose display progress and error messages\n"
" -n, --dry-run do everything except actual load\n"
" -h, --help this message\n",
command);
}
static const char *short_options = "c:dfvnh";
struct option long_options[] = {
{"config", 1, 0, 'c'},
{"debug", 0, 0, 'd'},
{"force", 0, 0, 'f'},
{"verbose", 0, 0, 'v'},
{"dry-run", 0, 0, 'n'},
{"help", 0, 0, 'h'},
{NULL, 0, 0, 0},
};
static int process_args(int argc, char **argv)
{
int c, o;
opterr = 1;
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1) {
switch(c) {
case 0:
error("error in argument processing\n");
exit(1);
break;
case 'd':
opt_debug = true;
break;
case 'f':
opt_force = true;
break;
case 'v':
opt_verbose = true;
break;
case 'n':
opt_dryrun = true;
break;
case 'h':
print_usage(argv[0]);
exit(0);
break;
case 'c':
/* TODO: reserved config location,
* act as a bad arg for now, when added update usage
*/
//opt_config = true; uncomment when implemented
/* Fall through */
default:
error("unknown argument: '%s'\n\n", optarg);
print_usage(argv[1]);
exit(1);
break;
}
}
return optind;
}
int main(int argc, char **argv)
{
int i, rc = 0;
optind = process_args(argc, argv);
if (!opt_dryrun && have_enough_privilege(argv[0]))
return 1;
/* if no location use the default one */
if (optind == argc) {
if (!opt_config && load_config(DEFAULT_CONFIG_LOCATIONS) == 0) {
verbose("Loaded policy config");
}
if ((rc = load_arg(DEFAULT_POLICY_LOCATIONS)))
verbose("Loading policy from default location '%s'", DEFAULT_POLICY_LOCATIONS);
else
debug("No policy specified, and no policy config or policy in default locations");
}
for (i = optind; i < argc; i++) {
/* Try to load all policy locations even if one fails
* but always return an error if any fail
*/
int tmp = load_arg(argv[i]);
if (!rc)
rc = tmp;
}
return rc;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,293 +0,0 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 13
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable adress area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
# ----------------------------------------------------------------------
# Copyright (C) 2015 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
# ----------------------------------------------------------------------
all:
# As translations get added, they will automatically be included, unless
# the lang is explicitly added to DISABLED_LANGS; e.g. DISABLED_LANGS=en es
DISABLED_LANGS=
COMMONDIR=../../common
include $(COMMONDIR)/Make-po.rules
XGETTEXT_ARGS+=--language=C --keyword=_ $(shell if [ -f ${NAME}.pot ] ; then echo -n -j ; fi)

View File

@@ -1,66 +0,0 @@
# Copyright (C) 2015 Canonical Ltd
# This file is distributed under the same license as the AppArmor package.
# John Johansen <john.johansen@canonical.com>, 2015.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr ""
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr ""
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr ""
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr ""
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr ""
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr ""

View File

@@ -1,73 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_enabled.c:21
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -x | --exclusive Shared interfaces must be available\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:37
#, c-format
msgid "No - not available on this system.\n"
msgstr ""
#: ../aa_enabled.c:41
#, c-format
msgid "No - disabled at boot.\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:50
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:54
#, c-format
msgid "Partially - public shared interfaces are not available.\n"
msgstr ""
#: ../aa_enabled.c:58
#, c-format
msgid "Error - %s\n"
msgstr ""
#: ../aa_enabled.c:73
#, c-format
msgid "unknown or incompatible options\n"
msgstr ""
#: ../aa_enabled.c:87
#, c-format
msgid "unknown option '%s'\n"
msgstr ""
#: ../aa_enabled.c:98
#, c-format
msgid "Yes\n"
msgstr ""

View File

@@ -1,55 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_exec.c:50
#, c-format
msgid ""
"USAGE: %s [OPTIONS] <prog> <args>\n"
"\n"
"Confine <prog> with the specified PROFILE.\n"
"\n"
"OPTIONS:\n"
" -p PROFILE, --profile=PROFILE\t\tPROFILE to confine <prog> with\n"
" -n NAMESPACE, --namespace=NAMESPACE\tNAMESPACE to confine <prog> in\n"
" -d, --debug\t\t\t\tshow messages with debugging information\n"
" -i, --immediate\t\t\tchange profile immediately instead of at exec\n"
" -v, --verbose\t\t\t\tshow messages with stats\n"
" -h, --help\t\t\t\tdisplay this help\n"
"\n"
msgstr ""
#: ../aa_exec.c:65
#, c-format
msgid "[%ld] aa-exec: ERROR: "
msgstr ""
#: ../aa_exec.c:76
#, c-format
msgid "[%ld] aa-exec: DEBUG: "
msgstr ""
#: ../aa_exec.c:89
#, c-format
msgid "[%ld] "
msgstr ""
#: ../aa_exec.c:107
#, c-format
msgid "[%ld] exec"
msgstr ""

View File

@@ -1,51 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_features_abi.c:53
#, c-format
msgid ""
"USAGE: %s [OPTIONS] <SOURCE> [OUTPUT OPTIONS]\n"
"\n"
"Output AppArmor feature abi from SOURCE to OUTPUT\n"
"OPTIONS:\n"
" -d, --debug show messages with debugging information\n"
" -v, --verbose show messages with stats\n"
" -h, --help display this help\n"
"SOURCE:\n"
" -f F, --file=F load features abi from file F\n"
" -x, --extract extract features abi from the kernel\n"
"OUTPUT OPTIONS:\n"
" --stdout default, write features to stdout\n"
" -w F, --write=F write features abi to the file F instead of stdout\n"
"\n"
msgstr ""
#: ../aa_features_abi.c:73
#, c-format
msgid "%s: ERROR: "
msgstr ""
#: ../aa_features_abi.c:85
#, c-format
msgid "%s: DEBUG: "
msgstr ""
#: ../aa_features_abi.c:98
msgid "\n"
msgstr ""

View File

@@ -1,71 +0,0 @@
# Afrikaans translation for apparmor
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2020-03-04 17:55+0000\n"
"Last-Translator: bernard stafford <Unknown>\n"
"Language-Team: Afrikaans <af@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2020-03-05 05:40+0000\n"
"X-Generator: Launchpad (build e0878392dc799b267dea80578fa65500a5d74155)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [opsies]\n"
" opsies:\n"
" -q | --quiet Moenie druk uit enige boodskappe\n"
" -h | --help Afdruk hulp\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "onbekende of onversoenbare opsies\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "onbekende opsie '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ja\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Geen - nie beskikbaar op hierdie stelsel.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Nee - gestremde by stewel.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Miskien - beleid koppelvlak nie beskikbaar.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Miskien - onvoldoende toestemmings om beskikbaarheid te bepaal.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Fout - '%s'\n"

View File

@@ -1,73 +0,0 @@
# German translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2018-02-09 23:55+0000\n"
"Last-Translator: Tobias Bannert <tobannert@gmail.com>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
"Language: de\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [Optionen]\n"
" Optionen:\n"
" -q | --quiet Keine Nachrichten anzeigen\n"
" -h | --help Hilfetext anzeigen\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "unbekannte oder nicht kompatible Optionen\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "unbekannte Option »%s«\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ja\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Nein auf diesem System nicht verfügbar.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Nein beim Start deaktiviert.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Vielleicht Richtlinienschnittstelle nicht verfügbar.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
"Vielleicht ungenügende Berechtigungen, um die Verfügbarkeit zu prüfen\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Fehler »%s«\n"

View File

@@ -1,72 +0,0 @@
# English (United Kingdom) translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-02-18 06:22+0000\n"
"Last-Translator: Andi Chandler <Unknown>\n"
"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
"Language: en_GB\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "unknown or incompatible options\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "unknown option '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Yes\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "No - not available on this system.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "No - disabled at boot.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Maybe - policy interface not available.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Maybe - insufficient permissions to determine availability.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Error - '%s'\n"

View File

@@ -1,71 +0,0 @@
# Spanish translation for apparmor
# Copyright (c) 2019 Rosetta Contributors and Canonical Ltd 2019
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2019-06-09 14:01+0000\n"
"Last-Translator: Adolfo Jayme <fitoschido@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-06-10 04:32+0000\n"
"X-Generator: Launchpad (build 18978)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [opciones]\n"
" opciones:\n"
" -q | --quiet No emitir ningún mensaje\n"
" -h | --help Mostrar la ayuda\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "opciones desconocidas o incompatibles\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "se desconoce la opción «%s»\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Sí\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "No; no disponible en este sistema.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "No; desactivado durante el arranque.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Quizá; interfaz de directiva no disponible.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Quizá; permisos insuficientes para determinar disponibilidad.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Error: «%s»\n"

View File

@@ -1,67 +0,0 @@
# Persian translation for apparmor
# Copyright (c) 2019 Rosetta Contributors and Canonical Ltd 2019
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2019-12-27 08:16+0000\n"
"Last-Translator: VahidNameni <Unknown>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-12-28 05:38+0000\n"
"X-Generator: Launchpad (build bceb5ef013b87ef7aafe0755545ceb689ca7ac60)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "تنظیم نامعلوم یا ناسازگار\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "تنظیم '%s' ناشناخته است\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "بله\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "خیر- در این سیستم موجود نیست.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "خیر - غیرفعال در زمان boot.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "شاید - رابط سیاست گذاری در دسترس نیست.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "شاید - دسترسی ناکافی جهت شناسایی در دسترس پذیری.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "خطا - '%s'\n"

View File

@@ -1,67 +0,0 @@
# Finnish translation for apparmor
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2020-01-29 07:44+0000\n"
"Last-Translator: Jiri Grönroos <Unknown>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2020-01-30 05:40+0000\n"
"X-Generator: Launchpad (build b8d1327fd820d6bf500589d6da587d5037c7d88e)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "tuntemattomat tai yhteensopimattomat valinnat\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "tuntematon valinta '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Kyllä\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Ei - ei käytettävissä tässä järjestelmässä.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Ei - poistettu käytöstä käynnistyksen yhteydessä.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Virhe - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Indonesian translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-01-20 08:59+0000\n"
"Last-Translator: Ari Setyo Wibowo <mr.a.contact@gmail.com>\n"
"Language-Team: Indonesian <id@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
"Language: id\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [options]\n"
" pilihan:\n"
" -q | --quiet Jangan tampilkan pesan apapun\n"
" -h | --help Tampilkan bantuan\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "pilihan yang tidak dikenali atau tidak kompatibel\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "pilihan tidak dikenali '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ya\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Tidak - tidak tersedia di sistem ini.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Tidak - nonaktifkan saat boot.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Mungkin - kebijakan antarmuka tidak tersedia.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Mungkin - izin tidak memadai untuk menentukan ketersediaan.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Kesalahan - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Portuguese translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-03-03 08:34+0000\n"
"Last-Translator: Ivo Xavier <ivofernandes12@gmail.com>\n"
"Language-Team: Portuguese <pt@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
"Language: pt\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [opções]\n"
" opções:\n"
" -q | --silencioso Não mostrar mensagens\n"
" -h | --ajuda Mostar ajuda\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "opções desconhecidas ou incompatíveis\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "opção desconhecida '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Sim\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Não - não disponível neste sistema.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Não - desligado ao iniciar.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Talvez - política de interface não disponível.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Talvez - permissões insuficientes para determinar disponibilidade.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Erro - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Romanian translation for apparmor
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2020-02-20 21:47+0000\n"
"Last-Translator: Daniel Slavu <Unknown>\n"
"Language-Team: Romanian <ro@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2020-02-21 05:39+0000\n"
"X-Generator: Launchpad (build 19413b719a8df7423ab1390528edadce9e0e4aca)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [opțiuni]\n"
" opțiuni:\n"
" -q | --calm Nu imprima niciun mesaj\n"
" -h | - ajutor Imprimare ajutor\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "opțiuni necunoscute sau incompatibile\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "opțiune necunoscută '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Da\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Nu - nu este disponibil pe acest sistem.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Nu - dezactivat la pornire.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Poate - interfața politică nu este disponibilă.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
"Poate - permisiuni insuficiente pentru a determina disponibilitatea.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Eroare - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Russian translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-03-29 14:46+0000\n"
"Last-Translator: Eugene Roskin <Unknown>\n"
"Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
"Language: ru\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [параметры]\n"
" параметры:\n"
" -q | --quiet не выводить никакие сообщения\n"
" -h | --help вывести справку\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "неизвестные или несовместимые параметры\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "неизвестный параметр '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Да\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Нет - недоступно на этой системе.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Нет - выключено при загрузке.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Возможно - интерфейс политики недоступен.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Возможно - недостаточно разрешений для определения доступности.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Ошибка - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Swedish translation for apparmor
# Copyright (c) 2018 Rosetta Contributors and Canonical Ltd 2018
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2018-09-08 03:51+0000\n"
"Last-Translator: Jonatan Nyberg <Unknown>\n"
"Language-Team: Swedish <sv@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [options]\n"
" flaggor:\n"
" -q | --quiet Skriv inte ut några meddelanden\n"
" -h | --help Skriv ut hjälp\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "okända eller inkompatibla flaggor\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "okänd flagga '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ja\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Nej - inte tillgänglig på detta system.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Nej - inaktiverad vid uppstart.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Kanske - policy gränssnitt inte tillgängliga.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
"Kanske - otillräckliga behörigheter för att bestämma tillgängligheten.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Fel - '%s'\n"

View File

@@ -1,71 +0,0 @@
# Swahili translation for apparmor
# Copyright (c) 2019 Rosetta Contributors and Canonical Ltd 2019
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2019-11-14 12:33+0000\n"
"Last-Translator: Swahilinux Administration <admin@swahilinux.org>\n"
"Language-Team: Swahili <sw@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-11-15 04:30+0000\n"
"X-Generator: Launchpad (build c597c3229eb023b1e626162d5947141bf7befb13)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [chaguzi]\n"
" chaguzi:\n"
" -q | --quiet Usichapishe jumbe yoyote\n"
" -h | --help Chapisha msaada\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "chaguo lisilojulikana au lisilofaa\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "chaguo lisilojulikana '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ndio\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "La - haipo kwenye mfumo huu.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "La - ilizimwa kwenye washi.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Labda - kiolesura cha faragha hakipo.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Labda - hamna ruhusa ya kutosha ili kuamua kama ipo.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Dosari - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Turkish translation for apparmor
# Copyright (c) 2018 Rosetta Contributors and Canonical Ltd 2018
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2018-05-19 23:10+0000\n"
"Last-Translator: Kudret EMRE <kudretemre@hotmail.com>\n"
"Language-Team: Turkish <tr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2019-04-18 05:33+0000\n"
"X-Generator: Launchpad (build 18928)\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [seçenekler]\n"
" seçenekler:\n"
" -q | --quiet Hiçbir mesajı gösterme\n"
" -h | --help Yardımı görüntüler\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "bilinmeyen veya uyumsuz seçenekler\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "bilinmeyen seçenek '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Evet\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Hayır - Bu sistemde kullanılabilir değil.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Hayır - önyüklemede devredışı bırakıldı.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Belki - policy arayüzü kullanılabilir değil.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
"Belki - kullanılabilir olup olmadığını denetlemek için yetersiz yetki.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Hata - '%s'\n"

View File

@@ -1,6 +1,5 @@
# ----------------------------------------------------------------------
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
# Copyright (c) 2016 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -18,7 +17,13 @@ NAME:=apache2-mod_apparmor
all:
COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
TARGET:=mod_apparmor.so
MANPAGES=mod_apparmor.8
@@ -70,31 +75,26 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
LDLIBS = -lapparmor
endif
APXS_CFLAGS="-Wc,$(EXTRA_WARNINGS)"
.PHONY: libapparmor_check
.SILENT: libapparmor_check
libapparmor_check: ; $(ERROR_MESSAGE)
all: libapparmor_check $(TARGET) docs
.PHONY: docs
docs: ${MANPAGES} ${HTMLMANPAGES}
all: libapparmor_check $(TARGET) ${MANPAGES} ${HTMLMANPAGES}
%.so: %.c
${APXS} ${LIBAPPARMOR_FLAGS} ${APXS_CFLAGS} -c $< ${LDLIBS}
${APXS} ${LIBAPPARMOR_FLAGS} -c $< ${LDLIBS}
mv .libs/$@ .
.PHONY: install
install: ${TARGET} ${MANPAGES}
mkdir -p ${DESTDIR}/${APXS_INSTALL_DIR}
install -m 755 $< ${DESTDIR}/${APXS_INSTALL_DIR}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
make install_manpages DESTDIR=${DESTDIR}
.PHONY: clean
clean: pod_clean
clean: _clean
rm -rf .libs
rm -f *.la *.lo *.so *.o *.slo
rm -f *.la *.lo *.so *.o *.slo Make.rules
.PHONY: check
check: check_pod_files

View File

@@ -30,10 +30,6 @@
/* #define DEBUG */
#ifndef unused_
#define unused_ __attribute__ ((unused))
#endif
/* should the following be configurable? */
#define DEFAULT_HAT "HANDLING_UNTRUSTED_INPUT"
#define DEFAULT_URI_HAT "DEFAULT_URI"
@@ -69,7 +65,7 @@ typedef struct {
* memory will be wiped out, and the magic_token will be lost, so apache
* wouldn't be able to change_hat back out. */
static int
aa_init(apr_pool_t *p, unused_ apr_pool_t *plog, unused_ apr_pool_t *ptemp, unused_ server_rec *s)
aa_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
apr_file_t *file;
apr_size_t size = sizeof(magic_token);
@@ -93,7 +89,7 @@ aa_init(apr_pool_t *p, unused_ apr_pool_t *plog, unused_ apr_pool_t *ptemp, unus
* to protect ourselves from bugs in parsing network input, but before
* we change_hat to the uri specific hat. */
static void
aa_child_init(unused_ apr_pool_t *p, unused_ server_rec *s)
aa_child_init(apr_pool_t *p, server_rec *s)
{
int ret;
@@ -141,7 +137,7 @@ aa_enter_hat(request_rec *r)
ap_get_module_config(r->server->module_config, &apparmor_module);
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
int i = 0;
char *aa_label, *aa_mode, *aa_hat;
char *aa_con, *aa_mode, *aa_hat;
const char *vhost_uri;
debug_dump_uri(r);
@@ -205,14 +201,14 @@ aa_enter_hat(request_rec *r)
/* Check to see if a defined AAHatName or AADefaultHatName would
* apply, but wasn't the hat we landed up in; report a warning if
* that's the case. */
aa_ret = aa_getcon(&aa_label, &aa_mode);
aa_ret = aa_getcon(&aa_con, &aa_mode);
if (aa_ret < 0) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
} else {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"AA checks: aa_getcon result is '%s', mode '%s'", aa_label, aa_mode);
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
/* TODO: use libapparmor get hat_name fn here once it is implemented */
aa_hat = strstr(aa_label, "//");
aa_hat = strstr(aa_con, "//");
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
aa_hat += 2; /* skip "//" */
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
@@ -230,7 +226,7 @@ aa_enter_hat(request_rec *r)
scfg->hat_name);
}
}
free(aa_label);
free(aa_con);
}
return OK;
@@ -264,7 +260,7 @@ aa_exit_hat(request_rec *r)
}
static const char *
aa_cmd_ch_path(unused_ cmd_parms *cmd, unused_ void *mconfig, const char *parm1)
aa_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "directory config change hat %s",
parm1 ? parm1 : "DEFAULT");
@@ -291,7 +287,7 @@ immunix_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
}
static const char *
aa_cmd_ch_srv(cmd_parms *cmd, unused_ void *mconfig, const char *parm1)
aa_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "server config change hat %s",
parm1 ? parm1 : "DEFAULT");
@@ -351,7 +347,7 @@ aa_merge_dir_config(apr_pool_t *p, void *parent, void *child)
*/
static void *
aa_create_srv_config(apr_pool_t *p, unused_ server_rec *srv)
aa_create_srv_config(apr_pool_t *p, server_rec *srv)
{
apparmor_srv_cfg *newcfg = (apparmor_srv_cfg *) apr_pcalloc(p, sizeof(*newcfg));
@@ -401,7 +397,7 @@ static const command_rec mod_apparmor_cmds[] = {
};
static void
register_hooks(unused_ apr_pool_t *p)
register_hooks(apr_pool_t *p)
{
ap_hook_post_config(aa_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(aa_child_init, NULL, NULL, APR_HOOK_MIDDLE);
@@ -412,7 +408,7 @@ register_hooks(unused_ apr_pool_t *p)
module AP_MODULE_DECLARE_DATA apparmor_module = {
STANDARD20_MODULE_STUFF,
aa_create_dir_config, /* dir config creator */
aa_create_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
aa_create_srv_config, /* server config */

View File

@@ -65,7 +65,7 @@ provides the AAHatName and AADefaultHatName Apache configuration options.
AAHatName allows you to specify a hat to be used for a given Apache
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
E<lt>LocationMatchE<gt> directive (see the Apache documentation for more
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
details). Note that mod_apparmor behavior can become confused if
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
and it is recommended to use one type of directive. If the hat specified by
@@ -135,11 +135,11 @@ may not work correctly. For Apache 2.4 users, you should enable the mpm_prefork
module.
There are likely other bugs lurking about; if you find any, please report
them at L<https://gitlab.com/apparmor/apparmor/-/issues>.
them at L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor_parser(8), aa_change_hat(2) and
L<https://wiki.apparmor.net>.
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,6 +1,5 @@
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2004, 2005 NOVELL (All rights reserved)
# Copyright (c) 2016 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -17,8 +16,15 @@
NAME=pam_apparmor
all:
COMMONDIR=../../common/
MAKE_RULES=common/Make.rules
include $(COMMONDIR)/Make.rules
include ${MAKE_RULES}
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
ifdef USE_SYSTEM
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
@@ -54,8 +60,8 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
AA_LDLIBS = -lapparmor
endif
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(EXTRA_WARNINGS) $(LIBAPPARMOR_INCLUDE)
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS) $(LDFLAGS)
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
LIBS=-lpam $(AA_LDLIBS)
OBJECTS=${NAME}.o get_options.o
@@ -63,11 +69,7 @@ OBJECTS=${NAME}.o get_options.o
.SILENT: libapparmor_check
libapparmor_check: ; $(ERROR_MESSAGE)
all: libapparmor_check $(NAME).so docs
.PHONY: docs
# docs: we should have some
docs:
all: libapparmor_check $(NAME).so
$(NAME).so: ${OBJECTS}
$(CC) $(EXTRA_CFLAGS) $(LINK_FLAGS) -o $@ ${OBJECTS} $(LIBS)
@@ -82,8 +84,10 @@ SECDIR ?= ${DESTDIR}/lib/security
.PHONY: install
install: $(NAME).so
install -m 755 -d $(SECDIR)
install -m 755 $(NAME).so $(SECDIR)/
install -m 555 $(NAME).so $(SECDIR)/
.PHONY: clean
clean:
clean: ${MAKE_RULES}
rm -f core core.* *.so *.o *.s *.a *~
rm -f ${NAME}-*.tar.gz Make.rules

View File

@@ -67,10 +67,10 @@ to syslog.
References
----------
Project webpage:
https://apparmor.net/
http://developer.novell.com/wiki/index.php/Novell_AppArmor
To provide feedback or ask questions please contact the
apparmor@lists.ubuntu.com mail list. This is the development list
apparmor-dev@forge.novell.com mail list. This is the development list
for the AppArmor team.
See also: change_hat(3), and the Linux-PAM online documentation at

View File

@@ -45,10 +45,6 @@
int debug_flag = 0;
#ifndef unused_
#define unused_ __attribute__ ((unused))
#endif
static struct config default_config = {
.hat_type[0] = eGroupname,
.hat_type[1] = eDefault,
@@ -58,14 +54,14 @@ static struct config default_config = {
/* --- session management functions (only) --- */
PAM_EXTERN int
pam_sm_close_session (unused_ pam_handle_t *pamh, unused_ int flags,
unused_ int argc, unused_ const char **argv)
pam_sm_close_session (pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
return PAM_IGNORE;
}
PAM_EXTERN
int pam_sm_open_session(pam_handle_t *pamh, unused_ int flags,
int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
int fd, retval, pam_retval = PAM_SUCCESS;

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat5
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -66,8 +66,8 @@ under src/jni_src.
cp dist/libJNIChangeHat.so /usr/lib
[Note: you must ensure that the target directory is passed to tomcat via the
java.library.path property. This can be accomplished by setting the JAVA_OPTS
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
find this library at startup]
@@ -108,13 +108,13 @@ under src/jni_src.
Once the installation steps above have been started you are ready to begin
creating a profile for your application. The profile creation tool genprof will
guide you through generating a profile and its support for change_hat will
prompt you create discrete hats as requested by the changeHatValve during
prompt you create discrete hats as requested byt the changeHatValve during
tomcat execution.
1. Create a basic profile for the tomcat server.
- Run the command "genprof PATH_TO_CATALINA.SH"
- In a separate window start tomcat and then stop tomcat
- In a seperate window start tomcat and then stop tomcat
- In the genprof window press "S" to scan for events
- Answer the questions about the initial profile for tomcat
@@ -124,7 +124,7 @@ tomcat execution.
- Stop the tomcat server
- Deploy your WAR file or equivalent files under the container.
- execute "genprof PATH_TO_CATALINA.SH"
- In a separate window start tomcat and then exercise your web application
- In a seperate window start tomcat and then exercise your web application
- In the genprof window press "S" to scan for events
During the prompting you will be asked questions similar to:
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
context).
If you choose to use the default hat: genprof will mediate all resource
requests in the default hat for the duration of processing this request.
When the request processing is complete the valve will change_hat back to the
When the request processng is complete the valve will change_hat back to the
parent context.
@@ -188,9 +188,10 @@ parent context.
8. Feedback/Resources
-----------------
Project webpage:
https://apparmor.net/
To provide feedback or ask questions please contact the
apparmor-dev@forge.novell.com mail list. This is the development list for the
AppArmor team.
To provide feedback or ask questions please contact the
apparmor@lists.ubuntu.com mail list. This is the development list
for the AppArmor team.

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat55
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -66,8 +66,8 @@ under src/jni_src.
cp dist/libJNIChangeHat.so /usr/lib
[Note: you must ensure that the target directory is passed to tomcat via the
java.library.path property. This can be accomplished by setting the JAVA_OPTS
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
find this library at startup]
@@ -108,13 +108,13 @@ under src/jni_src.
Once the installation steps above have been started you are ready to begin
creating a profile for your application. The profile creation tool genprof will
guide you through generating a profile and its support for change_hat will
prompt you create discrete hats as requested by the changeHatValve during
prompt you create discrete hats as requested byt the changeHatValve during
tomcat execution.
1. Create a basic profile for the tomcat server.
- Run the command "genprof PATH_TO_CATALINA.SH"
- In a separate window start tomcat and then stop tomcat
- In a seperate window start tomcat and then stop tomcat
- In the genprof window press "S" to scan for events
- Answer the questions about the initial profile for tomcat
@@ -124,7 +124,7 @@ tomcat execution.
- Stop the tomcat server
- Deploy your WAR file or equivalent files under the container.
- execute "genprof PATH_TO_CATALINA.SH"
- In a separate window start tomcat and then exercise your web application
- In a seperate window start tomcat and then exercise your web application
- In the genprof window press "S" to scan for events
During the prompting you will be asked questions similar to:
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
context).
If you choose to use the default hat: genprof will mediate all resource
requests in the default hat for the duration of processing this request.
When the request processing is complete the valve will change_hat back to the
When the request processng is complete the valve will change_hat back to the
parent context.
@@ -188,9 +188,10 @@ parent context.
8. Feedback/Resources
-----------------
Project webpage:
https://apparmor.net/
To provide feedback or ask questions please contact the
apparmor-dev@forge.novell.com mail list. This is the development list for the
AppArmor team.
To provide feedback or ask questions please contact the
apparmor@lists.ubuntu.com mail list. This is the development list
for the AppArmor team.

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
# Copyright 2009-2015 Canonical Ltd.
# Copyright 2009-2010 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -21,7 +21,7 @@
# exist
LOCALEDIR=/usr/share/locale
XGETTEXT_ARGS=--copyright-holder="Canonical Ltd" --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
XGETTEXT_ARGS=--copyright-holder="NOVELL, Inc." --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
# When making the .pot file, it's expected that the parent Makefile will
# pass in the list of sources in the SOURCES variable

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2010-2015 Canonical, Ltd.
# Copyright (C) 2010 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -15,21 +15,17 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ------------------------------------------------------------------
# Make.rules - common make targets and variables for building AppArmor
# Make.rules - common make targets and variables for building the SHASS
# product.
#
# NOTES:
# Before including this file in your Makefile, you should
# - define COMMONDIR (the location of the common/ directory)
# - define the default rule (usually 'all:'). (Note: you can redefine
# it later in your Makefile)
.PHONY: common_Make.rules_is_a_bad_target
common_Make.rules_is_a_bad_target:
@echo "*** default target in common/Make.rules hit - either you did something strange, or something is broken... ***"
exit 1
# - must define the package NAME before including this file.
# - After checking in to cvs, you'll need to delele the hardlinked
# Make.rules files that already exist in the individual application
# directories
DISTRIBUTION=AppArmor
VERSION=$(shell cat $(COMMONDIR)/Version)
VERSION=$(shell cat common/Version)
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
@@ -45,10 +41,108 @@ define nl
endef
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
# OVERRIDABLE variables
# Set these variables before including Make.rules to change its behavior
# SPECFILE - for packages that have a non-standard specfile name
# EXTERNAL_PACKAGE - for packages that have upstream versions that
# we're locally modifying (e.g. imnxcerttool/gnutls).
#
# use 'make BUILDIR=/some/where/else/' to override the /usr/src/redhat
# location -- it *should* pick out the right thing to do based on the
# .rpmmacros file, but you can still use BUILDDIR to override that.
TESTBUILDDIR=$(shell [ -f ${HOME}/.rpmmacros ] && awk '/^%_topdir/ {print $$2}' ${HOME}/.rpmmacros)
ifndef BUILDDIR
BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
echo ${TESTBUILDDIR} | sed "s^/$$^^" ; \
elif [ -d "/usr/src/redhat" ] ; then \
echo "/usr/src/redhat" ; \
elif [ -d "/usr/src/packages" ] ; then \
echo "/usr/src/packages" ; \
else \
echo "/tmp/${NAME}" ; \
fi ;)
endif
ifndef DISTRO
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
echo slackware ; \
elif [ -f /etc/debian_version ] ; then \
echo debian ;\
elif which rpm > /dev/null ; then \
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
echo suse ;\
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
echo rhel4 ;\
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
echo rhel4 ;\
else \
echo unknown ;\
fi ;\
else \
echo unknown ;\
fi)
endif
RPMARG=--define "_topdir $(BUILDDIR:/=)" \
--define "vendor NOVELL, Inc." \
--define "distribution ${DISTRIBUTION}" \
--define "debug_package %{nil}" \
--define "immunix_version ${VERSION}" \
$(shell [ -d ${BUILDDIR}/BUILDROOT ] && echo --define \"buildroot $(BUILDDIR:/=)/BUILDROOT\") \
$(shell [ -n "${DISTRO}" ] && echo --define \"distro ${DISTRO}\")
REPO_VERSION_CMD=([ -x /usr/bin/bzr ] && /usr/bin/bzr version-info . 2> /dev/null || awk '{ print "revno: "$2 }' common/.stamp_rev) | awk '/^revno:/ { print $2 }'
ifdef EXTERNAL_PACKAGE
RPMARG+=--define "_sourcedir $(shell pwd)"
endif
ifndef SPECFILE
SPECFILE = $(NAME).spec
endif
RELEASE_DIR = $(NAME)-$(VERSION)
TAR = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
LDCONFIG = /sbin/ldconfig
RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
ifdef EXTERNAL_PACKAGE
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
rpmbuild -ba ${RPMARG} ${SPECFILE}
else
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
__TARBALL=$(NAME)-$(VERSION)-$${__REPO_VERSION}.tar.gz ; \
make $${__TARBALL} ; \
cp $${__TARBALL} $(BUILDDIR)/SOURCES/
cp ${SPECFILE} $(BUILDDIR)/SPECS/
rpmbuild -ba ${RPMARG} ${SPECFILE}
.PHONY: ${SPECFILE}
${SPECFILE}: ${SPECFILE}.in
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
sed -e "s/@@immunix_version@@/${VERSION}/g" \
-e "s/@@repo_version@@/$${__REPO_VERSION}/g" $< > $@
%.tar.gz: clean ${SPECFILE}
-rm -rf $(RELEASE_DIR)
mkdir $(RELEASE_DIR)
$(TAR) --exclude $@ . | tar xz -C $(RELEASE_DIR)
$(TAR) --exclude $@ -f $@ $(RELEASE_DIR)
rm -rf $(RELEASE_DIR)
ifndef OVERRIDE_TARBALL
.PHONY: tarball
tarball: clean $(TARBALL)
endif
endif
ifndef PYTHON_VERSIONS
PYTHON_VERSIONS = $(call map, pathsearch, python3)
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
endif
ifndef PYTHON
@@ -58,35 +152,63 @@ endif
#Helper function to be used with $(call pyalldo, run_test_with_all.py)
pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
# Common set of compiler warnings
_EXTRA_WARNINGS = -Wall -Wsign-compare -Wmissing-field-initializers -Wformat -Wformat-security -Wunused-parameter -Wimplicit-fallthrough
EXTRA_WARNINGS := $(shell for warning in ${_EXTRA_WARNINGS} ; do \
if ${CC} $${warning} -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then \
echo "$${warning}"; \
else \
echo "***" >&2 ; \
echo "WARNING: unable to use $${warning} with ${CC}, dropping" >&2 ; \
echo "***" >&2 ; \
fi ; \
done)
.PHONY: version
.SILENT: version
version:
echo $(VERSION)
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
.PHONY: repo_version
.SILENT: repo_version
repo_version:
echo $(shell $(value REPO_VERSION_CMD))
$(value REPO_VERSION_CMD)
.PHONY: pod_clean
ifndef VERBOSE
.SILENT: pod_clean
endif
pod_clean:
.PHONY: build_dir
build_dir: $(BUILDRPMSUBDIRS)
$(BUILDRPMSUBDIRS):
mkdir -p $(BUILDRPMSUBDIRS)
.PHONY: _clean
.SILENT: _clean
_clean:
-[ -z "${NAME}" ] || rm -f ${NAME}-${VERSION}-*.tar.gz
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
# =====================
# generate list of capabilities based on
# /usr/include/linux/capabilities.h for use in multiple locations in
# the source tree
# =====================
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | sort)
.PHONY: list_capabilities
list_capabilities: /usr/include/linux/capability.h
@echo "$(CAPABILITIES)"
# =====================
# generate list of network protocols based on
# sys/socket.h for use in multiple locations in
# the source tree
# =====================
# These are the families that it doesn't make sense for apparmor
# to mediate. We use PF_ here since that is what is required in
# bits/socket.h, but we will rewrite these as AF_.
FILTER_FAMILIES=PF_UNIX
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
# emits the AF names in a "AF_NAME NUMBER," pattern
AF_NAMES=$(shell echo "\#include <sys/socket.h>" | cpp -dM | LC_ALL=C sed -n -e '/$(__FILTER)/d' -e 's/PF_LOCAL/PF_UNIX/' -e 's/^\#define[ \t]\+PF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\).*$$/AF_\1 \2,/p' | sort -n -k2)
.PHONY: list_af_names
list_af_names:
@echo "$(AF_NAMES)"
# =====================
# manpages
# =====================

View File

@@ -1 +1 @@
4.0.0~beta2
2.9.5

View File

@@ -1,19 +0,0 @@
#!/bin/bash -e
# =====================
# generate list of network protocols based on
# sys/socket.h for use in multiple locations in
# the source tree
# =====================
# It doesn't make sense for AppArmor to mediate PF_UNIX, filter it out. Search
# for "PF_" constants since that is what is required in bits/socket.h, but
# rewrite as "AF_".
echo "#include <sys/socket.h>" | \
cpp -dM | \
LC_ALL=C sed -n \
-e '/PF_UNIX/d' \
-e 's/PF_LOCAL/PF_UNIX/' \
-e 's/^#define[ \t]\+PF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\).*$/AF_\1 \2,/p' | \
sort -n -k2

View File

@@ -1,14 +0,0 @@
#!/bin/bash -e
# =====================
# generate list of capabilities based on
# /usr/include/linux/capabilities.h for use in multiple locations in
# the source tree
# =====================
echo "#include <linux/capability.h>" | \
cpp -dM | \
LC_ALL=C sed -n \
-e '/CAP_EMPTY_SET/d' \
-e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$/CAP_\1/p' | \
LC_ALL=C sort

View File

@@ -0,0 +1,137 @@
#!/bin/sh
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
# NOVELL (All rights reserved)
#
# 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.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# rc.apparmor by Steve Beattie
#
# /etc/init.d/aaeventd
# and its symbolic link
# /sbin/rcaaeventd
#
# chkconfig: 2345 01 99
# description: AppArmor Notification and Reporting daemon
#
### BEGIN INIT INFO
# Provides: aaeventd
# Required-Start: apparmor
# Required-Stop:
# Default-Start: 2 3 5
# Default-Stop:
# Short-Description: AppArmor Notification and Reporting
# Description: AppArmor Notification and Reporting daemon
### END INIT INFO
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
# source function library
if [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ]; then
. /etc/rc.d/init.d/functions
elif [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
else
exit 0
fi
sd_log_success_msg() {
echo -n "$*"
success
echo
}
sd_log_warning_msg() {
echo -n "$*"
warning
echo
}
sd_log_skipped_msg() {
echo -n "$*"
warning
echo
}
sd_log_failure_msg() {
echo -n "$*"
failure
echo
}
sd_action() {
STRING=$1
shift
action "${STRING} " "$@"
return $?
}
start_aa_event() {
if [ -x "$AA_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" daemon --pidfile $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE
elif [ -x "$SD_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" daemon --pidfile $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE
fi
}
stop_aa_event() {
if [ -x "$AA_EV_BIN" -a -f "$AA_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" killproc -p $AA_EV_PIDFILE -INT $AA_EV_BIN
fi
if [ -f "$SD_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" killproc -p $SD_EV_PIDFILE -INT $SD_EV_BIN
fi
}
usage() {
echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status}"
}
# source apparmor function library
if [ -f "${APPARMOR_FUNCTIONS}" ]; then
. ${APPARMOR_FUNCTIONS}
else
sd_log_failure_msg "Unable to find AppArmor initscript functions"
exit 1
fi
case "$1" in
start)
start_aa_event
rc=$?
;;
stop)
stop_aa_event
rc=$?
;;
restart|reload|force-reload|try-restart)
stop_aa_event
start_aa_event
rc=$?
;;
status)
echo -n "Checking for service AppArmor Event daemon:"
if [ "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ]; then
/sbin/checkproc -p $AA_EV_PIDFILE $AA_EV_BIN
rc_status -v
else
rc_status -u
fi
;;
*)
usage
exit 1
;;
esac
exit $rc

133
deprecated/rc.aaeventd.suse Normal file
View File

@@ -0,0 +1,133 @@
#!/bin/sh
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2000, 2001, 2002, 2003 2004, 2005, 2006, 2007
# NOVELL (All rights reserved)
#
# 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.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# rc.apparmor by Steve Beattie
#
# /etc/init.d/aaeventd
# and its symbolic link
# /sbin/rcaaeventd
#
# chkconfig: 2345 01 99
# description: AppArmor Notification and Reporting daemon
#
### BEGIN INIT INFO
# Provides: aaeventd
# Required-Start: apparmor
# Required-Stop: $null
# Default-Start: 2 3 5
# Default-Stop:
# Short-Description: AppArmor Notification and Reporting
# Description: AppArmor Notification and Reporting daemon
### END INIT INFO
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
# source function library
if [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ]; then
. /etc/rc.d/init.d/functions
elif [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
else
exit 0
fi
# Ugh, SUSE doesn't implement action
sd_action() {
STRING=$1
shift
"$@"
rc=$?
if [ $rc -eq 0 ] ; then
log_success_msg $"$STRING "
else
log_failure_msg $"$STRING "
fi
return $rc
}
sd_log_success_msg() {
log_success_msg $*
}
sd_log_warning_msg() {
log_warning_msg $*
}
sd_log_failure_msg() {
log_failure_msg $*
}
usage() {
echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status}"
}
start_aa_event() {
if [ -x "$AA_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" startproc -p $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE
elif [ -x "$SD_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" startproc -p $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE
fi
}
stop_aa_event() {
if [ -x "$AA_EV_BIN" -a -f "$AA_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" killproc -G -p $AA_EV_PIDFILE -INT $AA_EV_BIN
fi
if [ -f "$SD_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" killproc -G -p $SD_EV_PIDFILE -INT $SD_EV_BIN
fi
}
# source apparmor function library
if [ -f "${APPARMOR_FUNCTIONS}" ]; then
. ${APPARMOR_FUNCTIONS}
else
sd_log_failure_msg "Unable to find AppArmor initscript functions"
exit 1
fi
case "$1" in
start)
start_aa_event
rc=$?
;;
stop)
stop_aa_event
rc=$?
;;
restart|reload|force-reload|try-restart)
stop_aa_event
start_aa_event
rc=$?
;;
status)
echo -n "Checking for service AppArmor Event daemon:"
if [ "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ]; then
/sbin/checkproc -p $AA_EV_PIDFILE $AA_EV_BIN
rc_status -v
else
rc_status -u
fi
;;
*)
usage
exit 1
;;
esac
exit $rc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,124 @@
# ----------------------------------------------------------------------
# Copyright (c) 2006 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
package Immunix::Config;
use strict;
use warnings;
use Carp;
use Cwd qw(cwd realpath);
use File::Basename;
use File::Temp qw/ tempfile tempdir /;
use Data::Dumper;
use Locale::gettext;
use POSIX;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
read_config
write_config
find_first_file
find_first_dir
);
our $confdir = "/etc/apparmor";
# config vars
our $cfg;
our $repo_cfg;
sub read_config {
my $filename = shift;
my $config;
if (open(CONF, "$confdir/$filename")) {
my $which;
while (<CONF>) {
chomp;
# ignore comments
next if /^\s*#/;
if (m/^\[(\S+)\]/) {
$which = $1;
} elsif (m/^\s*(\S+)\s*=\s*(.*)\s*$/) {
my ($key, $value) = ($1, $2);
$config->{$which}{$key} = $value;
}
}
close(CONF);
}
# LP: #692406
# Explicitly disable the repository until there is an alternative, since
# the OpenSUSE site went away
if ($filename eq "repository.conf") {
$config->{repository}{enabled} = "no";
}
return $config;
}
sub write_config {
my ($filename, $config) = @_;
if (open(my $CONF, ">$confdir/$filename")) {
for my $section (sort keys %$config) {
print $CONF "[$section]\n";
for my $key (sort keys %{$config->{$section}}) {
print $CONF " $key = $config->{$section}{$key}\n"
if ($config->{$section}{$key});
}
}
chmod(0600, $CONF);
close($CONF);
} else {
die "Can't write config file $filename: $!";
}
}
sub find_first_file {
my $list = shift;
return if ( not defined $list );
my $filename;
for my $f (split(/\s+/, $list)) {
if (-f $f) {
$filename = $f;
last;
}
}
return $filename;
}
sub find_first_dir {
my $list = shift;
return if ( not defined $list );
my $dirname;
for my $f (split(/\s+/, $list)) {
if (-d $f) {
$dirname = $f;
last;
}
}
return $dirname;
}
1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,354 @@
# ----------------------------------------------------------------------
# Copyright (c) 2008 Dominic Reynolds
#
# 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.
#
#
# ----------------------------------------------------------------------
package Immunix::Repository;
use strict;
use warnings;
use Carp;
use Cwd qw(cwd realpath);
use Data::Dumper;
use File::Basename;
use File::Temp qw/ tempfile tempdir /;
use Immunix::Config;
use Locale::gettext;
use POSIX;
use RPC::XML;
use RPC::XML::Client;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
get_repo_client
did_result_succeed
get_result_error
user_login
user_register
upload_profile
fetch_profile_by_id
fetch_profiles_by_user
fetch_profiles_by_name
fetch_profiles_by_name_and_user
fetch_newer_profile
get_repo_config
set_repo_config
);
our %clients;
our %uid2login;
our $DEBUGGING = 0;
our $repo_cfg;
our $aa_cfg;
sub get_repo_client ($) {
my $repo_url = shift;
unless ( $clients{$repo_url} ) {
$clients{$repo_url} = new RPC::XML::Client $repo_url;
}
return $clients{$repo_url};
}
sub did_result_succeed {
my $result = shift;
my $ref = ref $result;
return ($ref && $ref ne "RPC::XML::fault") ? 1 : 0;
}
sub get_result_error {
my $result = shift;
if (ref $result) {
if (ref $result eq "RPC::XML::fault") {
$result = $result->string;
} else {
$result = $$result;
}
}
return $result;
}
sub user_login ($$$) {
my ($repo_url,$user,$pass) = @_;
my ($status,$detail);
my $repo_client = get_repo_client( $repo_url );
if ( $repo_client ) {
my $res = $repo_client->send_request('LoginConfirm', $user, $pass);
if (did_result_succeed($res)) {
$status = 1;
$detail = "";
} else {
$status = 0;
$detail = get_result_error($res);
}
}
return $status,$detail;
}
sub user_register ($$$$) {
my ($repo_url,$user,$pass,$email) = @_;
my $repo_client = get_repo_client( $repo_url );
my ($status,$detail);
if ( $repo_client ) {
my $res = $repo_client->send_request('Signup', $user, $pass, $email);
if (did_result_succeed($res)) {
$status = 1;
$detail = "";
} else {
$status = 0;
$detail = get_result_error($res);
}
}
return $status,$detail;
}
sub upload_profile ($$$$$$$) {
my ($repo_url,$user,$pass,$distro,$pname,$profile,$changelog) = @_;
my ($status,$detail);
my $repo_client = get_repo_client( $repo_url );
my $res = $repo_client->send_request( 'Create', $user, $pass, $distro,
$pname, $profile, $changelog);
if (did_result_succeed($res)) {
$detail = $res->value;
$status = 1;
} else {
$detail = get_result_error($res);
$status = 0;
}
return $status,$detail;
}
sub fetch_profile_by_id ($$) {
my ($repo_url,$id) = @_;
my $repo_client = get_repo_client( $repo_url );
my $repo_profile;
my ($status,$detail);
my $res = $repo_client->send_request('Show', $id);
if (did_result_succeed($res)) {
$status = 1;
$detail = $res->value();
} else {
$status = 0;
$detail = get_result_error($res);
}
return $status, $detail;
}
sub fetch_profiles ($$$$) {
my ($repo_url,$distro,$username,$fqdn) = @_;
my $p_hash = {};
my ($status,$detail);
my $repo_client = get_repo_client( $repo_url );
my $res =
$repo_client->send_request('FindProfiles', $distro, $fqdn, $username);
if (did_result_succeed($res)) {
$status = 1;
for my $p ( @$res ) {
my $p_repo = $p->{profile}->value();
$p_repo =~ s/flags=\(complain\)// if ( $p_repo ); #strip complain flag
$p->{profile} = $p_repo;
$p->{user_id} = $p->{user_id}->value();
$p->{id} = $p->{id}->value();
$p->{name} = $p->{name}->value();
$p->{created_at} = $p->{created_at}->value();
$p->{downloaded_count} = $p->{downloaded_count}->value();
}
$detail = $res;
} else {
$status = 0;
$detail = get_result_error($res);
}
return $status,$detail;
}
sub fetch_profiles_by_user ($$$) {
my ($repo_url,$distro,$username) = @_;
my $p_hash = {};
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, "" );
if ( $status ) {
for my $p ( @$detail ) {
my $p_repo = $p->{profile};
if ($p_repo ne "") {
$p->{username} = $username;
$p_hash->{$p->{name}} = $p;
}
}
} else {
return ($status,$detail);
}
return($status,$p_hash);
}
sub fetch_profiles_by_name_and_user ($$$$) {
my ($repo_url,$distro,$fqdbin, $username) = @_;
my $p_hash = {};
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, $fqdbin );
if ( $status ) {
for my $p ( @$detail ) {
my $p_repo = $p->{profile}?$p->{profile}:"";
$p_hash->{$p->{name}} = $p if ($p_repo ne "");
}
} else {
return ($status,$detail);
}
return($status,$p_hash);
}
sub fetch_profiles_by_name ($$$) {
my ($repo_url,$distro,$fqdbin) = @_;
my ($status,$detail,$data);
$detail = {};
($status,$data) = fetch_profiles( $repo_url, $distro, "", $fqdbin);
if ($status) {
my @uids;
for my $p (@$data) {
push @uids, $p->{user_id};
}
my ($status_unames,$unames) = fetch_usernames_from_uids($repo_url, @uids);
if ( $status_unames ) {
for my $p (@$data) {
if ( $unames->{$p->{user_id}} ) {
$p->{username} = $unames->{$p->{user_id}};
} else {
$p->{username} = "unkown-" . $p->{user_id};
}
}
} else {
print STDOUT "ERROR UID\n";
}
for my $p (@$data) {
$p->{profile_type} = "REPOSITORY";
$detail->{$p->{username}} = $p;
}
} else {
$detail = $data;
}
return $status,$detail;
}
sub fetch_newer_profile ($$$$$) {
my ($repo_url,$distro,$user,$id,$profile) = @_;
my $repo_client = get_repo_client( $repo_url );
my $p;
my ($status,$detail);
if ($repo_client) {
my $res =
$repo_client->send_request('FindProfiles', $distro, $profile, $user);
if (did_result_succeed($res)) {
my @profiles;
my @profile_list = @{$res->value};
$status = 1;
if (@profile_list) {
if ($profile_list[0]->{id} > $id) {
$p = $profile_list[0];
}
}
$detail = $p;
} else {
$status = 0;
$detail = get_result_error($res);
}
}
return $status,$detail;
}
sub fetch_usernames_from_uids ($) {
my ($repo_url,@searchuids) = @_;
my ($status,$result) = (1,{});
my @uids;
for my $uid ( @searchuids ) {
if ( $uid2login{$uid} ) {
$result->{$uid} = $uid2login{$uid};
} else {
push @uids, $uid;
}
}
if (@uids) {
my $repo_client = get_repo_client( $repo_url );
#RPC::XML will serialize the array into XML with the is_utf8 flag set
#which causes, HTTP:Message to fail. Looping on the array elements
#stops this from happening, and since these are all numbers it
#will not cause problems.
for my $foo (@uids) {
Encode::_utf8_off($foo);
}
my $res = $repo_client->send_request('LoginNamesFromUserIds', [@uids]);
if (did_result_succeed($res)) {
my @usernames = @{ $res->value };
for my $uid (@uids) {
my $username = shift @usernames;
$uid2login{$uid} = $username;
$result->{$uid} = $uid2login{$uid};
}
} else {
$status = 0;
$result = get_result_error($res);
}
}
return $status,$result;
}
sub get_repo_config {
unless ( $repo_cfg ) {
$repo_cfg = Immunix::Config::read_config("repository.conf");
}
unless ( $aa_cfg ) {
$aa_cfg = Immunix::Config::read_config("logprof.conf");
}
return {
"url" => $aa_cfg->{repository}{url},
"distro" => $aa_cfg->{repository}{distro},
"enabled" => $repo_cfg->{repository}{enabled},
"upload" => $repo_cfg->{repository}{upload},
"user" => $repo_cfg->{repository}{user},
"password" => $repo_cfg->{repository}{pass},
"email" => $repo_cfg->{repository}{email}
};
}
sub set_repo_config ($) {
my $cfg = shift;
my ($url,$distro,$enabled,$upload,$user,$pass);
unless ( $repo_cfg ) {
$repo_cfg = Immunix::Config::read_config("repository.conf");
}
unless ( $aa_cfg ) {
$aa_cfg = Immunix::Config::read_config("logprof.conf");
}
$repo_cfg->{repository}{enabled} = $cfg->{enabled} if ( $cfg->{enabled} );
$repo_cfg->{repository}{upload} = $cfg->{upload} if ( $cfg->{upload} );
$repo_cfg->{repository}{user} = $cfg->{user} if ( $cfg->{user} );
$repo_cfg->{repository}{pass} = $cfg->{password}if ( $cfg->{password} );
$repo_cfg->{repository}{email} = $cfg->{email} if ( $cfg->{email} );
$aa_cfg->{repository}{distro} = $cfg->{distro} if ( $cfg->{distro} );
$aa_cfg->{repository}{url} = $cfg->{url} if ( $cfg->{url} );
write_config("repository.conf", $repo_cfg);
write_config("logprof.conf", $aa_cfg);
}
1;

View File

@@ -0,0 +1,221 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2005-2006 Novell/SUSE
#
# 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.
#
# ------------------------------------------------------------------
package Immunix::Severity;
use strict;
use Data::Dumper;
my ($debug) = 0;
sub debug {
print @_ if $debug;
}
sub new {
my $self = {};
$self->{DATABASENAME} = undef;
$self->{CAPABILITIES} = {};
$self->{FILES} = {};
$self->{REGEXPS} = {};
$self->{DEFAULT_RANK} = 10;
bless($self);
shift;
$self->init(@_) if @_;
return $self;
}
sub init ($;$) {
my ($self, $resource, $read, $write, $execute, $severity);
$self = shift;
$self->{DATABASENAME} = shift;
$self->{DEFAULT_RANK} = shift if defined $_[0];
open(DATABASE, $self->{DATABASENAME})
or die "Could not open severity db $self->{DATABASENAME}: $!\n";
while (<DATABASE>) {
chomp();
next if m/^\s*#/;
next if m/^\s*$/;
# leading whitespace is fine; maybe it shouldn't be?
if (/^\s*\/(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s*$/) {
my ($path, $read, $write, $execute) = ($1, $2, $3, $4);
if (index($path, "*") == -1) {
$self->{FILES}{$path} = {
r => $read,
w => $write,
x => $execute
};
} else {
my $ptr = $self->{REGEXPS};
my @pieces = split(/\//, $path);
while (my $piece = shift @pieces) {
if (index($piece, "*") != -1) {
my $path = join("/", $piece, @pieces);
my $regexp = convert_regexp($path);
$ptr->{$regexp}{SD_RANK} = {
r => $read,
w => $write,
x => $execute
};
last;
} else {
$ptr->{$piece} = {} unless exists $ptr->{$piece};
$ptr = $ptr->{$piece};
}
}
}
} elsif (m|^\s*CAP|) {
($resource, $severity) = split;
$self->{CAPABILITIES}{$resource} = $severity;
} else {
print "unexpected database line: $_\n";
}
}
close(DATABASE);
debug Dumper($self);
return $self;
}
#rank:
# handle capability
# handle file
#
# handle capability
# if the name is in the database, return it
# otherwise, send a diagnostic message to stderr and return the default
#
# handle file
# initialize the current return value to 0
# loop over each entry in the database;
# find the max() value for each mode that matches and set a 'found' flag
# if the found flag has not been set, return the default;
# otherwise, return the maximum from the database
sub handle_capability ($) {
my ($self, $resource) = @_;
my $ret = $self->{CAPABILITIES}{$resource};
if (!defined($ret)) {
return "unexpected capability rank input: $resource\n";
}
return $ret;
}
sub check_subtree {
my ($tree, $mode, $sev, $first, @rest) = @_;
# reassemble the remaining path from this directory level
my $path = join("/", $first, @rest);
# first check if we have a literal directory match to descend into
if ($tree->{$first}) {
$sev = check_subtree($tree->{$first}, $mode, $sev, @rest);
}
# if we didn't get a severity already, check for matching globs
unless ($sev) {
# check each glob at this directory level
for my $chunk (grep { index($_, "*") != -1 } keys %{$tree}) {
# does it match the rest of our path?
if ($path =~ /^$chunk$/) {
# if we've got a ranking, check if it's higher than
# current one, if any
if ($tree->{$chunk}->{SD_RANK}) {
for my $m (split(//, $mode)) {
if ((!defined $sev)
|| $tree->{$chunk}->{SD_RANK}->{$m} > $sev)
{
$sev = $tree->{$chunk}->{SD_RANK}->{$m};
}
}
}
}
}
}
return $sev;
}
sub handle_file ($$) {
my ($self, $resource, $mode) = @_;
# strip off the initial / from the path we're checking
$resource = substr($resource, 1);
# break the path into directory-level chunks
my @pieces = split(/\//, $resource);
my $sev;
# if there's a exact match for this path in the db, use that instead of
# checking the globs
if ($self->{FILES}{$resource}) {
# check each piece of the passed mode against the db entry
for my $m (split(//, $mode)) {
if ((!defined $sev) || $self->{FILES}{$resource}{$m} > $sev) {
$sev = $self->{FILES}{$resource}{$m};
}
}
} else {
# descend into the regexp tree looking for matches
$sev = check_subtree($self->{REGEXPS}, $mode, $sev, @pieces);
}
return (defined $sev) ? $sev : $self->{DEFAULT_RANK};
}
sub rank ($;$) {
my ($self, $resource, $mode) = @_;
if (substr($resource, 0, 1) eq "/") {
return $self->handle_file($resource, $mode);
} elsif (substr($resource, 0, 3) eq "CAP") {
return $self->handle_capability($resource);
} else {
return "unexpected rank input: $resource\n";
}
}
sub convert_regexp ($) {
my ($input) = shift;
# we need to convert subdomain regexps to perl regexps
my $regexp = $input;
# escape + . [ and ] characters
$regexp =~ s/(\+|\.|\[|\])/\\$1/g;
# convert ** globs to match anything
$regexp =~ s/\*\*/.SDPROF_INTERNAL_GLOB/g;
# convert * globs to match anything at current path level
$regexp =~ s/\*/[^\/]SDPROF_INTERNAL_GLOB/g;
# convert {foo,baz} to (foo|baz)
$regexp =~ y/\{\}\,/\(\)\|/ if $regexp =~ /\{.*\,.*\}/;
# twiddle the escaped * chars back
$regexp =~ s/SDPROF_INTERNAL_GLOB/\*/g;
return $regexp;
}
1; # so the require or use succeeds

69
deprecated/utils/Makefile Normal file
View File

@@ -0,0 +1,69 @@
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2004-2009 NOVELL (All rights reserved)
# Copyright (c) 2010-2011, 2014 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# NOTE: this Makefile has been adjusted from the original to assist in
# the installation of the Immunix perl modules, if they're still needed
# by users. Because the utilities conflict with their replacments, make
# install *will* *not* install them.
NAME = apparmor-utils
all:
COMMONDIR=../../common/
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
MODDIR = Immunix
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
aa-unconfined aa-disable
MODULES = ${MODDIR}/AppArmor.pm ${MODDIR}/Repository.pm \
${MODDIR}/Config.pm ${MODDIR}/Severity.pm
all:
# need some better way of determining this
DESTDIR=/
BINDIR=${DESTDIR}/usr/sbin
CONFDIR=${DESTDIR}/etc/apparmor
VENDOR_PERL=$(shell perl -e 'use Config; print $$Config{"vendorlib"};')
PERLDIR=${DESTDIR}${VENDOR_PERL}/${MODDIR}
.PHONY: install
install:
install -d ${PERLDIR}
install -m 644 ${MODULES} ${PERLDIR}
.PHONY: clean
ifndef VERBOSE
.SILENT: clean
endif
clean: _clean
rm -f core core.* *.o *.s *.a *~
rm -f Make.rules
rm -rf staging/ build/
.PHONY: check
.SILENT: check
check:
for i in ${MODULES} ${PERLTOOLS} ; do \
perl -c $$i || exit 1; \
done

132
deprecated/utils/aa-audit Executable file
View File

@@ -0,0 +1,132 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use FindBin;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
$UI_Mode = "text";
# options variables
my $help = '';
GetOptions(
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
UI_Important("Can't find AppArmor profiles in $profiledir.");
exit 1;
}
# what are we profiling?
my @profiling = @ARGV;
unless (@profiling) {
@profiling = (UI_GetString("Please enter the program to switch to audit mode: ", ""));
}
for my $profiling (@profiling) {
next unless $profiling;
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
opendir(DIR,$profiledir);
my @tmp_fqdbin = grep ( /$profiling/, readdir(DIR));
closedir(DIR);
if (scalar @tmp_fqdbin eq 1) {
$fqdbin = "$profiledir/$tmp_fqdbin[0]";
} else {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
}
if (-e $fqdbin) {
my $filename;
if ($fqdbin =~ /^$profiledir\//) {
$filename = $fqdbin;
} else {
$filename = getprofilefilename($fqdbin);
}
# argh, skip directories
next unless -f $filename;
# skip rpm backup files
next if isSkippableFile($filename);
printf(gettext('Setting %s to audit mode.'), $fqdbin);
print "\n";
setprofileflags($filename, "audit");
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
if ($? != 0) {
UI_Info($cmd_info);
exit $?;
}
# if check_for_subdomain();
} else {
if ($profiling =~ /^[^\/]+$/) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}
}
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ program to switch to audit mode ]"), $0));
exit 0;
}

122
deprecated/utils/aa-autodep Executable file
View File

@@ -0,0 +1,122 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use FindBin;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
# force $PATH to be sane
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
$UI_Mode = "text";
# options variables
my $help = '';
my $force = undef;
GetOptions(
'force' => \$force,
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
my $sd_mountpoint = check_for_subdomain();
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
UI_Important(sprintf(gettext('Can\'t find AppArmor profiles in %s.'), $profiledir));
exit 1;
}
# what are we profiling?
my @profiling = @ARGV;
unless (@profiling) {
@profiling = (UI_GetString(gettext("Please enter the program to create a profile for: "), ""));
}
for my $profiling (@profiling) {
next unless $profiling;
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
# make sure that the app they're requesting to profile is not marked as
# not allowed to have it's own profile
if ($qualifiers{$fqdbin}) {
unless ($qualifiers{$fqdbin} =~ /p/) {
UI_Info(sprintf(gettext('%s is currently marked as a program that should not have it\'s own profile. Usually, programs are marked this way if creating a profile for them is likely to break the rest of the system. If you know what you\'re doing and are certain you want to create a profile for this program, edit the corresponding entry in the [qualifiers] section in /etc/apparmor/logprof.conf.'), $fqdbin));
exit 1;
}
}
if (-e $fqdbin) {
if (-e getprofilefilename($fqdbin) && !$force) {
UI_Info(sprintf(gettext('Profile for %s already exists - skipping.'), $fqdbin));
} else {
autodep($fqdbin);
reload($fqdbin) if $sd_mountpoint;
}
} else {
if ($profiling =~ /^[^\/]+$/) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}
}
exit 0;
sub usage {
UI_Info("usage: $0 [ --force ] [ -d /path/to/profiles ]");
exit 0;
}

131
deprecated/utils/aa-complain Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use FindBin;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
$UI_Mode = "text";
# options variables
my $help = '';
GetOptions(
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
UI_Important("Can't find AppArmor profiles in $profiledir.");
exit 1;
}
# what are we profiling?
my @profiling = @ARGV;
unless (@profiling) {
@profiling = (UI_GetString(gettext("Please enter the program to switch to complain mode: "), ""));
}
for my $profiling (@profiling) {
next unless $profiling;
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
opendir(DIR,$profiledir);
my @tmp_fqdbin = grep ( /$profiling/, readdir(DIR));
closedir(DIR);
if (scalar @tmp_fqdbin eq 1) {
$fqdbin = "$profiledir/$tmp_fqdbin[0]";
} else {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
}
if (-e $fqdbin) {
my $filename;
if ($fqdbin =~ /^$profiledir\//) {
$filename = $fqdbin;
} else {
$filename = getprofilefilename($fqdbin);
}
# argh, skip directories
next unless -f $filename;
# skip rpm backup files
next if isSkippableFile($filename);
printf(gettext('Setting %s to complain mode.'), $fqdbin);
print "\n";
setprofileflags($filename, "complain");
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
if ($? != 0) {
UI_Info($cmd_info);
exit $?;
}
# if check_for_subdomain();
} else {
if ($profiling =~ /^[^\/]+$/) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}
}
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ program to switch to complain mode ]"), $0));
exit 0;
}

152
deprecated/utils/aa-disable Executable file
View File

@@ -0,0 +1,152 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005-2010 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Canonical, Inc.
#
# To contact Canonical about this file by physical or electronic mail,
# you may find current contact information at www.canonical.com.
# ----------------------------------------------------------------------
use strict;
use FindBin;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
use File::Basename;
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
$UI_Mode = "text";
# options variables
my $help = '';
GetOptions(
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
UI_Important("Can't find AppArmor profiles in $profiledir.");
exit 1;
}
my $disabledir = "$profiledir/disable";
unless (-d $disabledir) {
UI_Important("Can't find AppArmor disable directory '$disabledir'.");
exit 1;
}
# what are we profiling?
my @profiling = @ARGV;
unless (@profiling) {
@profiling = (UI_GetString(gettext("Please enter the program whose profile should be disabled: "), ""));
}
for my $profiling (@profiling) {
next unless $profiling;
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
opendir(DIR,$profiledir);
my @tmp_fqdbin = grep ( /$profiling/, readdir(DIR));
closedir(DIR);
if (scalar @tmp_fqdbin eq 1) {
$fqdbin = "$profiledir/$tmp_fqdbin[0]";
} else {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
}
if (-e $fqdbin) {
my $filename;
if ($fqdbin =~ /^$profiledir\//) {
$filename = $fqdbin;
} else {
$filename = getprofilefilename($fqdbin);
}
# argh, skip directories
next unless -f $filename;
# skip package manager backup files
next if isSkippableFile($filename);
my ($bname, $dname, $suffix) = File::Basename::fileparse($filename);
if ($bname eq "") {
UI_Info(sprintf(gettext('Could not find basename for %s.'), $filename));
exit 1;
}
printf(gettext('Disabling %s.'), $fqdbin);
print "\n";
my $link = "$disabledir/$bname";
if (! -e $link) {
if (symlink($filename, $link) != 1) {
UI_Info(sprintf(gettext('Could not create %s symlink.'), $link));
exit 1;
}
}
my $cmd_info = qx(cat $filename | $parser -I$profiledir -R 2>&1 1>/dev/null);
if ($? != 0) {
UI_Info($cmd_info);
exit $?;
}
# if check_for_subdomain();
} else {
if ($profiling =~ /^[^\/]+$/) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}
}
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ program to have profile disabled ]"), $0));
exit 0;
}

142
deprecated/utils/aa-enforce Executable file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use FindBin;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
$UI_Mode = "text";
# options variables
my $help = '';
GetOptions(
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
UI_Important("Can't find AppArmor profiles in $profiledir.");
exit 1;
}
# what are we profiling?
my @profiling = @ARGV;
unless (@profiling) {
@profiling = (UI_GetString(gettext("Please enter the program to switch to enforce mode: "), ""));
}
for my $profiling (@profiling) {
next unless $profiling;
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
opendir(DIR,$profiledir);
my @tmp_fqdbin = grep ( /$profiling/, readdir(DIR));
closedir(DIR);
if (scalar @tmp_fqdbin eq 1) {
$fqdbin = "$profiledir/$tmp_fqdbin[0]";
} else {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
}
if (-e $fqdbin) {
my $filename;
if ($fqdbin =~ /^$profiledir\//) {
$filename = $fqdbin;
} else {
$filename = getprofilefilename($fqdbin);
}
# argh, skip directories
next unless -f $filename;
# skip rpm backup files
next if isSkippableFile($filename);
printf(gettext('Setting %s to enforce mode.'), $fqdbin);
print "\n";
setprofileflags($filename, "");
# remove symlink in $profiledir/force-complain as well
my $complainlink = $filename;
$complainlink =~ s/^$profiledir/$profiledir\/force-complain/;
-e $complainlink and unlink($complainlink);
# remove symlink in $profiledir/disable as well
my $disablelink = $filename;
$disablelink =~ s/^$profiledir/$profiledir\/disable/;
-e $disablelink and unlink($disablelink);
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
if ($? != 0) {
UI_Info($cmd_info);
exit $?;
}
# if check_for_subdomain();
} else {
if ($profiling =~ /^[^\/]+$/) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}
}
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ program to switch to enforce mode ]"), $0));
exit 0;
}

940
deprecated/utils/aa-eventd Executable file
View File

@@ -0,0 +1,940 @@
#!/usr/bin/perl -w
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use Data::Dumper;
use DBI;
use Fcntl;
use File::Temp qw(tempfile);
use Getopt::Long;
use POSIX 'setsid';
use Time::Local;
use File::Tail;
use Immunix::Severity;
require LibAppArmor;
##########################################################################
# locations
my $productname = "apparmor";
my $cfgdir = "/etc/$productname";
my $dbdir = "/var/log/$productname";
my $cfgfile = "$cfgdir/notify.cfg";
my $errlog = "$dbdir/event-dispatch.log";
my $logfile = "/var/log/audit/audit.log";
my $syslogfile = "/var/log/messages";
##########################################################################
# options variables
my $pidfile = '';
GetOptions('pidfile|p=s' => \$pidfile);
my $DEBUG = 0;
my $config;
my $verbose = { last_notify => 0 };
my $summary = { last_notify => 0 };
my $terse = { last_notify => 0 };
# we don't want to call str2time on every line and also batch up event dbs
# a month at a time, so we need to keep track of a few extra things
my $timestamp = 0;
my $lasttime = "";
my $counter = 0;
my $thismonth = 0;
my $nextmonth = 0;
# pop open a connection to the severity database
my $sevdb = new Immunix::Severity("$cfgdir/severity.db", -1);
my $REdate = '\w{3}\s+\d+\s+\d{2}:\d{2}:\d{2}';
my $last_inserted_time;
my $last_inserted_counter;
##########################################################################
# commit how often?
my $timeout = 5;
# keep track of when we commited last
my $last_flush_time = 0;
# keep track of some statistics
my $max = 0;
my $inserts = 0;
my $total = 0;
my @commit_buffer;
my @debug_buffer;
my @verbose_buffer;
my @summary_buffer;
my @terse_buffer;
my $date_module = "None";
my %templates = (
"path" => "(time,counter,type,op,profile,sdmode,mode_req,mode_deny,resource,prog,pid,severity) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
"link" => "(time,counter,type,op,profile,sdmode,resource,target,prog,pid,severity) VALUES(?,?,?,?,?,?,?,?,?,?,?)",
"chattr" => "(time,counter,type,op,profile,sdmode,resource,mode_req,mode_deny,prog,pid,severity) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
"capability" => "(time,counter,type,op,profile,sdmode,resource,prog,pid,severity) VALUES(?,?,?,?,?,?,?,?,?,?)",
"capable" => "(time,counter,type,op,prog,pid,profile) VALUES(?,?,?,?,?,?,?)",
"unknown_hat" => "(time,counter,type,op,profile,sdmode,resource,pid) VALUES(?,?,?,?,?,?,?,?)",
"fork" => "(time,counter,type,op,profile,sdmode,pid,resource) VALUES(?,?,?,?,?,?,?,?)",
"changing_profile" => "(time,counter,type,op,profile,sdmode,pid) VALUES(?,?,?,?,?,?,?)",
"profile_replacement" => "(time,counter,type,op,profile,sdmode,prog,pid,severity) VALUES(?,?,?,?,?,?,?,?,?)",
"net" => "(time,counter,type,op,net_family,net_socktype,net_proto,pid,profile) VALUES(?,?,?,?,?,?,?,?,?)",
"removed" => "(time,counter,type,op,severity) VALUES(?,?,?,?,?)",
"initialized" => "(time,counter,type,op,resource,severity) VALUES(?,?,?,?,?,?)",
"ctrl_var" => "(time,counter,type,op,resource,mode_req,mode_deny,severity) VALUES(?,?,?,?,?,?,?,?)",
"profile_load" => "(time,counter,type,op,resource,prog,pid) VALUES(?,?,?,?,?,?,?)",
);
##########################################################################
# generic functions
sub errlog ($) {
my $mesg = shift;
my $localtime = localtime(time);
print ERRLOG "[$localtime] $mesg\n";
}
sub readconfig () {
my $cfg = {};
# record when we read the config file
$cfg->{load_time} = time;
if (open(CFG, $cfgfile)) {
# yank in the values we need
while (<CFG>) {
$cfg->{$1} = $2 if /^(\S+)\s+(.+)\s*$/;
}
close(CFG);
}
return $cfg;
}
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
}
sub parsedate ($) {
my $time = shift;
my $timestamp = 0;
if ($date_module eq 'TimeDate') {
$timestamp = Date::Parse::str2time($time);
} elsif ($date_module eq 'DateManip') {
$timestamp = Date::Manip::UnixDate(Date::Manip::ParseDateString($time), '%s');
} else {
errlog "No date module found, exiing";
kill HUP => -$$;
}
return $timestamp;
}
##########################################################################
# database handling functions
sub connect_database ($) {
my $dbdir = shift;
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbdir/events.db", "", "", {RaiseError=>1});
# we'll do the commits ourselves so performance doesn't suck
$dbh->{AutoCommit} = 0;
# bump up our cache size a little
$dbh->do("PRAGMA cache_size = 20000;");
# figure out if the tables already exist or not
my %existing_tables;
my $sth = $dbh->prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;");
$sth->execute;
while (my @row = $sth->fetchrow_array) {
$existing_tables{ $row[0] } = 1;
}
$sth->finish;
# create the info table and fill in the appropriate values for this db
unless ($existing_tables{info}) {
my $host = `hostname -f`;
chomp $host;
$dbh->do("CREATE TABLE info (name,value)");
$sth = $dbh->prepare("INSERT INTO info(name,value) VALUES(?,?)");
$sth->execute("version", "0.2");
$sth->execute("host", "$host");
}
# create the events table
unless ($existing_tables{events}) {
$dbh->do(
"CREATE TABLE events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
time INTEGER NOT NULL,
counter INTEGER NOT NULL,
op,
pid,
sdmode,
type,
mode_deny,
mode_req,
resource,
target,
profile,
prog,
name_alt,
attr,
parent,
active_hat,
net_family,
net_proto,
net_socktype,
severity INTEGER
)"
);
# set up the indexes we want
#my @indexes = qw(time type sdmode mode resource profile prog severity);
my @indexes = qw(time type op sdmode mode_req mode_deny resource profile prog severity);
for my $index (@indexes) {
$dbh->do("CREATE INDEX " . $index . "_idx ON events($index)");
}
}
# make sure our changes actually get saved
$dbh->commit || errlog "Error commiting changes: $!";
# mark the db as up to date as of now
$last_flush_time = time;
return $dbh;
}
##########################################################################
sub verbose_notify_handler {
my ($email, $file, $last, $level, $unknown) = @_;
$last = localtime($last);
my $now = time;
my $host = `hostname -f`;
chomp $host;
my $subj = "Verbose Security Report for $host.";
my $mesg = "The following security events occured since $last:\n\n";
my @events;
if (open(V, $file)) {
while (<V>) {
chomp;
if (/^(\d+) (\d+) (.+)$/) {
my ($timestamp, $counter, $logmsg) = ($1, $2, $3);
push @events, [ $timestamp, $counter ];
$mesg .= "$logmsg\n";
}
}
close(V);
if (@events) {
if ($DEBUG) {
my $count = scalar @events;
errlog "[$count events] sending verbose notification to $email.";
}
# actually send out the notification...
open(MAIL, "| sendmail -F 'AppArmor Security Notification' $email");
print MAIL "To: $email\n";
print MAIL "Subject: $subj\n\n";
print MAIL "$mesg\n";
print MAIL ".\n";
close(MAIL);
}
# delete the verbose notification logfile once we've processed it
unlink($file);
}
}
sub summary_notify_handler {
my ($email, $file, $last, $level, $unknown) = @_;
$last = localtime($last);
my $now = time;
my $host = `hostname -f`;
chomp $host;
my $subj = "Summary Security Report for $host.";
my $mesg = "The following security events occured since $last:\n\n";
my @events;
if (open(V, $file)) {
while (<V>) {
chomp;
if (/^(\d+) (\d+) (.+)$/) {
my ($timestamp, $counter, $logmsg) = ($1, $2, $3);
push @events, [ $timestamp, $counter ];
$mesg .= "$logmsg\n";
}
}
close(V);
if (@events) {
if ($DEBUG) {
my $count = scalar @events;
errlog "[$count events] sending summary notification to $email.";
}
# actually send out the notification...
open(MAIL, "| sendmail -F 'AppArmor Security Notification' $email");
print MAIL "To: $email\n";
print MAIL "Subject: $subj\n\n";
print MAIL "$mesg\n";
print MAIL ".\n";
close(MAIL);
}
# delete the verbose notification logfile once we've processed it
unlink($file);
}
}
sub terse_notify_handler {
my ($email, $file, $last, $level, $unknown) = @_;
$last = localtime($last);
my $now = time;
my $host = `hostname -f`;
chomp $host;
my @events;
my $count = 0;
if (open(V, $file)) {
while (<V>) {
chomp;
if (/^(\d+) (\d+) (.+)$/) {
my ($timestamp, $counter, $logmsg) = ($1, $2, $3);
push @events, [ $timestamp, $counter ];
$count++;
}
}
close(V);
if ($count) {
if ($DEBUG) {
errlog "[$count events] sending terse notification to $email.";
}
my $subj = "Security Report for $host.";
my $mesg = "$host has had $count security events since $last.";
# actually send out the notification...
open(MAIL, "| sendmail -F 'AppArmor Security Notification' $email");
print MAIL "To: $email\n";
print MAIL "Subject: $subj\n\n";
print MAIL "$mesg\n";
print MAIL ".\n";
close(MAIL);
}
# delete the terse notification logfile once we've processed it
unlink($file);
}
}
sub fork_into_background {
my ($name, $func, @args) = @_;
my $pid = fork;
if (not defined $pid) {
# something bad happened, just log it...
errlog "couldn't fork for \"$name\": $!"
} elsif ($pid == 0) {
# we're in the child process now...
# set our process name
$0 = $name;
# call our subroutine
my $ret = &$func(@args);
exit($ret);
}
return $pid;
}
##########################################################################
# Parse event record into key-value pairs
sub parseEvent($) {
my %ev = ();
my $msg = shift;
chomp($msg);
my $event = LibAppArmor::parse_record($msg);
# resource is an alternate term for 'name1' below
# mode is an alternate term for 'mode_deny' below
$ev{'time'} = LibAppArmor::aa_log_record::swig_epoch_get($event);
$ev{'op'} = LibAppArmor::aa_log_record::swig_operation_get($event);
$ev{'pid'} = LibAppArmor::aa_log_record::swig_pid_get($event);
$ev{'mode_deny'} = LibAppArmor::aa_log_record::swig_denied_mask_get($event);
$ev{'mode_req'} = LibAppArmor::aa_log_record::swig_requested_mask_get($event);
$ev{'profile'}= LibAppArmor::aa_log_record::swig_profile_get($event);
$ev{'prog'} = LibAppArmor::aa_log_record::swig_name_get($event);
$ev{'name2'} = LibAppArmor::aa_log_record::swig_name2_get($event);
$ev{'attr'} = LibAppArmor::aa_log_record::swig_attribute_get($event);
$ev{'parent'} = LibAppArmor::aa_log_record::swig_parent_get($event);
$ev{'magic_token'} = LibAppArmor::aa_log_record::swig_magic_token_get($event);
$ev{'resource'} = LibAppArmor::aa_log_record::swig_info_get($event);
$ev{'active_hat'} = LibAppArmor::aa_log_record::swig_active_hat_get($event);
$ev{'sdmode'} = LibAppArmor::aa_log_record::swig_event_get($event);
# NetDomain
if ( $ev{'op'} && $ev{'op'} =~ /socket/ ) {
next if $ev{'op'} =~ /create/;
$ev{'net_family'} = LibAppArmor::aa_log_record::swig_net_family_get($event);
$ev{'net_proto'} = LibAppArmor::aa_log_record::swig_net_protocol_get($event);
$ev{'net_socktype'} = LibAppArmor::aa_log_record::swig_net_sock_type_get($event);
}
LibAppArmor::free_record($event);
if ( ! $ev{'time'} ) { $ev{'time'} = time; }
# remove null responses
for (keys(%ev)) {
if ( ! $ev{$_} || $ev{$_} !~ /\w+/) {delete($ev{$_}); }
#errlog "EVENT: $_ is $ev{$_}";
}
if ( $ev{'sdmode'} ) {
#0 = invalid, 1 = error, 2 = AUDIT, 3 = ALLOW/PERMIT,
#4 = DENIED/REJECTED, 5 = HINT, 6 = STATUS/config change
if ( $ev{'sdmode'} == 2 ) { $ev{'sdmode'} = "AUDITING"; }
elsif ( $ev{'sdmode'} == 3 ) { $ev{'sdmode'} = "PERMITING"; }
elsif ( $ev{'sdmode'} == 4 ) { $ev{'sdmode'} = "REJECTING"; }
else { delete($ev{'sdmode'}); }
}
return \%ev;
}
sub process_event ($$) {
my $dbh = shift;
my $logmsg = shift;
my $sth;
my $severity = "";
my @eventList = ();
my $type = undef;
my $time = undef;
return unless $logmsg && $logmsg =~ /APPARMOR/;
my $ev = parseEvent($logmsg);
# skip logprof hints
if ( ! $ev->{'op'} || $ev->{'op'} eq 'clone') { return; }
$time = time; # XXX - do we want current time or $ev->{'time'}?
if ($time ne $lasttime) {
$counter = 0;
$timestamp = $time;
$lasttime = $time;
}
$counter++;
# some statistics...
$max = $counter if $counter > $max;
# if we already have events in the db, make sure we don't try to re-enter
# duplicates if we start up again and parse the same logfile over again
if ($last_inserted_time) {
return if $timestamp < $last_inserted_time;
if ($timestamp == $last_inserted_time) {
return if $counter <= $last_inserted_counter;
}
$last_inserted_time = undef;
}
if ( $ev->{'sdmode'} && $ev->{'sdmode'} eq "REJECTING") {
$severity = $sevdb->rank($ev->{'prog'}, $ev->{'mode_req'});
if ( ! $severity ) { $severity = "-1"; }
# we only do notification for enforce mode events
if ($config->{verbose_freq}) {
if ( ($severity >= $config->{verbose_level})
|| (($severity == -1) && $config->{verbose_unknown}))
{
push @verbose_buffer, [ $timestamp, $counter, $logmsg ];
}
}
if ($config->{summary_freq}) {
if ( ($severity >= $config->{summary_level})
|| (($severity == -1) && $config->{summary_unknown}))
{
push @summary_buffer, [ $timestamp, $counter, "path",
$ev->{'prog'}, $ev->{'mode_req'}, $ev->{'resource'} ];
}
}
if ($config->{terse_freq}) {
if ( ($severity >= $config->{terse_level})
|| (($severity == -1) && $config->{terse_unknown}))
{
push @terse_buffer, [ $timestamp, $counter, "dummy" ];
}
}
}
unless ( $ev->{'op'} ) {
my $errmsg = "ERROR: No operation found: ";
for my $k (sort keys(%$ev)) {
$errmsg .= "$k is $ev->{$k}, ";
}
errlog("$errmsg\n");
return;
}
# Format the message to match the db template
if ($ev->{'op'} eq 'link' ) {
$type = 'link';
push(@eventList, [$time,$counter,$type,$ev->{'profile'},$ev->{'sdmode'},
$ev->{'resource'},$ev->{'target'},$ev->{'prog'},$ev->{'pid'},$severity]);
} elsif ($ev->{'op'} eq 'attribute') {
$type = 'chattr';
push(@eventList, []);
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'resource'},$ev->{'mode_req'},$ev->{'mode_deny'},$ev->{'prog'},
$ev->{'pid'},$severity]);
} elsif ($ev->{'op'} eq 'capability') {
$type = 'capability';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'resource'},$ev->{'prog'},$ev->{'pid'},$severity]);
} elsif ($ev->{'op'} eq 'capable') {
$type = 'capable';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'prog'},
$ev->{'profile'},$ev->{'pid'}]);
} elsif ($ev->{'op'} =~ /ontrol variable/ ) {
$type = 'ctrl_var';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'resource'},
$ev->{'mode_req'},$ev->{'mode_deny'},$severity]);
} elsif ($ev->{'op'} eq 'unknown_hat') {
$type = 'unknown_hat';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'resource'},$ev->{'pid'},$severity]);
} elsif ($ev->{'op'} eq 'fork') {
$type = 'fork';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'pid'},$ev->{'resource'}]);
} elsif ($ev->{'op'} eq 'changing_profile') {
$type = 'changing_profile';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'pid'}]);
} elsif ($ev->{'op'} eq 'profile_load') {
$type = 'profile_load';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'resource'},
$ev->{'prog'},$ev->{'pid'}]);
} elsif ($ev->{'op'} eq 'profile_replace') {
$type = 'profile_replacement';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},$ev->{'sdmode'},
$ev->{'prog'},$ev->{'pid'},$severity]);
} elsif ($ev->{'op'} eq 'removed') {
$type = 'removed';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$severity]);
} elsif ($ev->{'op'} eq 'initialized') {
$type = 'initialized';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'resource'},$severity]);
} elsif ( $ev->{'op'} =~ /socket/) {
$type = 'net';
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'net_family'},
$ev->{'net_sock_type'},$ev->{'net_proto'},$ev->{'pid'},$ev->{'profile'}]);
} else {
$type = 'path';
if ( ! $ev->{'prog'} ) { $ev->{'prog'} = "NIL"; }
push(@eventList, [$time,$counter,$type,$ev->{'op'},$ev->{'profile'},
$ev->{'sdmode'},$ev->{'mode_req'},$ev->{'mode_deny'},$ev->{'resource'},
$ev->{'prog'},$ev->{'pid'},$severity]);
}
push(@commit_buffer, @eventList);
$inserts++;
}
sub dump_events {
my ($which, @events) = @_;
if ($DEBUG) {
my $count = scalar @events;
errlog "dumping $count events to $which db.";
}
if (open(F, ">>$dbdir/$which.db")) {
for my $event (@events) {
my @event = @$event;
print F "@event\n";
}
close(F);
} else {
errlog "can't write to $dbdir/$which.db: $!";
}
}
sub check_timers ($) {
my $dbh = shift;
# what time is it right... NOW
my $now = time;
# make sure we commit periodically
if (($inserts > 10000) || ($now >= ($last_flush_time + $timeout))) {
my $last_prepare = "";
my $sth;
for my $event (sort { $a->[0] cmp $b->[0] } @commit_buffer) {
my @event = @{$event};
#my $type = shift @event;
my $type = $event[2];
eval {
if ($type ne $last_prepare) {
$sth = $dbh->prepare("INSERT INTO events $templates{$type}");
$last_prepare = $type;
}
$sth->execute(@event);
};
if ($@) {
print ERRLOG "DBI Execution failed: $DBI::errstr\n";
}
#$sth->execute(@event);
}
$dbh->commit || errlog "Error commiting changes: $!";
# need to get the time again to include how much time it takes to
# actually write all this crap to the db
$now = time;
if ($DEBUG && $inserts) {
$total += $inserts;
my $delta = $now - $last_flush_time;
my $rate = int($inserts / $delta);
errlog "$rate/s $inserts in ${delta}s total=$total max=$max";
}
$last_flush_time = $now;
@commit_buffer = ();
$max = 0;
$inserts = 0;
if (@verbose_buffer) {
# if we've got verbose events, dump them
dump_events("verbose", @verbose_buffer);
# and clear out our buffer
@verbose_buffer = ();
}
if (@terse_buffer) {
# if we've got terse events, dump them
dump_events("terse", @terse_buffer);
# and clear out our buffer
@terse_buffer = ();
}
# bail out if we don't have notification configured
return unless -f $cfgfile;
# what time did we last read the config file?
my $load_time = $config->{load_time};
# check when the config file was last modified...
my $mtime = (stat($cfgfile))[9];
# if it's been changed since we last read the config file, we need to
# load the new settings
if ($load_time < $mtime) {
errlog "Reloading changed config file.";
$config = readconfig();
}
}
# bail out if we don't have notification configured
return unless -f $cfgfile;
if ($config->{terse_freq}) {
if (($terse->{last_notify} + $config->{terse_freq}) <= $now) {
if (-f "$dbdir/terse.db") {
$DEBUG && errlog "doing terse notification...";
# get a temporary filename...
my ($fh, $filename) = tempfile("terseXXXXXX", DIR => $dbdir);
# overwrite the temp file we just created...
rename("$dbdir/terse.db", $filename);
if ($DEBUG) {
errlog "terse file is $filename";
}
# do the actual notification in the background
fork_into_background("terse-notification",
\&terse_notify_handler,
$config->{terse_email},
$filename,
$terse->{last_notify},
$config->{terse_level},
$config->{terse_unknown});
# ...keep track of when we last sent out a notify
$terse->{last_notify} = $now;
}
}
}
if ($config->{summary_freq}) {
if (($summary->{last_notify} + $config->{summary_freq}) <= $now) {
if (-f "$dbdir/summary.db") {
$DEBUG && errlog "doing summary notification...";
# get a temporary filename...
my ($fh, $filename) = tempfile("summaryXXXXXX", DIR => $dbdir);
# overwrite the temp file we just created...
rename("$dbdir/summary.db", $filename);
# do the actual notification in the background
fork_into_background("summary-notification",
\&summary_notify_handler,
$config->{summary_email},
$filename,
$summary->{last_notify},
$config->{summary_level},
$config->{summary_unknown});
# ...keep track of when we last sent out a notify
$summary->{last_notify} = $now;
}
}
}
if ($config->{verbose_freq}) {
if (($verbose->{last_notify} + $config->{verbose_freq}) <= $now) {
if (-f "$dbdir/verbose.db") {
$DEBUG && errlog "doing verbose notification...";
# get a temporary filename...
my ($fh, $filename) = tempfile("verboseXXXXXX", DIR => $dbdir);
# overwrite the temp file we just created...
rename("$dbdir/verbose.db", $filename);
if ($DEBUG) {
errlog "verbose file is $filename";
}
# do the actual notification in the background
fork_into_background("verbose-notification",
\&verbose_notify_handler,
$config->{verbose_email},
$filename,
$verbose->{last_notify},
$config->{verbose_level},
$config->{verbose_unknown});
# ...keep track of when we last sent out a notify
$verbose->{last_notify} = $now;
}
}
}
}
sub get_last_event {
my $dbh = shift;
my ($time, $counter);
# get the oldest timestamp...
my $sth = $dbh->prepare('SELECT MAX(time) FROM events');
$sth->execute;
my @row = $sth->fetchrow_array || (0);
$time = $row[0];
if ($time) {
# get the highest counter for this timestamp...
$sth = $dbh->prepare("SELECT MAX(counter) FROM events WHERE time = $time");
$sth->execute;
@row = $sth->fetchrow_array || (0);
$counter = $row[0];
}
return ($time, $counter);
}
##########################################################################
# start the real magic...
my $finished;
# make sure we exit if someone sends us the right signal
sub sig_handler {
my $signame = shift;
errlog("Caught signal '$signame'. Exiting...");
$finished = 1;
}
# set up our error log without buffering
open(ERRLOG, ">>$dbdir/event-dispatch.log");
my $oldfd = select(ERRLOG);
$| = 1;
select($oldfd);
$config = readconfig();
# fork off into the background. we need to do this before we connect to
# the db, otherwise, we'll get an ugly error about rolling back a
# connection that's being destroyed
daemonize;
# automagically reap child processes
$SIG{INT} = \&sig_handler;
$SIG{TERM} = \&sig_handler;
$SIG{CHLD} = 'IGNORE';
# Sigh, portable dates in perl sucks
eval "use Date::Parse";
if (!$@) {
$date_module = 'TimeDate';
} else {
eval "use Date::Manip";
if (!$@) {
$date_module = 'DateManip';
} else {
errlog "Unable to load Date module; use either TimeDate or Date::Manip";
$finished = 1;
}
}
# if they want us to write a pid, do it
if ($pidfile) {
if (open(PIDFILE, ">$pidfile")) {
print PIDFILE "$$\n";
close(PIDFILE);
}
}
my $dbh = connect_database($dbdir);
($last_inserted_time, $last_inserted_counter) = get_last_event($dbh);
my $auditlog = File::Tail->new(
name => $logfile,
debug => 1,
tail => -1,
interval => 1,
maxinterval => 5,
adjustafter => 20,
errmode => "return",
ignore_noexistant => 1
);
my $syslog = File::Tail->new(
name => $syslogfile,
debug => 1,
tail => -1,
interval => 1,
maxinterval => 5,
adjustafter => 20,
errmode => "return",
ignore_noexistant => 1
);
my $line = '';
# process complete lines from the buffer...
while (not $finished) {
my ($nfound, $timeleft, @pending) = File::Tail::select(undef, undef, undef, $timeout, ($auditlog, $syslog));
foreach (@pending) {
process_event($dbh, $_->read);
}
# see if we should flush pending entries to disk and/or do notification
check_timers($dbh);
}
# make sure we don't exit with any pending events not written to the db
$dbh->commit || errlog "Error commiting changes: $!";
$dbh->disconnect || errlog "Error disconnecting from db: $!";
# close our error/debugging log file
close(ERRLOG);
unlink($pidfile) if $pidfile;
exit 0;

216
deprecated/utils/aa-genprof Executable file
View File

@@ -0,0 +1,216 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use Getopt::Long;
use Immunix::AppArmor;
use Data::Dumper;
use Locale::gettext;
use POSIX;
sub sysctl_read($) {
my $path = shift;
my $value = undef;
if (open(SYSCTL, "<$path")) {
$value = int(<SYSCTL>);
}
close(SYSCTL);
return $value;
}
sub sysctl_write($$) {
my $path = shift;
my $value = shift;
return if (!defined($value));
if (open(SYSCTL, ">$path")) {
print SYSCTL $value;
close(SYSCTl);
}
}
# force $PATH to be sane
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
# options variables
my $help = '';
GetOptions(
'file|f=s' => \$filename,
'dir|d=s' => \$profiledir,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
my $sd_mountpoint = check_for_subdomain();
unless ($sd_mountpoint) {
fatal_error(gettext("AppArmor does not appear to be started. Please enable AppArmor and try again."));
}
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
fatal_error "Can't find AppArmor profiles in $profiledir.";
}
# what are we profiling?
my $profiling = shift;
unless ($profiling) {
$profiling = UI_GetString(gettext("Please enter the program to profile: "), "")
|| exit 0;
}
my $fqdbin;
if (-e $profiling) {
$fqdbin = get_full_path($profiling);
chomp($fqdbin);
} else {
if ($profiling !~ /\//) {
my $which = which($profiling);
if ($which) {
$fqdbin = get_full_path($which);
}
}
}
unless ($fqdbin && -e $fqdbin) {
if ($profiling =~ /^[^\/]+$/) {
fatal_error(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' in the other window in order to find the fully-qualified path.'), $profiling, $profiling));
} else {
fatal_error(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
}
}
# make sure that the app they're requesting to profile is not marked as
# not allowed to have it's own profile
check_qualifiers($fqdbin);
# load all the include files
loadincludes();
my $profilefilename = getprofilefilename($fqdbin);
if (-e $profilefilename) {
$helpers{$fqdbin} = getprofileflags($profilefilename) || "enforce";
} else {
autodep($fqdbin);
$helpers{$fqdbin} = "enforce";
}
if ($helpers{$fqdbin} eq "enforce") {
complain($fqdbin);
reload($fqdbin);
}
# When reading from syslog, it is possible to hit the default kernel
# printk ratelimit. This will result in audit entries getting skipped,
# making profile generation inaccurate. When using genprof, disable
# the printk ratelimit, and restore it on exit.
my $ratelimit_sysctl = "/proc/sys/kernel/printk_ratelimit";
my $ratelimit_saved = sysctl_read($ratelimit_sysctl);
END { sysctl_write($ratelimit_sysctl, $ratelimit_saved); }
sysctl_write($ratelimit_sysctl, 0);
UI_Info(gettext("\nBefore you begin, you may wish to check if a\nprofile already exists for the application you\nwish to confine. See the following wiki page for\nmore information:\nhttp://wiki.apparmor.net/index.php/Profiles"));
UI_Important(gettext("Please start the application to be profiled in \nanother window and exercise its functionality now.\n\nOnce completed, select the \"Scan\" button below in \norder to scan the system logs for AppArmor events. \n\nFor each AppArmor event, you will be given the \nopportunity to choose whether the access should be \nallowed or denied."));
my $syslog = 1;
my $logmark = "";
my $done_profiling = 0;
$syslog = 0 if (-e "/var/log/audit/audit.log");
while (not $done_profiling) {
if ($syslog) {
$logmark = `date | md5sum`;
chomp $logmark;
$logmark = $1 if $logmark =~ /^([0-9a-f]+)/;
system("$logger -p kern.warn 'GenProf: $logmark'");
} else {
$logmark = last_audit_entry_time();
}
eval {
my $q = {};
$q->{headers} = [ gettext("Profiling"), $fqdbin ];
$q->{functions} = [ "CMD_SCAN", "CMD_FINISHED" ];
$q->{default} = "CMD_SCAN";
my ($ans, $arg) = UI_PromptUser($q);
if ($ans eq "CMD_SCAN") {
my $lp_ret = do_logprof_pass($logmark);
$done_profiling = 1 if $lp_ret eq "FINISHED";
} else {
$done_profiling = 1;
}
};
if ($@) {
if ($@ =~ /FINISHING/) {
$done_profiling = 1;
} else {
die $@;
}
}
}
for my $p (sort keys %helpers) {
if ($helpers{$p} eq "enforce") {
enforce($p);
reload($p);
}
}
UI_Info(gettext("Reloaded AppArmor profiles in enforce mode."));
UI_Info(gettext("\nPlease consider contributing your new profile! See\nthe following wiki page for more information:\nhttp://wiki.apparmor.net/index.php/Profiles\n"));
UI_Info(sprintf(gettext('Finished generating profile for %s.'), $fqdbin));
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ -f /path/to/logfile ] [ program to profile ]"), $0));
exit 0;
}
sub last_audit_entry_time {
local $_ = `tail -1 /var/log/audit/audit.log`;
my $logmark;
if (/^*msg\=audit\((\d+\.\d+\:\d+).*\).*$/) {
$logmark = $1;
} else {
$logmark = "";
}
return $logmark;
}

72
deprecated/utils/aa-logprof Executable file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
use strict;
use Data::Dumper;
use Getopt::Long;
use Locale::gettext;
use POSIX;
use Immunix::AppArmor;
# force $PATH to be sane
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
setup_yast();
# options variables
my $help = '';
my $logmark;
GetOptions(
'file|f=s' => \$filename,
'dir|d=s' => \$profiledir,
'logmark|m=s' => \$logmark,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
# let's convert it to full path...
$profiledir = get_full_path($profiledir);
unless (-d $profiledir) {
fatal_error "Can't find AppArmor profiles in $profiledir.";
}
# load all the include files
loadincludes();
do_logprof_pass($logmark);
shutdown_yast();
exit 0;
sub usage {
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ -f /path/to/logfile ] [ -m \"mark in log to start processing after\""), $0));
exit 0;
}

821
deprecated/utils/aa-repo.pl Normal file
View File

@@ -0,0 +1,821 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2008 Dominic Reynolds. All Rights Reserved.
#
# 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.
#
#
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
#
my $usage =
"aa-repo.pl --command args\n";
my $usage_search =
" --search [author=XXX] [prog=XXX] [id=XXX]
Search the repository for profiles matching the search criteria
and return the results.
NOTE: One --search switch per option
--verbose|v
Verbosity level. Supply either one or two switches. Two switches
adds full profile text in returned search results.\n";
my $usage_push =
" --push [--profile=XXX|all] [--changelog=XXX]
Push local profiles to repository, uses configured user and upon
overwrite of an existing profile in the repository then prompt
user with a diff for confirmation XXX the name of the application
whose profile should be uploaded or \"all\" to upload all
profiles. Multiple --profile switches may be passed to supply
multiple profile names
e.g. --push --profile /usr/sbin/mdnsd --profile /usr/sbin/ftp
e.g. --push --profile all\n";
my $usage_pull =
" --pull [--author=XXX] [--profile=XXX] or [--id=XXX] [--mode=complain]
pull remote profiles and install on local system
If operation will change local profiles then prompt user with
diff for confirmation
NOTE: One --pull switch per option and there are three acceptable
combinations
--pull --author=XXX
* pull all profiles in the repo for the author
--pull --author=XXX --profile=XXXX
* pull the profile for prog owned by author
--pull --id=XXXX
* pull the profile with id
--pull --mode=complain
* set the profile(s) to complain mode when installed
Profiles are checked for conflicts with currently installed
profiles and presented as a list to the user to confirm and view.\n";
my $usage_sync =
" --sync [--up] [--down] [--noconfirm]
Synchronize local profile set with the repository - showing
changes and allowing prompting the user with the diffs and
suggest the newest version to be activated. If the --all option
is passed then treat profiles not marked as remote as new
profiles that will be uploaded to the repository.\n";
my $usage_stat =
" --status
Show the current status of the local profile set. This operation
is similar to sync but does not prompt the user to up|down load
changes\n";
my $usage_getconfig =
" --getconfig|c
Print the current configuration for the repsository\n";
my $usage_setconfig =
" --setconfig [url=xxx] [username=xxxx] [password=xxxx] [enabled=(yes|no)]
[upload=(yes|no)]
Set the configuration options for the repository.
NOTE: One --setconfig switch per option\n";
my $usage_bottom =
" --quiet|q Don't prompt user - assume that all changes should be made.
ISSUES:
o Should changes made to the system be recorded somehow? An audit event?
o Should the tool allow a repo/distro to be passed for each operation?
";
use strict;
use Getopt::Long;
use Immunix::AppArmor;
use Immunix::Repository;
use Data::Dumper;
use Locale::gettext;
use POSIX;
# force $PATH to be sane
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
# initialize the local poo
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
# options variables
my $help = '';
my $verbose = '';
my ( $id, $author, $mode, %search, $sync, $getconfig, $push,
$pull, %setconfig, @profiles, $all, $changelog, $stat );
GetOptions(
'search=s%' => \%search,
'sync=s' => \$sync,
'status' => \$stat,
'getconfig|c' => \$getconfig,
'setconfig=s%' => \%setconfig,
'push' => \$push,
'id=s' => \$id,
'author=s' => \$author,
'profile=s' => \@profiles,
'changelog=s' => \$changelog,
'pull' => \$pull,
'all|a' => \$all,
'help|h' => \$help,
'verbose|v+' => \$verbose
);
#
# Root privs required to run the repo tool
#
if ( geteuid() != 0 ) {
print STDERR gettext(
"You must be logged in with root user privileges to use this program.\n"
);
exit;
}
# --help
# tell 'em how to use it...
&usage && exit if $help;
my $config = get_repo_config();
#
# --getconfig operation
#
&config && exit if $getconfig;
my $sd_mountpoint = check_for_subdomain();
unless ($sd_mountpoint) {
fatal_error(gettext(
"AppArmor does not appear to be started. Please enable AppArmor and try again."
)
);
}
#
# --setconfig operation
#
if ( keys %setconfig ) {
$config->{url} = $setconfig{url} if ( $setconfig{url} );
$config->{distro} = $setconfig{distro} if ( $setconfig{distro} );
$config->{enabled} = $setconfig{enabled} if ( $setconfig{enabled} );
$config->{email} = $setconfig{email} if ( $setconfig{email} );
$config->{user} = $setconfig{username} if ( $setconfig{username} );
$config->{password} = $setconfig{password} if ( $setconfig{password} );
$config->{upload} = $setconfig{upload} if ( $setconfig{upload} );
set_repo_config( $config );
}
#
# --push operation
#
if ( $push ) {
my ($conflicts, $repo_profiles, $local_profiles, @overrides);
if ( ! @profiles ) {
print STDERR gettext(
"Must supply at least one profile using \"--profile XXX\" to --push\n"
);
exit 1;
} else {
print STDERR Data::Dumper->Dump([@profiles], [qw(*profiles)]);
}
my $changelog = $changelog?$changelog:"none";
push_profiles( \@profiles, $changelog, 1 );
}
#
# --pull operation
#
if ( $pull ) {
my $type = "";
if ( $id ) {
if ( $author || @profiles ) {
print STDERR gettext(
"Option --id=XX is only allowed by itself and not in combination to
other options for the --pull command.\n"
);
exit 1;
}
$type = "id";
}
if ( @profiles && ! $author ) {
print STDERR gettext(
"Option --profile=XX requires that the --author=XX option be supplied
to distinguish a specific profile.\n"
);
exit 1;
} else {
$type = "profile";
}
my $mode = $mode eq "complain"?1:0;
pull_profiles( \@profiles, $type, $mode, 1 );
}
#
# --search operation
#
if ( keys %search ) {
if ( $search{id} ) {
my($status,$result) = fetch_profile_by_id( $config->{url},
$search{id} );
if ($status) {
my $title = sprintf(gettext( "Profile ID %s\n"), $search{id});
console_print_search_results( $title,
"profile",
{ $result->{name} => $result }
);
} else {
print STDERR "ERROR $result\n";
}
} elsif ( $search{author} && $search{prog} ) {
my($status,$result) =
fetch_profiles_by_name_and_user( $config->{url},
$config->{distro},
$search{prog},
$search{author}
);
if ( $status ) {
my $title =
sprintf(gettext("Profiles matching user: %s and program: %s\n"),
$search{author},
$search{prog}
);
console_print_search_results( $title, "profile", $result );
} else {
print STDERR "ERROR $result\n";
}
} elsif ( $search{author} ) {
my($status,$result) = fetch_profiles_by_user( $config->{url},
$config->{distro},
$search{author}
);
if ( $status ) {
my $title = sprintf(gettext( "Profiles for %s\n"), $search{author});
console_print_search_results( $title, "profile", $result );
} else {
print STDERR "ERROR $result\n";
}
} elsif ( $search{prog} ) {
my($status,$result) = fetch_profiles_by_name( $config->{url},
$config->{distro},
$search{prog},
);
if ( $status ) {
my $title = sprintf(gettext("Profiles matching program: %s\n"),
$search{prog});
console_print_search_results( $title, "user", $result );
} else {
print STDERR "ERROR $result\n";
}
} else {
print STDERR
"Unsupported search criteria. Please specify at least one of
author=XXX prog=XXX id=XXX\n";
}
}
if ( $stat ) {
my ( $local_profiles, $remote_profiles );
my $msg =
" The following profiles are stored in the repository but
are not synchronized with the copy in the repository\n";
my ($status, $result) = fetch_profiles_by_user( $config->{url},
$config->{distro},
$config->{user}
);
if ( $status ) {
$remote_profiles = $result;
} else {
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
$result);
exit;
}
readprofiles();
$local_profiles = serialize_local_profiles( \%sd );
my ($local_only,$unsynched,$synched,$conflicts) = ({}, {}, {});
$unsynched = find_profile_conflicts($remote_profiles, $local_profiles);
for my $p ( keys %$local_profiles ) {
if ( ! $remote_profiles->{$p} ) {
$local_only->{$p} = $local_profiles->{$p};
}
}
for my $p ( keys %$remote_profiles ) {
$synched->{$p} =
$remote_profiles->{$p}->{profile} if ( ! %$unsynched->{$p} );
}
UI_status($synched, $unsynched, $local_only);
}
######################
# Helper functions
######################
#
# Compare the local profile set with the remote profile set.
# Return a list of the conflicting profiles as a list
# { PROFILE_NAME => [LOCAL_PROFILE, REMOTE_PROFILE] ]
#
#
# remote_profiles = repository profiles as returned by one of the
# Immunix::Repository::fetch... functions
# local_profiles = hash ref containing
# { name => serialized local profile }
#
#
sub find_profile_conflicts ($$) {
my ($remote_profiles,$local_profiles) = @_;
my $conflicts = {};
for my $p ( keys(%$local_profiles) ) {
if ( $local_profiles->{$p} and $remote_profiles->{$p} ) {
my $p_local = $local_profiles->{$p};
my $p_remote = $remote_profiles->{$p}->{profile};
chomp($p_local);
chomp($p_remote);
if ( $p_remote ne $p_local ) {
$conflicts->{$p} = [ $p_local, $p_remote ];
}
}
}
return( $conflicts );
}
sub serialize_local_profiles ($) {
my $profiles = shift;
my $local_profiles = {};
for my $p ( keys %$profiles ) {
my $serialize_opts = {};
$serialize_opts->{NO_FLAGS} = 1;
my $p_local = serialize_profile( $profiles->{$p},
$p,
$serialize_opts );
$local_profiles->{$p} = $p_local;
}
return $local_profiles;
}
sub console_print_search_results ($$$) {
my ($title, $type,$result) = @_;
open(PAGER, "| less") or die "Can't open pager";
print PAGER $title;
print PAGER "Found " . values(%$result) . " profiles \n";
for my $p ( values(%$result) ) {
if ( $verbose ) {
if ( $type eq "user" ) {
print PAGER " Author [ " . $p->{username} . " ]\n";
} elsif ( $type eq "profile" ) {
print PAGER " Name [ " . $p->{name} . " ]\n";
}
print PAGER " Created [ " . $p->{created_at} . " ]\n";
print PAGER " Downloads [ " . $p->{downloaded_count} . " ]\n";
print PAGER " ID [ " . $p->{id} . " ]\n";
if ( $verbose > 1 ) {
print PAGER " Profile [ \n" . $p->{profile} . " ]\n\n";
} else {
print PAGER "\n";
}
} else {
my $data = $type eq "user"?$p->{username}:$p->{name};
print PAGER " " . $data . "\n";
}
}
close PAGER;
}
sub UI_resolve_profile_conflicts {
my ($explanation, $conflict_hash) = @_;
my $url = $config->{url};
my @conflicts = map { [ $_,
$conflict_hash->{$_}->[0],
$conflict_hash->{$_}->[1]
] }
keys %$conflict_hash;
my @commits = [];
my $title = "Profile conflicts";
my %resolution = ();
my $q = {};
$q->{title} = $title;
$q->{headers} = [ "Repository", $url, ];
$q->{explanation} = $explanation;
$q->{functions} = [ "CMD_OVERWRITE",
"CMD_KEEP",
"CMD_VIEW_CHANGES",
"CMD_ABORT",
"CMD_CONTINUE", ];
$q->{default} = "CMD_OVERWRITE";
$q->{options} = [ map { $_->[0] } @conflicts ];
$q->{selected} = 0;
my ($ans, $arg);
do {
($ans, $arg) = UI_PromptUser($q);
if ($ans eq "CMD_VIEW_CHANGES") {
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
}
if ( $ans eq "CMD_OVERWRITE") {
$q->{options} =
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
$conflicts[$arg]->[0] . " O":
$_ }
@{$q->{options}}
];
$resolution{$conflicts[$arg]->[0]} = "O";
}
if ( $ans eq "CMD_KEEP") {
$q->{options} =
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
$conflicts[$arg]->[0] . " K":
$_ }
@{$q->{options}}
];
$resolution{$conflicts[$arg]->[0]} = "K";
}
$q->{selected} = ($arg+1) % @conflicts;
} until $ans =~ /^CMD_CONTINUE/;
if ($ans eq "CMD_CONTINUE") {
my @results = ();
for my $p ( keys %resolution ) {
if ( $resolution{$p} eq "O" ) {
push @results, $p;
}
}
return @results;
}
}
sub UI_display_profiles {
my ($explanation, $profile_hash) = @_;
my $url = $config->{url};
my @profiles = map { [ $_, $profile_hash->{$_} ] } keys %$profile_hash;
my $title = gettext("Profiles");
my $q = {};
$q->{title} = $title;
$q->{headers} = [ "Repository", $url, ];
$q->{explanation} = $explanation;
$q->{functions} = [ "CMD_VIEW",
"CMD_CONTINUE", ];
$q->{default} = "CMD_CONTINUE";
$q->{options} = [ map { $_->[0] } @profiles ];
$q->{selected} = 0;
my ($ans, $arg);
do {
($ans, $arg) = UI_PromptUser($q);
if ($ans eq "CMD_VIEW") {
my $pager = get_pager();
open ( PAGER, "| $pager" ) or die "Can't open $pager";
print PAGER gettext("Profile: ") . $profiles[$arg]->[0] . "\n";
print PAGER $profiles[$arg]->[1];
close PAGER;
}
$q->{selected} = ($arg+1) % @profiles;
} until $ans =~ /^CMD_CONTINUE/;
return;
}
sub UI_display_profile_conflicts {
my ($explanation, $conflict_hash) = @_;
my $url = $config->{url};
my @conflicts = map { [ $_,
$conflict_hash->{$_}->[0],
$conflict_hash->{$_}->[1]
] }
keys %$conflict_hash;
my @commits = [];
my $title = gettext("Profile conflicts");
my $q = {};
$q->{title} = $title;
$q->{headers} = [ "Repository", $url, ];
$q->{explanation} = $explanation;
$q->{functions} = [ "CMD_VIEW_CHANGES",
"CMD_CONTINUE", ];
$q->{default} = "CMD_CONTINUE";
$q->{options} = [ map { $_->[0] } @conflicts ];
$q->{selected} = 0;
my ($ans, $arg);
do {
($ans, $arg) = UI_PromptUser($q);
if ($ans eq "CMD_VIEW_CHANGES") {
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
}
$q->{selected} = ($arg+1) % @conflicts;
} until $ans =~ /^CMD_CONTINUE/;
return;
}
sub usage {
if ( $help eq "push" ) {
print STDERR $usage . $usage_push ."\n";
} elsif ( $help eq "pull" ) {
print STDERR $usage . $usage_pull ."\n";
} elsif ( $help eq "sync" ) {
print STDERR $usage . $usage_sync ."\n";
} elsif ( $help eq "getconfig" ) {
print STDERR $usage . $usage_getconfig ."\n";
} elsif ( $help eq "setconfig" ) {
print STDERR $usage . $usage_setconfig ."\n";
} elsif ( $help eq "status" ) {
print STDERR $usage . $usage_stat ."\n";
} elsif ( $help eq "search" ) {
print STDERR $usage . $usage_search ."\n";
} else {
open(PAGER, "| less") or die "Can't open pager";
print PAGER $usage .
$usage_search .
$usage_push .
$usage_pull .
$usage_sync .
$usage_stat .
$usage_setconfig .
$usage_getconfig .
$usage_bottom . "\n";
close PAGER;
}
}
#
# --getconfig helper function
#
sub config {
my $configstr = gettext("Current config\n");
my $config = get_repo_config();
$configstr .= "\turl:\t\t$config->{url}\n";
$configstr .= "\tdistro:\t\t$config->{distro}\n";
$configstr .= "\tenabled:\t$config->{enabled}\n";
$configstr .= "\temail:\t\t$config->{email}\n";
$configstr .= "\tusername:\t$config->{user}\n";
$configstr .= "\tpassword:\t$config->{password}\n";
$configstr .= "\tupload:\t\t$config->{upload}\n";
print STDERR $configstr . "\n";
}
#
# helper function to push profiles to the repository
# used by --push and --sync options
#
sub push_profiles($$$) {
my ( $p_ref, $changelog, $confirm ) = @_;
my ( $conflicts, $remote_profiles, $local_profiles, @overrides );
my @profiles = @$p_ref;
my $conflict_msg =
" The following profile(s) selected for upload conflicts with a profile already
stored in the repository for your account. Please choose whether to keep the
current version or overwrite it.\n";
$all = 0;
readprofiles();
my ($status, $result) = fetch_profiles_by_user( $config->{url},
$config->{distro},
$config->{user}
);
if ( $status ) {
$remote_profiles = $result;
} else {
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
$result);
exit;
}
$all = 1 if ( grep(/^all$/, @profiles) );
if ( $all ) {
$local_profiles = serialize_local_profiles( \%sd );
} else {
my $local_sd = {};
for my $p ( @profiles ) {
if ( !$sd{$p} ) {
print STDERR
sprintf(gettext("Profile for [%s] does not exist\n"), $p);
exit;
}
$local_sd->{$p} = $sd{$p};
}
$local_profiles = serialize_local_profiles( $local_sd );
}
$conflicts = find_profile_conflicts($remote_profiles, $local_profiles);
if ( keys %$conflicts ) {
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
}
if ( $local_profiles ) {
my @uploads;
for my $p ( keys %$local_profiles ) {
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
print STDERR gettext("Uploading ") . $p . "... ";
my ($status,$result) = upload_profile( $config->{url},
$config->{user},
$config->{password},
$config->{distro},
$p,
$local_profiles->{$p},
$changelog
);
print STDERR gettext("done") . "\n";
}
if ( $status ) {
push @uploads, $p;
} else {
print STDERR gettext("Error uploading") . "$p: $result\n";
}
}
if ( @uploads ) {
#
# Currently the upload API with the repository returns the
# the current users profile set before the update so we have
# to refetch to obtain the metadata to update the local profiles
#
my $repo_p = [];
print STDERR gettext("Updating local profile metedata....\n");
my ($status,$result) = fetch_profiles_by_user( $config->{url},
$config->{distro},
$config->{user} );
if ( $status ) {
for my $p ( @uploads ) {
push( @$repo_p, [$p, $result->{$p}] ) if ( $result->{$p} );
}
activate_repo_profiles( $config->{url}, $repo_p, 0 );
print STDERR gettext(" done\n");
} else {
print STDERR gettext(
"Failed to retrieve updated profiles from the repository. Error: "
) . $result . "\n";
}
}
}
}
#
# Helper function for pulling profiles from the repository
# used by --pull and --sync options
#
sub pull_profiles($$$$) {
my ( $p_ref, $mode, $confirm, $opts ) = @_;
my @profiles = @$p_ref;
my ( $conflicts, $commit_list, $remote_profiles,
$local_profiles, @overrides );
my $conflict_msg =
" The following profiles selected for download conflict with profiles
already deployed on the system. Please choose whether to keep the local
version or overwrite with the version from the repository\n";
readprofiles();
if ( $opts->{id} ) {
my ($status,$newp) = fetch_profile_by_id( $config->{url}, $opts->{id} );
if ( ! $status ) {
print STDERR gettext(
sprintf("Error occured during operation\n\t[%s]\n",
$newp
)
);
exit 1;
} else {
$remote_profiles = { $newp->{name} => $newp->{profile} };
}
} elsif ( @profiles && $opts->{author} ) {
$remote_profiles = {};
for my $p ( @profiles ) {
my ($status,$profiles) =
fetch_profiles_by_name_and_user( $config->{url},
$config->{distro},
$p,
$opts->{author} );
if ( ! $status ) {
print STDERR gettext(sprintf(
"Error occured during operation\n\t[%s]\n",
$profiles
)
);
exit 1;
} else {
$remote_profiles->{$p} = $profiles->{$p};
}
}
} elsif ( $opts->{author} ) {
my ($status,$profiles) = fetch_profiles_by_user( $config->{url},
$config->{distro},
$opts->{author} );
if ( ! $status ) {
print STDERR gettext(sprintf(
"Error occured during operation\n\t[%s]\n",
$profiles
)
);
exit 1;
} else {
$remote_profiles = $profiles;
}
}
$local_profiles = serialize_local_profiles( \%sd );
$conflicts = find_profile_conflicts( $remote_profiles, $local_profiles );
if ( keys %$conflicts ) {
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
}
for my $p ( keys %$remote_profiles ) {
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
$remote_profiles->{$p}->{username} = $opts->{author};
push @$commit_list, [$p, $remote_profiles->{$p}];
}
}
if ( $commit_list and @$commit_list ) {
activate_repo_profiles( $config->{url}, $commit_list, $mode );
system("rcapparmor reload");
} else {
UI_Info(gettext("No changes to make"));
}
}
sub UI_status {
my ($synched, $unsynched, $local) = @_;
my $url = $config->{url};
my $synched_text = gettext("Synchronized repository profiles:\t\t") .
keys %$synched;
my $unsynched_text = gettext("Unsynchronized repository profiles:\t") .
keys %$unsynched;
my $local_text = gettext("Local only profiles :\t\t\t") . keys %$local;
my $options = [ $synched_text, $unsynched_text, $local_text ];
my $title = gettext("Profile Status");
my $explanation = gettext(
" This is the current status of active profiles on the system.
To view the profiles or unsyncronized changes select VIEW\n"
);
my $q = {};
$q->{title} = $title;
$q->{headers} = [ "Repository", $url, ];
$q->{explanation} = $explanation;
$q->{functions} = [ "CMD_VIEW", "CMD_FINISHED", ];
$q->{default} = "CMD_FINISHED";
$q->{options} = $options;
$q->{selected} = 0;
my ($ans, $arg);
do {
($ans, $arg) = UI_PromptUser($q);
if ($ans eq "CMD_VIEW") {
if ( $arg == 0 ) {
UI_display_profiles(
gettext("Profiles stored in the repository"),
$synched
);
} elsif ( $arg == 1 ) {
UI_display_profile_conflicts(
gettext("Unsyncronised profile changes"),
$unsynched
);
} elsif ( $arg == 2 ) {
UI_display_profiles(
gettext("Profiles stored in the repository"),
$local
);
}
}
} until $ans =~ /^CMD_FINSHED/;
}

218
deprecated/utils/aa-status Normal file
View File

@@ -0,0 +1,218 @@
#!/usr/bin/perl -w
# ------------------------------------------------------------------
#
# Copyright (C) 2005-2006 Novell/SUSE
#
# 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.
#
# ------------------------------------------------------------------
use strict;
use Getopt::Long;
use Cwd 'abs_path';
my $confdir = "/etc/apparmor";
my $sd_mountpoint;
my $check_enabled = 0;
my $count_enforced = 0;
my $count_profiled = 0;
my $count_complain = 0;
my $verbose = 0;
my $help;
GetOptions(
'complaining' => \$count_complain,
'enabled' => \$check_enabled,
'enforced' => \$count_enforced,
'profiled' => \$count_profiled,
'verbose|v' => \$verbose,
'help|h' => \$help,
) or usage();
sub usage {
print "Usage: $0 [OPTIONS]\n";
print "Displays various information about the currently loaded AppArmor policy.\n";
print "OPTIONS (one only):\n";
print " --enabled returns error code if subdomain not enabled\n";
print " --profiled prints the number of loaded policies\n";
print " --enforced prints the number of loaded enforcing policies\n";
print " --complaining prints the number of loaded non-enforcing policies\n";
print " --verbose (default) displays multiple data points about loaded policy set\n";
print " --help this message\n";
exit;
}
$verbose = 1 if ($count_complain + $check_enabled + $count_enforced + $count_profiled == 0);
usage() if $help or ($count_complain + $check_enabled + $count_enforced + $count_profiled + $verbose > 1);
sub is_subdomain_loaded() {
return 1 if (-d "/sys/module/apparmor");
if(open(MODULES, "/proc/modules")) {
while(<MODULES>) {
return 1 if m/^(subdomain|apparmor)\s+/;
}
}
return 0;
}
sub find_subdomainfs() {
my $sd_mountpoint;
if(open(MOUNTS, "/proc/mounts")) {
while(<MOUNTS>) {
$sd_mountpoint = "$1/apparmor" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/apparmor";
$sd_mountpoint = "$1/subdomain" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/subdomain";
$sd_mountpoint = $1 if m/^\S+\s+(\S+)\s+subdomainfs\s/ && -e "$1";
}
close(MOUNTS);
}
return $sd_mountpoint;
}
sub get_profiles {
my $mountpoint = shift;
my %profiles = ();
if (open(PROFILES, "$mountpoint/profiles")) {
while(<PROFILES>) {
$profiles{$1} = $2 if m/^([^\(]+)\s+\((\w+)\)$/;
}
close(PROFILES);
}
return (%profiles);
}
sub get_processes {
my %profiles = @_;
my %processes = ();
if (opendir(PROC, "/proc")) {
my $file;
while (defined($file = readdir(PROC))) {
if ($file =~ m/^\d+/) {
if (open(CURRENT, "/proc/$file/attr/current")) {
while (<CURRENT>) {
if (m/^([^\(]+)\s+\((\w+)\)$/) {
$processes{$file}{'profile'} = $1;
$processes{$file}{'mode'} = $2;
} elsif (grep(abs_path("/proc/$file/exe") eq $_ , keys(%profiles))) {
# keep only unconfined processes that have a profile defined
$processes{$file}{'profile'} = abs_path("/proc/$file/exe");
$processes{$file}{'mode'} = 'unconfined';
}
}
close(CURRENT);
}
}
}
closedir(PROC);
}
return (%processes);
}
my $is_loaded = is_subdomain_loaded();
if (!$is_loaded) {
print STDERR "apparmor module is not loaded.\n" if $verbose;
exit 1;
}
print "apparmor module is loaded.\n" if $verbose;
$sd_mountpoint = find_subdomainfs();
if (!$sd_mountpoint) {
print STDERR "apparmor filesystem is not mounted.\n" if $verbose;
exit 3;
}
if (! -r "$sd_mountpoint/profiles") {
print STDERR "You do not have enough privilege to read the profile set.\n" if $verbose;
exit 4;
}
#print "subdomainfs is at $sd_mountpoint.\n" if $verbose;
# processes is a hash table :
# * keys : processes pid
# * values : hash containing information about the running process:
# * 'profile' : name of the profile applied to the running process
# * 'mode' : mode of the profile applied to the running process
my %processes = ();
my %enforced_processes = ();
my %complain_processes = ();
my %unconfined_processes = ();
# profiles is a hash table :
# * keys : profile name
# * value : profile mode
my %profiles;
my @enforced_profiles = ();
my @complain_profiles = ();
%profiles = get_profiles($sd_mountpoint);
@enforced_profiles = grep { $profiles{$_} eq 'enforce' } keys %profiles;
@complain_profiles = grep { $profiles{$_} eq 'complain' } keys %profiles;
# we consider the case where no profiles are loaded to be "disabled" as well
my $rc = (keys(%profiles) == 0) ? 2 : 0;
if ($check_enabled) {
exit $rc;
}
if ($count_profiled) {
print scalar(keys(%profiles)). "\n";
exit $rc;
}
if ($count_enforced) {
print $#enforced_profiles + 1 . "\n";
exit $rc;
}
if ($count_complain) {
print $#complain_profiles + 1 . "\n";
exit $rc;
}
if ($verbose) {
print keys(%profiles) . " profiles are loaded.\n";
print $#enforced_profiles + 1 . " profiles are in enforce mode.\n";
for (sort(@enforced_profiles)) {
print " " . $_ . "\n";
}
print $#complain_profiles + 1 . " profiles are in complain mode.\n";
for (sort(@complain_profiles)) {
print " " . $_ . "\n";
}
}
%processes = get_processes(%profiles);
if ($verbose) {
for (keys(%processes)) {
$enforced_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'enforce';
$complain_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'complain';
# some early code uses unconfined instead of unconfined.
$unconfined_processes{$_} = $processes{$_} if $processes{$_}{'mode'} =~ /uncon(fi|strai)ned/;
}
print keys(%processes) . " processes have profiles defined.\n";
print keys(%enforced_processes) . " processes are in enforce mode :\n";
for (sort { $enforced_processes{$a}{'profile'} cmp $enforced_processes{$b}{'profile'} } keys(%enforced_processes)) {
print " " . $enforced_processes{$_}{'profile'} . " ($_) \n";
}
print keys(%complain_processes) . " processes are in complain mode.\n";
for (sort { $complain_processes{$a}{'profile'} cmp $complain_processes{$b}{'profile'} } keys(%complain_processes)) {
print " " . $complain_processes{$_}{'profile'} . " ($_) \n";
}
print keys(%unconfined_processes) . " processes are unconfined but have a profile defined.\n";
for (sort { $unconfined_processes{$a}{'profile'} cmp $unconfined_processes{$b}{'profile'} } keys(%unconfined_processes)) {
print " " . $unconfined_processes{$_}{'profile'} . " ($_) \n";
}
}
exit $rc;

113
deprecated/utils/aa-unconfined Executable file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/perl -w
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
#
# To contact Novell about this file by physical or electronic mail,
# you may find current contact information at www.novell.com.
# ----------------------------------------------------------------------
#
# unconfined -
# audit local system for processes listening on network connections
# that are not currently running with a profile.
use strict;
use Getopt::Long;
use Immunix::AppArmor;
use Locale::gettext;
use POSIX;
setlocale(LC_MESSAGES, "");
textdomain("apparmor-utils");
# options variables
my $paranoid = '';
my $help = '';
GetOptions(
'paranoid' => \$paranoid,
'help|h' => \$help,
);
# tell 'em how to use it...
&usage && exit if $help;
sub usage {
printf(gettext("Usage: %s [ --paranoid ]\n"), $0);
exit 0;
}
my $subdomainfs = check_for_subdomain();
die gettext("AppArmor does not appear to be started. Please enable AppArmor and try again.") . "\n"
unless $subdomainfs;
my @pids;
if ($paranoid) {
opendir(PROC, "/proc") or die gettext("Can't read /proc\n");
@pids = grep { /^\d+$/ } readdir(PROC);
closedir(PROC);
} else {
if (open(NETSTAT, "LANG=C /bin/netstat -nlp |")) {
while (<NETSTAT>) {
chomp;
push @pids, $5
if /^(tcp|udp)\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\s+)\s+(\d+)\/(\S+)/;
}
close(NETSTAT);
}
}
for my $pid (sort { $a <=> $b } @pids) {
my $prog = readlink "/proc/$pid/exe" or next;
my $attr;
if (open(CURRENT, "/proc/$pid/attr/current")) {
while (<CURRENT>) {
chomp;
$attr = $_ if (/^\// || /^null/);
}
close(CURRENT);
}
my $cmdline = `cat /proc/$pid/cmdline`;
my $pname = (split(/\0/, $cmdline))[0];
if ($pname =~ /\// && !($pname eq $prog)) {
$pname = "($pname) ";
} else {
$pname = "";
}
if (not $attr) {
if ($prog =~ m/^(\/usr\/bin\/python|\/usr\/bin\/perl|\/bin\/bash)$/) {
#my $scriptname = (split(/\0/, `cat /proc/$pid/cmdline`))[1];
$cmdline =~ s/\0/ /g;
$cmdline =~ s/\s+$//;
chomp $cmdline;
print "$pid $prog ($cmdline) " . gettext("not confined\n");
} else {
print "$pid $prog $pname" . gettext("not confined\n");
}
} else {
if ($prog =~ m/^(\/usr\/bin\/python|\/usr\/bin\/perl|\/bin\/bash)$/) {
#my $scriptname = (split(/\0/, `cat /proc/$pid/cmdline`))[1];
$cmdline =~ s/\0/ /g;
$cmdline =~ s/\s+$//;
chomp $cmdline;
print "$pid $prog ($cmdline) " . gettext("confined by") . " '$attr'\n";
} else {
print "$pid $prog $pname" . gettext("confined by") . " '$attr'\n";
}
}
}

View File

@@ -0,0 +1,135 @@
#! /usr/bin/perl -w
# Very simple script to try converting AppArmor profiles to the new
# profile syntax as of April 2007.
#
# Copyright (C) 2007 Andreas Gruenbacher <agruen@suse.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.
#
# 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.
use FileHandle;
use File::Temp;
use Getopt::Std;
use strict;
sub match($) {
my ($str) = @_;
my @fields;
@fields = ($str =~ /^(\s*)([@\/]\S*)(\s.*,)$/);
if (!@fields) {
@fields = ($str =~ /^(\s*")((?:[^"]|\\")*)("\s.*,)$/);
}
return @fields;
}
sub alterations($) {
my ($str) = @_;
if ($str =~ /^([^{]*){([^}]*,[^}]*)}(.*)$/) {
my @strs = map { "$1$_$3" } split(/,/, $2);
return map { alterations($_) } @strs;
} else {
return ($str);
}
}
my %known_dirs;
sub remember_pathname($) {
my ($str) = @_;
my $pathname;
for (split /(\/)/, $str) {
if ($_ eq '/' && $pathname ne '') {
#print "<<>> $pathname\n";
$known_dirs{$pathname} = 1;
}
$pathname .= $_;
}
}
sub add_slash($$) {
my ($str, $perms) = @_;
return exists $known_dirs{$str} || -d $str;
}
sub never_add_slash($$) {
my ($str, $perms) = @_;
return $perms =~ /[lmx]/ || $str =~ /\.(so|cf|db|conf|config|log|pid|so\*)$/ ||
$str =~ /(\*\*|\/)$/ || (-e $str && ! -d $str);
}
our($opt_i);
getopts('i');
foreach my $filename (@ARGV) {
my $fh_in;
$fh_in = new FileHandle("< $filename")
or die "$filename: $!\n";
while (<$fh_in>) {
if (my @fields = match($_)) {
for my $x (alterations($fields[1])) {
remember_pathname($x);
}
}
}
}
if (@ARGV == 0) {
print "Usage: $0 profile ...\n";
print "Tries to convert the profile to the new profile syntax, and\n" .
"prints the result to standard output. The result may need" .
"further review.\n";
exit 0;
}
foreach my $filename (@ARGV) {
my ($fh_in, $fh_out, $tmpname);
$fh_in = new FileHandle("< $filename")
or die "$filename: $!\n";
if ($opt_i) {
($fh_out, $tmpname) = mkstemp("$filename.XXXXXX")
or die "$!\n";
*STDOUT = $fh_out;
}
while (<$fh_in>) {
if (my @fields = match($_)) {
for my $x (alterations($fields[1])) {
if (never_add_slash($x, $fields[2])) {
print $_;
} elsif (add_slash($x, $fields[2])) {
print "$fields[0]$x/$fields[2] # (dir)\n";
} else {
print "$fields[0]$x/$fields[2] # (maybe-dir)\n";
print $_;
}
}
} else {
print $_;
}
}
if ($opt_i) {
rename $tmpname, $filename
or die "$filename: $!\n";
}
}
# vim: smartindent softtabstop=4 shiftwidth=4

View File

@@ -0,0 +1,201 @@
#!/usr/bin/perl -wi
# automatically repair apparmor profiles that have had their supporting
# infrastructure refactored out from underneath them
# note -i in shebang line -- this program will modify in-place
# profiles or #include chunks specified on the command line without
# backups. Please make some yourself and inspect the changes made by
# this tool to ensure they look correct.
# It'll try to fix up #include files (supplied by SUSE/Immunix) that have
# moved; it will also inspect many #include files that exist solely
# for netdomain rule separation, and either remove the #include line
# from profiles/includes or suck in the contents of the specific file,
# depending if there was any non-netdomain content.
# If you haven't modified any of the files listed in the @useless array,
# you probably don't have to concern yourself with the complicated part
# of the previous paragraph. If you did modify any of those files, this
# tool will inspect those for changes, try to update any lines in those
# files for correctness, and insert those lines directly into the
# referencing profiles.
our %count_cache;
# count the number of 'interesting' lines in the file
sub numlines ($) {
my $name = $_[0];
return $count_cache{$name} if $count_cache{$name};
open FH, $name or return 1; # can't tell -> not empty
my $linecount=0;
while(<FH>) {
if (m/^[^#]*#include/) {
$linecount++;
} elsif (m/^\s*#/) {
# just a comment, skip it
} elsif (m/\s*tcp_/) {
# netdomain rules are unenforced, skip it
} elsif (m/\s*udp_/) {
# netdomain rules are unenforced, skip it
} elsif (m/\S+/) {
$linecount++;
}
}
close FH;
$count_cache{$name} = $linecount;
return $linecount;
}
# given a single line from a profile, perform some search/replace
# operations to reflect new locations for old files.
#
# change #include lines that reference files in the @useless array:
# don't print the #include any more, and either suck in the contents of
# the referenced file (calling itself recursively to fix up _those_
# files) or just leave well enough alone, if the file had no
# 'interesting' lines as defined above.
%transforms = (
# renamed around SuSE 9.3
"abstractions/kde3" => "abstractions/kde",
"abstractions/user-GTK" => "abstractions/gnome",
"abstractions/user-Xauthority" => "abstractions/X",
# user-custom -> program-chunks around SHASS 1.1, but these changed dirs
"user-custom/fonts" => "abstractions/fonts",
"user-custom/kde3" => "abstractions/kde",
"user-custom/user-GTK" => "abstractions/gnome",
"user-custom/user-mail" => "abstractions/user-mail",
"user-custom/user-manpages" => "abstractions/user-manpages",
"user-custom/user-Xauthority" => "abstractions/X",
"user-custom/user-tmp" => "abstractions/user-tmp",
# try to forget the -files
"program-chunks/base-files" => "abstractions/base",
"program-chunks/nameservice-files" => "abstractions/nameservice",
"immunix-standard/base-files" => "abstractions/base",
"immunix-standard/nameservice-files" => "abstractions/nameservice",
# immunix-standard -> program-chunks
"immunix-standard/postfix-bounce" => "program-chunks/postfix-bounce",
"immunix-standard/postfix-cleanup" => "program-chunks/postfix-cleanup",
"immunix-standard/postfix-common" => "program-chunks/postfix-common",
"immunix-standard/postfix-flush" => "program-chunks/postfix-flush",
"immunix-standard/postfix-local" => "program-chunks/postfix-local",
"immunix-standard/postfix-master" => "program-chunks/postfix-master",
"immunix-standard/postfix-nqmgr" => "program-chunks/postfix-nqmgr",
"immunix-standard/postfix-pickup" => "program-chunks/postfix-pickup",
"immunix-standard/postfix-proxymap" => "program-chunks/postfix-proxymap",
"immunix-standard/postfix-qmgr" => "program-chunks/postfix-qmgr",
"immunix-standard/postfix-showq" => "program-chunks/postfix-showq",
"immunix-standard/postfix-smtp" => "program-chunks/postfix-smtp",
"immunix-standard/postfix-smtpd" => "program-chunks/postfix-smtpd",
"immunix-standard/postfix-trivial-rewrite" => "program-chunks/postfix-trivial-rewrite",
"immunix-standard/apache-default-uri" => "program-chunks/apache-default-uri",
"immunix-standard/at" => "program-chunks/at",
);
# chunks that immunix tools never populated -- lets remove the ones that
# don't have any useful information
my @useless = qw{
program-chunks/base-nd
program-chunks/portmap-nd
program-chunks/postfix-local-nd
program-chunks/postfix-master-nd
program-chunks/postfix-proxymap-nd
program-chunks/postfix-smtpd-nd
program-chunks/postfix-smtp-nd
user-custom/base-nd
user-custom/portmap-nd
user-custom/postfix-local-nd
user-custom/postfix-master-nd
user-custom/postfix-proxymap-nd
user-custom/postfix-smtpd-nd
user-custom/postfix-smtp-nd
immunix-standard/base-nd
immunix-standard/portmap-nd
immunix-standard/postfix-local-nd
immunix-standard/postfix-master-nd
immunix-standard/postfix-proxymap-nd
immunix-standard/postfix-smtpd-nd
immunix-standard/postfix-smtp-nd
program-chunks/at
program-chunks/fam
program-chunks/httpd
program-chunks/identd
program-chunks/imapd
program-chunks/ipop2d
program-chunks/ipop3d
program-chunks/lpd
program-chunks/mutt
program-chunks/named
program-chunks/nmbd
program-chunks/ntalkd
program-chunks/ntpd
program-chunks/postgres
program-chunks/rpc.lockd
program-chunks/rpc.nfsd
program-chunks/rpc.statd
program-chunks/samba
program-chunks/sendmail.sendmail
program-chunks/shells
program-chunks/slocate
program-chunks/snmpd
program-chunks/spamc
program-chunks/sshd
program-chunks/swat
program-chunks/syslogd
program-chunks/talk
program-chunks/xfs
};
# create an alternation to speed up the regexp below
my $useless = join('|', @useless);
sub fixup ($) {
$line = $_[0];
$line =~ s/#include\s+<([^>]+)>/$i = (exists $transforms{$1}) ? $transforms{$1} : "$1"; "#include <$i>"/e;
if ($line =~ m/\s*#include\s+<($useless)>/) {
my $file = $1;
if (numlines("/etc/subdomain.d/$file") > 0) {
my $succ = open INC, "/etc/subdomain.d/$file";
if (not $succ) {
print STDERR "Error opening /etc/subdomain.d/$file\n";
} else {
while(my $included_line = <INC>) {
print fixup_loop($included_line);
}
close INC;
}
}
$line = ""; # this line has been handled by the file
}
return $line;
}
# call fixup on a single entry repeatedly -- this way, we can encode
# 'small' changes in the fixup routine when they are made, rather than
# encoding all possible starting points and which specific end point
# they should go to.
sub fixup_loop ($) {
my $line = $_[0];
my $saved;
do {
$saved = $line;
$line = fixup($saved);
} until ($line eq $saved);
return $line;
}
# main entry point; fix each line in every file in argv.
while(<>) {
print fixup_loop($_);
}

View File

@@ -1,36 +0,0 @@
# ----------------------------------------------------------------------
# Copyright (c) 2016 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# 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.
# ----------------------------------------------------------------------
NAME = documentation
all:
COMMONDIR=../common/
include $(COMMONDIR)/Make.rules
all: docs
SOURCES:= $(wildcard *.odt)
DOCS:=$(SOURCES:.odt=.pdf)
.PHONY: docs
docs: $(DOCS)
%.pdf: %.odt
unoconv -v -f pdf --output "$@" "$<"
.PHONY: clean
ifndef VERBOSE
.SILENT: clean
endif
clean:
rm -f *.pdf

Binary file not shown.

Binary file not shown.

View File

@@ -1,25 +0,0 @@
The apparmor logo (logo-default-red.svg) was created by Noah Davis and
released under the LGPL (licence included below).
Logo variants and uses:
logo-default-red.svg - default logo and coloration used for the apparmor
project. Created for larger (64x64) uses.
Not optimized for small 16x16 tiles.
License
* Copyright (c) 2018 Noah Davis <noahadvs@gmail.com>
*
* The appaprmor logo is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This logo file 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg height="64" width="64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="55" x2="55" xlink:href="#j" y1="54" y2="9"/><linearGradient id="b"><stop offset="0" stop-color="#bf4231"/><stop offset="1" stop-color="#e05e4c"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="32" x2="32" y1="58" y2="6"><stop offset="0" stop-color="#173f4f"/><stop offset="1" stop-color="#2f5361"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="55" x2="55" xlink:href="#b" y1="54" y2="9"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="20" x2="45" xlink:href="#k" y1="22" y2="47"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="37" x2="37" y1="46" y2="38"><stop offset="0" stop-color="#be4434"/><stop offset=".25" stop-color="#c44837"/><stop offset="1" stop-color="#cb4c3b"/></linearGradient><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="26" x2="50" xlink:href="#k" y1="16" y2="40"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="40" x2="47" xlink:href="#k" y1="38" y2="45"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="43" x2="46" xlink:href="#k" y1="44" y2="47"/><linearGradient id="j"><stop offset="0" stop-color="#eff0f1"/><stop offset="1" stop-color="#fcfcfc"/></linearGradient><linearGradient id="k"><stop offset="0" stop-color="#292c2f"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="l" gradientUnits="userSpaceOnUse" x1="32" x2="32" xlink:href="#j" y1="54" y2="9"/><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="32" x2="32" xlink:href="#b" y1="54" y2="9"/><path d="m32 6c-6.33333 3.35447-12.66667 4.72491-19 6v25.001953c0 7 10.26331 16.561337 19 20.998047 8.73669-4.43671 19-13.998047 19-20.998047v-25.001953c-6.33333-1.27509-12.66667-2.64553-19-6z" fill="url(#c)" stroke-linecap="square" stroke-width="2"/><path d="m13 36.001953v1c0 7 10.26331 16.561337 19 20.998047 8.73669-4.43671 19-13.998047 19-20.998047v-1c0 7-10.26331 16.561337-19 20.998047-8.73669-4.43671-19-13.998047-19-20.998047z" fill="#292c2f" opacity=".2" stroke-linecap="square" stroke-width="2"/><path d="m48 14-26.304688 32.304688 11.208985 11.208984c8.525508-4.614773 18.095703-13.751033 18.095703-20.511719v-20.001953z" fill="url(#i)" opacity=".2"/><path d="m40.824219 12.349609-17.617188 35.238282c2.735569 2.548653 5.806349 4.895376 8.792969 6.412109 7.392765-3.754157 16-12.076982 16-18v-22c-2.403402-.483885-4.789398-1.006952-7.175781-1.650391z" fill="url(#d)"/><path d="m32 9c-5.358808 2.838395-10.64102 3.921074-16 5v22c0 3.530034 3.17163 7.828219 7.207031 11.587891l17.617188-35.238282c-2.934573-.791246-5.868718-1.784199-8.824219-3.349609z" fill="url(#a)"/><path d="m24 14-8 16 20.935547 20.935547c1.522034-1.10756 3.001377-2.336903 4.361328-3.638672l-1.296875-1.296875-7-14z" fill="url(#e)" opacity=".2"/><path d="m28 14 12 32 8-16h-4z" fill="url(#g)" opacity=".2"/><g stroke-width="1.857143"><path d="m24 14 16 32 8-16h-4l-1 2h-6l-9-18zm14 20h4l-2 4z" fill="url(#l)"/><path d="m24 14-8 16h4l1-2h6l8.5 17.000001h4zm0 8 2 4h-4z" fill="url(#m)"/><path d="m32 38 4 8h4l-4-8z" fill="url(#f)"/></g><path d="m48 30-8 16 3.617188 3.617188c4.013144-3.887728 7.018045-8.222958 7.351562-11.9375.019301-.229864.03125-.456776.03125-.677735v-4.001953z" fill="url(#h)" opacity=".2"/></svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -1,118 +0,0 @@
From 24b6ac149a57c2d3d5a9920e64d914e8ff00d346 Mon Sep 17 00:00:00 2001
From: Vegard Nossum <vegard.nossum@oracle.com>
Date: Thu, 7 Jul 2016 13:41:11 -0700
Subject: [PATCH 01/27] apparmor: fix oops, validate buffer size in
apparmor_setprocattr()
When proc_pid_attr_write() was changed to use memdup_user apparmor's
(interface violating) assumption that the setprocattr buffer was always
a single page was violated.
The size test is not strictly speaking needed as proc_pid_attr_write()
will reject anything larger, but for the sake of robustness we can keep
it in.
SMACK and SELinux look safe to me, but somebody else should probably
have a look just in case.
Based on original patch from Vegard Nossum <vegard.nossum@oracle.com>
modified for the case that apparmor provides null termination.
Fixes: bb646cdb12e75d82258c2f2e7746d5952d3e321a
Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: John Johansen <john.johansen@canonical.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Cc: stable@kernel.org
Signed-off-by: John Johansen <john.johansen@canonical.com>
Reviewed-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
---
security/apparmor/lsm.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index dec607c..5ee8201 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -523,34 +523,34 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
{
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- char *command, *args = value;
+ char *command, *largs = NULL, *args = value;
size_t arg_size;
int error;
if (size == 0)
return -EINVAL;
- /* args points to a PAGE_SIZE buffer, AppArmor requires that
- * the buffer must be null terminated or have size <= PAGE_SIZE -1
- * so that AppArmor can null terminate them
- */
- if (args[size - 1] != '\0') {
- if (size == PAGE_SIZE)
- return -EINVAL;
- args[size] = '\0';
- }
-
/* task can only write its own attributes */
if (current != task)
return -EACCES;
- args = value;
+ /* AppArmor requires that the buffer must be null terminated atm */
+ if (args[size - 1] != '\0') {
+ /* null terminate */
+ largs = args = kmalloc(size + 1, GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+ memcpy(args, value, size);
+ args[size] = '\0';
+ }
+
+ error = -EINVAL;
args = strim(args);
command = strsep(&args, " ");
if (!args)
- return -EINVAL;
+ goto out;
args = skip_spaces(args);
if (!*args)
- return -EINVAL;
+ goto out;
arg_size = size - (args - (char *) value);
if (strcmp(name, "current") == 0) {
@@ -576,10 +576,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
goto fail;
} else
/* only support the "current" and "exec" process attributes */
- return -EINVAL;
+ goto fail;
if (!error)
error = size;
+out:
+ kfree(largs);
return error;
fail:
@@ -588,9 +590,9 @@ fail:
aad.profile = aa_current_profile();
aad.op = OP_SETPROCATTR;
aad.info = name;
- aad.error = -EINVAL;
+ aad.error = error = -EINVAL;
aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
- return -EINVAL;
+ goto out;
}
static int apparmor_task_setrlimit(struct task_struct *task,
--
2.7.4

View File

@@ -1,33 +0,0 @@
From 444bc4f95ec283cd0fb9777f4890bd9bc307809d Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 11 Apr 2016 16:55:10 -0700
Subject: [PATCH 02/27] apparmor: fix refcount bug in profile replacement
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 705c287..222052f 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1189,12 +1189,12 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
aa_get_profile(newest);
aa_put_profile(parent);
rcu_assign_pointer(ent->new->parent, newest);
- } else
- aa_put_profile(newest);
+ }
/* aafs interface uses replacedby */
rcu_assign_pointer(ent->new->replacedby->profile,
aa_get_profile(ent->new));
__list_add_profile(&parent->base.profiles, ent->new);
+ aa_put_profile(newest);
} else {
/* aafs interface uses replacedby */
rcu_assign_pointer(ent->new->replacedby->profile,
--
2.7.4

View File

@@ -1,38 +0,0 @@
From 1224a06778b89dcbf0ca85bd961c2fcdd8765a69 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 11 Apr 2016 16:57:19 -0700
Subject: [PATCH 03/27] apparmor: fix replacement bug that adds new child to
old parent
When set atomic replacement is used and the parent is updated before the
child, and the child did not exist in the old parent so there is no
direct replacement then the new child is incorrectly added to the old
parent. This results in the new parent not having the child(ren) that
it should and the old parent when being destroyed asserting the
following error.
AppArmor: policy_destroy: internal error, policy '<profile/name>' still
contains profiles
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 222052f..c92a9f6 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1193,7 +1193,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
/* aafs interface uses replacedby */
rcu_assign_pointer(ent->new->replacedby->profile,
aa_get_profile(ent->new));
- __list_add_profile(&parent->base.profiles, ent->new);
+ __list_add_profile(&newest->base.profiles, ent->new);
aa_put_profile(newest);
} else {
/* aafs interface uses replacedby */
--
2.7.4

View File

@@ -1,87 +0,0 @@
From 15d921647676fdc2c3ee1cf9aa8f578b1012ecff Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Sun, 8 Jun 2014 11:20:54 -0700
Subject: [PATCH 04/27] apparmor: fix uninitialized lsm_audit member
BugLink: http://bugs.launchpad.net/bugs/1268727
The task field in the lsm_audit struct needs to be initialized if
a change_hat fails, otherwise the following oops will occur
BUG: unable to handle kernel paging request at 0000002fbead7d08
IP: [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
PGD 1e3f35067 PUD 0
Oops: 0002 [#1] SMP
Modules linked in: pppox crc_ccitt p8023 p8022 psnap llc ax25 btrfs raid6_pq xor xfs libcrc32c dm_multipath scsi_dh kvm_amd dcdbas kvm microcode amd64_edac_mod joydev edac_core psmouse edac_mce_amd serio_raw k10temp sp5100_tco i2c_piix4 ipmi_si ipmi_msghandler acpi_power_meter mac_hid lp parport hid_generic usbhid hid pata_acpi mpt2sas ahci raid_class pata_atiixp bnx2 libahci scsi_transport_sas [last unloaded: tipc]
CPU: 2 PID: 699 Comm: changehat_twice Tainted: GF O 3.13.0-7-generic #25-Ubuntu
Hardware name: Dell Inc. PowerEdge R415/08WNM9, BIOS 1.8.6 12/06/2011
task: ffff8802135c6000 ti: ffff880212986000 task.ti: ffff880212986000
RIP: 0010:[<ffffffff8171153e>] [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
RSP: 0018:ffff880212987b68 EFLAGS: 00010006
RAX: 0000000000020000 RBX: 0000002fbead7500 RCX: 0000000000000000
RDX: 0000000000000292 RSI: ffff880212987ba8 RDI: 0000002fbead7d08
RBP: ffff880212987b68 R08: 0000000000000246 R09: ffff880216e572a0
R10: ffffffff815fd677 R11: ffffea0008469580 R12: ffffffff8130966f
R13: ffff880212987ba8 R14: 0000002fbead7d08 R15: ffff8800d8c6b830
FS: 00002b5e6c84e7c0(0000) GS:ffff880216e40000(0000) knlGS:0000000055731700
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000002fbead7d08 CR3: 000000021270f000 CR4: 00000000000006e0
Stack:
ffff880212987b98 ffffffff81075f17 ffffffff8130966f 0000000000000009
0000000000000000 0000000000000000 ffff880212987bd0 ffffffff81075f7c
0000000000000292 ffff880212987c08 ffff8800d8c6b800 0000000000000026
Call Trace:
[<ffffffff81075f17>] __lock_task_sighand+0x47/0x80
[<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
[<ffffffff81075f7c>] do_send_sig_info+0x2c/0x80
[<ffffffff81075fee>] send_sig_info+0x1e/0x30
[<ffffffff8130242d>] aa_audit+0x13d/0x190
[<ffffffff8130c1dc>] aa_audit_file+0xbc/0x130
[<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
[<ffffffff81304cc2>] aa_change_hat+0x202/0x530
[<ffffffff81308fc6>] aa_setprocattr_changehat+0x116/0x1d0
[<ffffffff8130a11d>] apparmor_setprocattr+0x25d/0x300
[<ffffffff812cee56>] security_setprocattr+0x16/0x20
[<ffffffff8121fc87>] proc_pid_attr_write+0x107/0x130
[<ffffffff811b7604>] vfs_write+0xb4/0x1f0
[<ffffffff811b8039>] SyS_write+0x49/0xa0
[<ffffffff8171a1bf>] tracesys+0xe1/0xe6
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/audit.c | 3 ++-
security/apparmor/file.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 89c7865..3a7f1da 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -200,7 +200,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
if (sa->aad->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL,
- sa->u.tsk ? sa->u.tsk : current);
+ sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
+ sa->u.tsk : current);
if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(sa->aad->error);
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 913f377..43d6ae7 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -110,7 +110,8 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
- sa.type = LSM_AUDIT_DATA_NONE;
+ sa.type = LSM_AUDIT_DATA_TASK;
+ sa.u.tsk = NULL;
sa.aad = &aad;
aad.op = op,
aad.fs.request = request;
--
2.7.4

View File

@@ -1,32 +0,0 @@
From c1216728b7d644443eef31e4bd9d01b4a0a51d61 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 25 Jul 2014 04:02:03 -0700
Subject: [PATCH 05/27] apparmor: exec should not be returning ENOENT when it
denies
The current behavior is confusing as it causes exec failures to report
the executable is missing instead of identifying that apparmor
caused the failure.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/domain.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index dc0027b..67a7418 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -433,7 +433,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
new_profile = aa_get_newest_profile(ns->unconfined);
info = "ux fallback";
} else {
- error = -ENOENT;
+ error = -EACCES;
info = "profile not found";
/* remove MAY_EXEC to audit as failure */
perms.allow &= ~MAY_EXEC;
--
2.7.4

View File

@@ -1,28 +0,0 @@
From 2d3389de6c8ab6b3ad2cef4ea460c8fce2a226b9 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 25 Jul 2014 04:01:56 -0700
Subject: [PATCH 06/27] apparmor: fix update the mtime of the profile file on
replacement
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/apparmorfs.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index ad4fa49..45a6199 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -379,6 +379,8 @@ void __aa_fs_profile_migrate_dents(struct aa_profile *old,
for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
new->dents[i] = old->dents[i];
+ if (new->dents[i])
+ new->dents[i]->d_inode->i_mtime = CURRENT_TIME;
old->dents[i] = NULL;
}
}
--
2.7.4

View File

@@ -1,36 +0,0 @@
From 9caa96e30a1b2bb191a29af872285c8d0b078c10 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 25 Jul 2014 04:02:08 -0700
Subject: [PATCH 07/27] apparmor: fix disconnected bind mnts reconnection
Bind mounts can fail to be properly reconnected when PATH_CONNECT is
specified. Ensure that when PATH_CONNECT is specified the path has
a root.
BugLink: http://bugs.launchpad.net/bugs/1319984
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/path.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 71e0e3a..bb2f2c6 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -141,7 +141,10 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
error = -EACCES;
if (*res == '/')
*name = res + 1;
- }
+ } else if (*res != '/')
+ /* CONNECT_PATH with missing root */
+ error = prepend(name, *name - buf, "/", 1);
+
}
out:
--
2.7.4

View File

@@ -1,114 +0,0 @@
From 11702a732e149380e05e2ab8ae1b743ac89f892f Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 25 Jul 2014 04:02:10 -0700
Subject: [PATCH 08/27] apparmor: internal paths should be treated as
disconnected
Internal mounts are not mounted anywhere and as such should be treated
as disconnected paths.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/path.c | 64 +++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index bb2f2c6..596f799 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -25,7 +25,6 @@
#include "include/path.h"
#include "include/policy.h"
-
/* modified from dcache.c */
static int prepend(char **buffer, int buflen, const char *str, int namelen)
{
@@ -39,6 +38,38 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen)
#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
+/* If the path is not connected to the expected root,
+ * check if it is a sysctl and handle specially else remove any
+ * leading / that __d_path may have returned.
+ * Unless
+ * specifically directed to connect the path,
+ * OR
+ * if in a chroot and doing chroot relative paths and the path
+ * resolves to the namespace root (would be connected outside
+ * of chroot) and specifically directed to connect paths to
+ * namespace root.
+ */
+static int disconnect(const struct path *path, char *buf, char **name,
+ int flags)
+{
+ int error = 0;
+
+ if (!(flags & PATH_CONNECT_PATH) &&
+ !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
+ our_mnt(path->mnt))) {
+ /* disconnected path, don't return pathname starting
+ * with '/'
+ */
+ error = -EACCES;
+ if (**name == '/')
+ *name = *name + 1;
+ } else if (**name != '/')
+ /* CONNECT_PATH with missing root */
+ error = prepend(name, *name - buf, "/", 1);
+
+ return error;
+}
+
/**
* d_namespace_path - lookup a name associated with a given path
* @path: path to lookup (NOT NULL)
@@ -74,7 +105,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
* control instead of hard coded /proc
*/
return prepend(name, *name - buf, "/proc", 5);
- }
+ } else
+ return disconnect(path, buf, name, flags);
return 0;
}
@@ -120,32 +152,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
goto out;
}
- /* If the path is not connected to the expected root,
- * check if it is a sysctl and handle specially else remove any
- * leading / that __d_path may have returned.
- * Unless
- * specifically directed to connect the path,
- * OR
- * if in a chroot and doing chroot relative paths and the path
- * resolves to the namespace root (would be connected outside
- * of chroot) and specifically directed to connect paths to
- * namespace root.
- */
- if (!connected) {
- if (!(flags & PATH_CONNECT_PATH) &&
- !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
- our_mnt(path->mnt))) {
- /* disconnected path, don't return pathname starting
- * with '/'
- */
- error = -EACCES;
- if (*res == '/')
- *name = res + 1;
- } else if (*res != '/')
- /* CONNECT_PATH with missing root */
- error = prepend(name, *name - buf, "/", 1);
-
- }
+ if (!connected)
+ error = disconnect(path, buf, name, flags);
out:
return error;
--
2.7.4

View File

@@ -1,29 +0,0 @@
From c70811d9e6234c96d0ef405cd8ad78b70efb8637 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Sat, 16 Apr 2016 13:59:02 -0700
Subject: [PATCH 09/27] apparmor: fix put() parent ref after updating the
active ref
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index c92a9f6..455c9f8 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1187,8 +1187,8 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
/* parent replaced in this atomic set? */
if (newest != parent) {
aa_get_profile(newest);
- aa_put_profile(parent);
rcu_assign_pointer(ent->new->parent, newest);
+ aa_put_profile(parent);
}
/* aafs interface uses replacedby */
rcu_assign_pointer(ent->new->replacedby->profile,
--
2.7.4

View File

@@ -1,87 +0,0 @@
From f671b902943f83f0fbc8c8b7bf8bbfb817d124f1 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Sat, 16 Apr 2016 14:16:50 -0700
Subject: [PATCH 10/27] apparmor: fix log failures for all profiles in a set
currently only the profile that is causing the failure is logged. This
makes it more confusing than necessary about which profiles loaded
and which didn't. So make sure to log success and failure messages for
all profiles in the set being loaded.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 455c9f8..db31bc5 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1067,7 +1067,7 @@ static int __lookup_replace(struct aa_namespace *ns, const char *hname,
*/
ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
{
- const char *ns_name, *name = NULL, *info = NULL;
+ const char *ns_name, *info = NULL;
struct aa_namespace *ns = NULL;
struct aa_load_ent *ent, *tmp;
int op = OP_PROF_REPL;
@@ -1082,18 +1082,15 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
/* released below */
ns = aa_prepare_namespace(ns_name);
if (!ns) {
- info = "failed to prepare namespace";
- error = -ENOMEM;
- name = ns_name;
- goto fail;
+ error = audit_policy(op, GFP_KERNEL, ns_name,
+ "failed to prepare namespace", -ENOMEM);
+ goto free;
}
mutex_lock(&ns->lock);
/* setup parent and ns info */
list_for_each_entry(ent, &lh, list) {
struct aa_policy *policy;
-
- name = ent->new->base.hname;
error = __lookup_replace(ns, ent->new->base.hname, noreplace,
&ent->old, &info);
if (error)
@@ -1121,7 +1118,6 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
if (!p) {
error = -ENOENT;
info = "parent does not exist";
- name = ent->new->base.hname;
goto fail_lock;
}
rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
@@ -1214,9 +1210,22 @@ out:
fail_lock:
mutex_unlock(&ns->lock);
-fail:
- error = audit_policy(op, GFP_KERNEL, name, info, error);
+ /* audit cause of failure */
+ op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
+ audit_policy(op, GFP_KERNEL, ent->new->base.hname, info, error);
+ /* audit status that rest of profiles in the atomic set failed too */
+ info = "valid profile in failed atomic policy load";
+ list_for_each_entry(tmp, &lh, list) {
+ if (tmp == ent) {
+ info = "unchecked profile in failed atomic policy load";
+ /* skip entry that caused failure */
+ continue;
+ }
+ op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
+ audit_policy(op, GFP_KERNEL, tmp->new->base.hname, info, error);
+ }
+free:
list_for_each_entry_safe(ent, tmp, &lh, list) {
list_del_init(&ent->list);
aa_load_ent_free(ent);
--
2.7.4

View File

@@ -1,33 +0,0 @@
From bc3c7d342bf53afdfdf46bc92dac5c624c89fb91 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Sat, 16 Apr 2016 14:19:38 -0700
Subject: [PATCH 11/27] apparmor: fix audit full profile hname on successful
load
Currently logging of a successful profile load only logs the basename
of the profile. This can result in confusion when a child profile has
the same name as the another profile in the set. Logging the hname
will ensure there is no confusion.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index db31bc5..ca402d0 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -1159,7 +1159,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
list_del_init(&ent->list);
op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
- audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
+ audit_policy(op, GFP_ATOMIC, ent->new->base.hname, NULL, error);
if (ent->old) {
__replace_profile(ent->old, ent->new, 1);
--
2.7.4

View File

@@ -1,112 +0,0 @@
From 848da0479e5b9da3dc2ae4c64e0cca77a0abf02a Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 20 Apr 2016 14:18:18 -0700
Subject: [PATCH 12/27] apparmor: ensure the target profile name is always
audited
The target profile name was not being correctly audited in a few
cases because the target variable was not being set and gotos
passed the code to set it at apply:
Since it is always based on new_profile just drop the target var
and conditionally report based on new_profile.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/domain.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 67a7418..fc3036b 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -346,7 +346,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
file_inode(bprm->file)->i_uid,
file_inode(bprm->file)->i_mode
};
- const char *name = NULL, *target = NULL, *info = NULL;
+ const char *name = NULL, *info = NULL;
int error = 0;
if (bprm->cred_prepared)
@@ -399,6 +399,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (cxt->onexec) {
struct file_perms cp;
info = "change_profile onexec";
+ new_profile = aa_get_newest_profile(cxt->onexec);
if (!(perms.allow & AA_MAY_ONEXEC))
goto audit;
@@ -413,7 +414,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (!(cp.allow & AA_MAY_ONEXEC))
goto audit;
- new_profile = aa_get_newest_profile(cxt->onexec);
goto apply;
}
@@ -445,10 +445,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (!new_profile) {
error = -ENOMEM;
info = "could not create null profile";
- } else {
+ } else
error = -EACCES;
- target = new_profile->base.hname;
- }
perms.xindex |= AA_X_UNSAFE;
} else
/* fail exec */
@@ -459,7 +457,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
* fail the exec.
*/
if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
- aa_put_profile(new_profile);
error = -EPERM;
goto cleanup;
}
@@ -474,10 +471,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
error = may_change_ptraced_domain(new_profile);
- if (error) {
- aa_put_profile(new_profile);
+ if (error)
goto audit;
- }
}
/* Determine if secure exec is needed.
@@ -498,7 +493,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
bprm->unsafe |= AA_SECURE_X_NEEDED;
}
apply:
- target = new_profile->base.hname;
/* when transitioning profiles clear unsafe personality bits */
bprm->per_clear |= PER_CLEAR_ON_SETID;
@@ -506,15 +500,19 @@ x_clear:
aa_put_profile(cxt->profile);
/* transfer new profile reference will be released when cxt is freed */
cxt->profile = new_profile;
+ new_profile = NULL;
/* clear out all temporary/transitional state from the context */
aa_clear_task_cxt_trans(cxt);
audit:
error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
- name, target, cond.uid, info, error);
+ name,
+ new_profile ? new_profile->base.hname : NULL,
+ cond.uid, info, error);
cleanup:
+ aa_put_profile(new_profile);
aa_put_profile(profile);
kfree(buffer);
--
2.7.4

View File

@@ -1,27 +0,0 @@
From 706473f3ead5cdffe5ad159adfbc090e0fda81d6 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Thu, 17 Mar 2016 12:02:54 -0700
Subject: [PATCH 13/27] apparmor: check that xindex is in trans_table bounds
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy_unpack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index a689f10..c841b12 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -676,7 +676,7 @@ static bool verify_xindex(int xindex, int table_size)
int index, xtype;
xtype = xindex & AA_X_TYPE_MASK;
index = xindex & AA_X_INDEX_MASK;
- if (xtype == AA_X_TABLE && index > table_size)
+ if (xtype == AA_X_TABLE && index >= table_size)
return 0;
return 1;
}
--
2.7.4

View File

@@ -1,27 +0,0 @@
From 05a64c434466029b298ee1e78a988cd6a7f80c0e Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 18 Nov 2015 11:41:05 -0800
Subject: [PATCH 14/27] apparmor: fix ref count leak when profile sha1 hash is
read
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/apparmorfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 45a6199..0d8dd71 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -331,6 +331,7 @@ static int aa_fs_seq_hash_show(struct seq_file *seq, void *v)
seq_printf(seq, "%.2x", profile->hash[i]);
seq_puts(seq, "\n");
}
+ aa_put_profile(profile);
return 0;
}
--
2.7.4

View File

@@ -1,37 +0,0 @@
From 6b0b8b91f454bd021e27abe0e611a6764e4806c1 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 16 Dec 2015 18:09:10 -0800
Subject: [PATCH 15/27] apparmor: fix refcount race when finding a child
profile
When finding a child profile via an rcu critical section, the profile
may be put and scheduled for deletion after the child is found but
before its refcount is incremented.
Protect against this by repeating the lookup if the profiles refcount
is 0 and is one its way to deletion.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
---
security/apparmor/policy.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index ca402d0..7807125 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -766,7 +766,9 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
struct aa_profile *profile;
rcu_read_lock();
- profile = aa_get_profile(__find_child(&parent->base.profiles, name));
+ do {
+ profile = __find_child(&parent->base.profiles, name);
+ } while (profile && !aa_get_profile_not0(profile));
rcu_read_unlock();
/* refcount released by caller */
--
2.7.4

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