2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-02 23:35:37 +00:00

Compare commits

..

604 Commits

Author SHA1 Message Date
John Johansen
3004390a6c Bump version to 2.10.3
Signed-off-by: John Johansen <john.johansen@canonical.com>
2017-10-19 00:44:42 -07:00
John Johansen
95d2b6ed3d 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.

cherry-pick: r3376
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Suggested-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
[cboltz: Add 'unspec' to the network domain keywords of the utils]
2017-10-18 23:35:11 -07:00
Steve Beattie
2e1d4f5b67 libapparmor: fix swig test_apparmor.py for zero length ptrace records
Merge from trunk revision 3715

The added testcase for a ptrace target with an empty string
(ptrace_garbage_lp1689667_1.in) was causing the swig python test script
to fail. The generated python swig record for libapparmor ends up
setting a number of fields to None or other values that indicate the
value is unset, and the test script was checking if the value in the
field didn't evaluate to False in a python 'if' test.

Unfortunately, python evaluates the empty string '' as False in 'if'
tests, resulting in the specific field that contained the empty string
to be dropped from the returned record. This commit fixes that by
special case checking for the empty string.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2017-10-18 17:09:42 -07:00
John Johansen
24c136f069 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:46:51 -07:00
Christian Boltz
f9df4da913 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:48:42 +02:00
Christian Boltz
4dff14d0b2 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:06 +02:00
Christian Boltz
000cbb1f8a 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:46 +02:00
Christian Boltz
667b38528a Add network 'smc' keyword in NetworkRule and apparmor.d manpage
'smc' seems to be new in kernel 4.12.


Note that the 2.10 apparmor.d manpage also misses the 'kcm' keyword, so
the patch also adds it there.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk, 2.11 and 2.10.
2017-08-30 11:07:28 +02:00
Christian Boltz
d32501b204 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:30 +02:00
Christian Boltz
9c33ba4359 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:44:34 +02:00
Christian Boltz
205f19704a 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:38:02 +02:00
Jamie Strandboge
fdbe6e9f7f 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:19 -05:00
Jamie Strandboge
e409e5b66d 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:12:03 -05:00
Christian Boltz
ed37e5edc2 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:31:49 +02:00
Christian Boltz
98d0f323a4 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:54:44 +02:00
Jamie Strandboge
f052a62e4a Origin: r3669 from trunk
Description: adjust the multiarch alternation rule in the perl abstraction for
 modern Debian and Ubuntu systems which store some modules under the
 architecture-specific perl-base directory instead of perl or perl5.

Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-06-26 14:45:28 -05:00
Christian Boltz
01824ded0b 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:14:35 +02:00
Tyler Hicks
68af901615 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.

If you backport this utility with the fix for CVE-2017-6507 to an
apparmor 2.10 release and your backported aa-remove-unknown utility is
sourcing the upstream rc.apparmor.functions file, you'll want to include
the following bug fix to prevent the aa-remove-unknown utility from
removing child profiles that it shouldn't remove:

  r3440 - Fix: parser: incorrect output of child profile names

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:39:49 +00:00
Tyler Hicks
9dd1cbec0a 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:36:51 +00:00
Seth Arnold
d0ef880bbe parser: Fix delete after new[] -- patch from Oleg Strikov <oleg.strikov@gmail.com> 2017-03-21 21:44:57 -07:00
Christian Boltz
d9be57a140 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:01:51 +01:00
Christian Boltz
5094333f2c 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:47:43 +01:00
Steve Beattie
d47fdc7b42 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:44:40 -08:00
Christian Boltz
860ccb3b13 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:44:40 +01:00
Christian Boltz
1395a86f84 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:42:52 +01:00
Kees Cook
6bcb0928d2 glibc uses /proc/*/auxv and /proc/*/status files, too
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-01-20 17:22:10 -08:00
Kees Cook
f73180c395 Apache2 profile updates for proper signal handling, optional saslauth,
and OCSP stapling

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2017-01-20 17:19:56 -08:00
Steve Beattie
43495f0033 Subject: utils/aa-unconfined: fix netstat invocation regression
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:22:58 -08:00
John Johansen
99cb8cc7f1 update version 2.10.2 2017-01-08 20:19:13 -08:00
Christian Boltz
7b47dee81e Backport abstractions/wayland changes from trunk r3590
Acked-by: Steve Beattie <steve@nxnw.org>

------------------------------------------------------------
revno: 3590
fixes bug: https://launchpad.net/bugs/1507469
committer: Seth Arnold <seth.arnold@canonical.com>
branch nick: apparmor
timestamp: Wed 2016-11-30 15:16:32 -0800
message:
  Add more wayland paths, suggested by Simon McVittie in
  https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1507469
2017-01-08 17:10:09 +01:00
Christian Boltz
789309f419 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:49:47 +01:00
Christian Boltz
e7488ebff1 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:24 +01:00
Christian Boltz
498853ca6e 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:25 +01:00
Christian Boltz
e262991d18 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:22:06 +01:00
Christian Boltz
90b8189547 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:53:39 +01:00
Christian Boltz
34d1b5ddce 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:15:23 +01:00
John Johansen
9d09389290 Add backwards compatibility php5 abstraction
Signed-off-by: John Johansen <john.johansen@canonical.com>
2016-12-07 00:29:41 -08:00
John Johansen
b292de2ca0 Update php abstraction
Signed-off-by: kees cook <kees@outflux.net>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-12-07 00:26:57 -08:00
Christian Boltz
e5daa5fa39 logparser.py: improve file vs. network event recognition
Sometimes network events come with an operation keyword looking like
file_perm which makes them look like file events. Instead of ignoring
these events (which was a hotfix to avoid crashes), improve the type
detection.

In detail, this means:
- replace OPERATION_TYPES (which was basically a list of network event
  keywords) with OP_TYPE_FILE_OR_NET (which is a list of keywords for
  file and network events)
- change op_type() parameters to expect the whole event, not only the
  operation keyword, and rebuild the type detection based on the event
  details
- as a side effect, this simplifies the detection for file event
  operations in parse_event_for_tree()
- remove workaround code from parse_event_for_tree()

Also add 4 new testcases with log messages that were ignored before.

References:

a) various bugreports about crashes caused by unexpected operation keywords:
   https://bugs.launchpad.net/apparmor/+bug/1466812
   https://bugs.launchpad.net/apparmor/+bug/1509030
   https://bugs.launchpad.net/apparmor/+bug/1540562
   https://bugs.launchpad.net/apparmor/+bug/1577051
   https://bugs.launchpad.net/apparmor/+bug/1582374

b) the summary bug for this patch
   https://bugs.launchpad.net/apparmor/+bug/1613061



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


Note: in 2.10, the test_multi/*.profile files are unexpected and not
checked because this part of the tests is trunk-only, therefore I don't
include them.
2016-12-06 22:29:39 +01:00
John Johansen
383bbd68d6 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:21:27 -08:00
Steve Beattie
845507b8a1 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:06:55 -08:00
Christian Boltz
6b2a8191a6 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:36:19 +01:00
Christian Boltz
681fef917b 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:33:46 +01:00
Christian Boltz
b15f758490 logparser.py parse_event(): always store family, protocol and sock_type
Storing these event details depending on the operation type only makes
things more difficult because it's hard to differenciate between file
and network events.

Note that this happens at the first log parsing stage (libapparmor log
event -> temporary python array) and therefore doesn't add a serious
memory footprint. The event tree will still only contain the elements
relevant for the actual event type.

This change means that lots of testcases now get 3 more fields (all
None) when testing parse_event(), so update all affected testcases.
(test-network doesn't need a change for probably obvious reasons.)

Also rename a misnamed test in test-change_profile.


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


Note: 2.10 has fewer rule classes, therefore less test-*.py files need
to be changed. Also, I had to slightly adjust the logparser.py patch
because 2.10 doesn't have support for signal events.
2016-11-19 11:00:01 +01:00
Christian Boltz
c9e3e6e85a 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:01 +01:00
Christian Boltz
6920e3d717 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:15 +01:00
Christian Boltz
ae595aea03 Fix 'alias' rule description in apparmor.d manpage
The apparmor.d description about alias rules was broken in multiple
ways. The manpage
- didn't include the   alias   keyword
- listed alias rules in the "COMMA RULES" section - while that's correct
  for the comma requirement, it's also wrong because COMMA RULES is
  meant to be inside a profile
- didn't list alias rules in the PREAMBLE section

This patch fixes this.

It also moves the definition of VARIABLE, VARIABLE ASSIGNMENT (both
unchanged) and ALIAS RULE next to PREAMBLE.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.10
2016-11-16 20:42:08 +01:00
Christian Boltz
1251e0c143 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:44:53 +01:00
Steve Beattie
b56fdec804 libapparmor python bindings: use __init__.py to import from LibAppArmor.py
Merge from trunk revision 3582.

Fix import errors with swig > 3.0.8 with the libapparmor python
bindings. Do this by removing the code to rename the generated
LibAppArmor.py, and instead use a stub __init__.py that automatically
imports everything from LibAppArmor.py. Also adjust bzrignore to
compensate for the autogenerated file name changing.

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

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-11-14 14:10:35 -08:00
Christian Boltz
eacb977ebd 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:12 +01:00
Christian Boltz
29d287f94e 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:35:20 +01:00
Christian Boltz
9fd54008c4 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:17 +02:00
Christian Boltz
0ffc0941a8 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:03 +02:00
intrigeri
ed68e397aa Profile abstractions: add wayland/weston abstraction
Merged from trunk commit 3566.

Add a basic wayland abstraction.
Include the wayland abstraction from the gnome one.

This is the least invasive solution to the problem I'm trying to
solve right now (Evince not starting in GNOME on Wayland, and probably
similar issues for other GNOME applications I suppose).

Bug: https://bugs.debian.org/827335
Bug: https://bugs.debian.org/807880
2016-10-14 10:01:50 -07:00
Christian Boltz
c79607927d 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:29:59 +02:00
Christian Boltz
353ef34ca0 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:53:37 +02:00
Christian Boltz
80a17a6106 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:15 +02:00
Christian Boltz
44f2c6d2bc [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


*** *** ***   backport
*** *** ***   --fixes lp:1379874
2016-10-01 20:25:51 +02:00
Christian Boltz
a7898cfe5b 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:08 +02:00
Tyler Hicks
91b9b44f53 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:50:43 -05:00
Christian Boltz
8fcfc27d56 Allow 'kcm' in network rules
This is probably
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/Documentation/networking/kcm.txt


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.10.
2016-09-12 23:35:00 +02:00
Christian Boltz
791d40aa9d 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 new hat doesn't get initialized as
profile_storage(), and 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


Acked-by: Steve Beattie <steve@nxnw.org> for trunk, 2.10 and 2.9
2016-08-15 22:06:47 +02:00
Christian Boltz
4ad98a8302 type_is_str(): make pyflakes3 happy
pyflakes3 doesn't check sys.version and therefore complains about
'unicode' being undefined.

This patch defines unicode as alias of str to make pyflakes3 happy, and
as a side effect, simplifies type_is_str().


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.10.
2016-08-12 12:02:43 +02:00
Christian Boltz
064541cb53 delete_duplicates(): don't modify self.rules while looping over it
By calling self.delete() inside the delete_duplicates() loop, the
self.rules list was modified. This resulted in some rules not being
checked and therefore (some, not all) superfluous rules not being
removed.

This patch switches to a temporary variable to loop over, and rebuilds
self.rules with the rules that are not superfluous.

This also fixes some strange issues already marked with a "Huh?" comment
in the tests.


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

Note that in 2.10 cleanprof_test.* doesn't contain a ptrace rule,
therefore the cleanprof_test.out change doesn't make sense for 2.10.
2016-08-08 23:16:12 +02:00
Christian Boltz
9618cc9a62 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:06 +02:00
Christian Boltz
119522307f 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:15:42 +02:00
Christian Boltz
2a929f3f1c 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:44:18 +02:00
Seth Arnold
ec4de6e081 add ld.so.preload to <abstractions/base>, thanks to Uzair Shamim 2016-07-29 11:46:16 -07:00
Christian Boltz
fde4f8a522 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:13:49 +02:00
Seth Arnold
cad5d461ca intrigeri@boum.org 2016-06-24 mod_apparmor manpage: fix "documenation" typo. 2016-06-24 10:36:42 -07:00
Seth Arnold
922096a8be From: Simon McVittie <simon.mcvittie@collabora.co.uk>
Date: Tue, 21 Jun 2016 18:18:45 +0100
Subject: abstractions/nameservice: also support ConnMan-managed resolv.conf

Follow the same logic we already did for NetworkManager,
resolvconf and systemd-resolved. The wonderful thing about
standards is that there are so many to choose from.

Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>

[modified by sarnold to fit the surroundings]
2016-06-22 15:15:42 -07:00
Christian Boltz
9d8340a8b3 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:43:55 +02:00
Christian Boltz
1d8e388c93 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:07:33 +02:00
Christian Boltz
28d5c335af 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:06:25 +02:00
Christian Boltz
8ea1054f50 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:23 +02:00
Christian Boltz
36b699bcf6 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:51:55 +02:00
Christian Boltz
0125d04924 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:18:34 +02:00
Seth Arnold
ad169656bf 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:23:22 -07:00
Seth Arnold
0f7ccc49bb 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:30:29 -07:00
Christian Boltz
90e5294578 load variables in ask_the_questions()
Variables can be used in several rule types (from the existing *Rule
classes: change_profile, dbus, ptrace, signal). It seems nobody uses
variables with those rules, otherwise we'd have received a bugreport ;-)

I noticed this while working on FileRule, where usage of variables is
more common. The file code in bzr (not using a *Rule class) already
loads the variables, so old versions don't need changes for file rule
handling.

However, 2.10 already has ChangeProfileRule and therefore also needs
this fix.


Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.10.
2016-05-10 14:34:40 +02:00
Christian Boltz
6d19a507ae 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:02:11 +02:00
John Johansen
fff8d65985 common/Version: prepare for 2.10.1 release 2016-04-20 02:07:34 -07:00
John Johansen
8e2595c634 Fix: parser: incorrect output of child profile names
BugLink: http://bugs.launchpad.net/bugs/1551950

The apparmor_parser is incorrectly outputting the names of child profiles
and hats, by adding a : between the parent and the child profile name

  Eg.
    /usr/sbin/httpd{,2}-prefork
    /usr/sbin/httpd{,2}-prefork://DEFAULT_URI
    /usr/sbin/httpd{,2}-prefork://HANDLING_UNTRUSTED_INPUT

  instead of what it should be
    /usr/sbin/httpd{,2}-prefork
    /usr/sbin/httpd{,2}-prefork//DEFAULT_URI
    /usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-04-18 13:09:51 -07:00
Christian Boltz
711ca72c6b 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:21:31 +02:00
Tyler Hicks
af8ccba6d2 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:37:26 -05:00
Christian Boltz
fa5d235f28 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:30 +02:00
Christian Boltz
bdb18c5ccf 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:23 +02:00
Christian Boltz
0cd0743b47 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:06 +01:00
Steve Beattie
6e1e27a931 utils: make aa-status(8) work without python3-apparmor
Merge from trunk commit 3391

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

If python3-apparmor is not installed, aa-status aborts due to the
ded
import to handle fancier exception handling failing. This patch makes
aa-status(8) work even in that case, falling back to normal python
exceptions, to keep its required dependencies as small as possible.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2016-03-18 13:32:45 -07:00
Christian Boltz
150350c42c 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:25:29 +01:00
Christian Boltz
61ee9623c5 Prevent crash caused by serialize_profile_from_old_profile()
If a profile file contains multiple profiles and one of those profiles
contains a rule managed by a *Ruleset class,
serialize_profile_from_old_profile() crashes with an AttributeError.

This happens because profile_data / write_prof_data contain only one
profile with its hats, which explodes if a file contains multiple
profiles, as reported in lp#1528139

Fixing this would need lots of
    write_prof_data[hat] -> write_prof_data[profile][hat]
changes (and of course also a change in the calling code) or, better
option, a full rewrite of serialize_profile_from_old_profile().

Unfortunately I don't have the time to do the rewrite at the moment (I
have other things on my TODO list), and changing write_prof_data[hat] ->
write_prof_data[profile][hat] is something that might introduce more
breakage, so I'm not too keen to do that.

Therefore this patch wraps the serialize_profile_from_old_profile() call
in try/except. If it fails, the diff will include an error message and
recommend to use 'View Changes b/w (C)lean profiles' instead, which is
known to work.

Note: I know using an error message as 'newprofile' isn't an usual way
to display an error message, but I found it more intuitive than
displaying it as a warning (without $PAGER).


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



Acked-by: Seth Arnold <seth.arnold@canonical.com> for trunk and 2.10
2016-02-20 13:33:17 +01:00
Christian Boltz
458f696f8e 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:16:49 +01:00
Christian Boltz
331e54b36e Add simple_tests/profile/profile_ns_bad8.sd to utils test exception list
parser/tst/simple_tests/profile/profile_ns_bad8.sd was added in r3376
(trunk) / r3312 (2.10 branch) and contains the profile name ':ns/t'
which misses the terminating ':' for the namespace.

Unfortunately the tools don't understand namespaces yet and just use the
full profile name. This also means this test doesn't fail as expected
when tested against the utils code.

This patch adds profile_ns_bad8.sd to the exception list of
test-parser-simple-tests.py.


Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.10.
2016-02-19 00:25:20 +01:00
Tyler Hicks
85be9528ec 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>
[cboltz: Add 'unspec' to the network domain keywords of the utils]
2016-02-18 16:31:56 -06:00
Tyler Hicks
5493e01408 parser: Properly parse named transition targets
https://launchpad.net/bugs/1540666

Reuse the new parse_label() function to initialize named_transition
structs so that transition targets, when used with change_profile, are
properly seperated into a profile namespace and profile name.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-02-18 16:00:05 -06:00
Tyler Hicks
da0daadf40 parser: Allow the profile keyword to be used with namespaces
https://launchpad.net/bugs/1544387

Don't split namespaces from profile names using YACC grammar. Instead,
treat the entire string as a label in the grammer. The label can then be
split into a namespace and a profile name using the new parse_label()
function.

This fixes a bug that caused the profile keyword to not be used with a
label containing a namespace in the profile declaration.

Fixing this bug uncovered a bad parser test case at
simple_tests/profile/profile_ns_ok1.sd. The test case mistakenly
included two definitions of the :foo:unattached profile despite being
marked as expected to pass. I've adjusted the name of one of the
profiles to :foo:unattached2.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2016-02-18 16:00:04 -06:00
Christian Boltz
6d05fa4a6e 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:09:36 +01:00
Christian Boltz
f5df1bf45e 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:25 +01:00
Christian Boltz
a80c75e308 apparmor.d.pod: document 'deny x'
deny rules don't allow ix, Px, Ux etc. - only 'deny /foo x,' is allowed.


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


Note: Seth mentioned in the mail that he doesn't like the 'deny x'
section too much, but we didn't find a better solution when discussing
it on IRC. Therefore I keep the patch unchanged, but will happily
review a follow-up patch if someone sends one ;-)
2016-02-12 21:43:42 +01:00
Christian Boltz
f5462aa931 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:09:57 +01:00
Tyler Hicks
91e73d54fe 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:35:57 -06:00
Tyler Hicks
57cdc4257d 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:38:39 -06:00
Tyler Hicks
4c04a05996 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:38:39 -06:00
Tyler Hicks
a492bcfc80 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:38:39 -06:00
Steve Beattie
ec9292bd5e utils: handle versioned ruby interpreters
Merge from trunk revision 3353

On Debian and Ubuntu it's possible to have multiple ruby interpreters
installed, and the default to use is handled by the ruby-defaults
package, which includes a symlink from /usr/bin/ruby to the versioned
ruby interpreter.

This patch makes aa.py:get_interpreter_and_abstraction() take that into
account by using a regex to match possible versions of ruby. Testcases
are included. (I noticed this lack of support because on Ubuntu the
ruby test was failing because get_interpreter_and_abstraction()
would get the complete path, which on my 16.04 laptop would get
/usr/bin/ruby2.2.)

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-01-25 23:05:47 -08:00
Christian Boltz
703cc22b52 utils/test/Makefile: print test filenames in 'make check' and 'make coverage'
This makes it easier to find the file that contains a failing test.



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

Bug: https://launchpad.net/bugs/1526085
2016-01-25 23:49:54 +01:00
Christian Boltz
4fd66468d8 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.

Bug: https://launchpad.net/bugs/1525119
2016-01-25 23:45:52 +01:00
Christian Boltz
b80aadd624 Improve __repr__() for *Ruleset
If a *Ruleset is empty, let __repr__() print/return

    <FooRuleset (empty) />

instead of

    <FooRuleset>
</FooRuleset>



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

Bug: https://launchpad.net/bugs/1523297
2016-01-25 23:42:45 +01:00
Steve Beattie
0dde5efc62 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:23:23 -08:00
Christian Boltz
99b59f7169 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:51:52 +01:00
Christian Boltz
061c76c5b1 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:26 +01:00
John Johansen
dab2636a27 Fix: segfault when processing directories
BugLink: http://bugs.launchpad.net/bugs/1534405

Patch -r 2952 switched over to using the library kernel interface, and
added a kernel_interface parameter to the dir_cb struct, that is used
to process directories.

Unfortunately kernel_interface parameter of the dir_cb struct is not being
properly initialized resulting in odd failures and sefaults when the parser
is processing directories.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2016-01-14 17:30:33 -08:00
Christian Boltz
a41bff515f 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.
2016-01-12 19:49:52 +01:00
Christian Boltz
483f11d06c 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:26:46 +01:00
Jamie Strandboge
1140e54442 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:04:34 -06:00
Christian Boltz
b54d1f2049 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:48:43 +01:00
Christian Boltz
6e846245ab Adjust test-aa.py for python2
This means:
- expect unicode (instead of str) when reading from a file in py2
- convert keys() result to a set to avoid test failures because of
  dict_keys type

After this change, all tests work for both py2 and py3.


Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk and 2.10.
2015-12-17 23:45:33 +01:00
Christian Boltz
218cb42fbe Adjust type(x) == str checks in the rule classes for py2
python 3 uses only the 'str' type, while python 2 also uses 'unicode'.
This patch adds a type_is_str() function to common.py - depending on the
python version, it checks for both. This helper function is used to keep
the complexity outside of the rule classes.

The rule classes get adjusted to use type_is_str() instead of checking
for type(x) == str, which means they support both python versions.

Finally, add test-common.py with some tests for type_is_str().


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


Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk and 2.10

Note: 2.10 doesn't contain SignalRule and aare.py, and rule/__init__.py
doesn't have check_and_split_list(), therefore it doesn't get those
parts of the patch.
2015-12-17 23:38:02 +01:00
Tyler Hicks
df12e87fb5 utils: Use apparmor.fail for AppArmorException handling in aa-easyprof
Don't catch AppArmorExceptions in aa-easyprof any longer and rely on
apparmor.fail to print the exception to stderr.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-12-16 16:12:59 -06:00
Christian Boltz
5a2da347d4 Let the apparmor.fail error handler print to stderr
The patch also switches to using error() instead of a plain print() for
AppArmorException, which means prefixing the error message with 'ERROR: '



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


Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk and 2.10.
2015-12-16 12:00:00 +01:00
Tyler Hicks
cfbc1a2a79 parser: Honor the --namespace-string commandline option
https://launchpad.net/bugs/1526085

Revno 2934 'Add fns to handle profile removal to the kernel interface'
introduced a regression in the parser's namespace support by causing the
--namespace-string option to be ignored. This resulted in the profile(s)
being loaded into the global namespace rather than the namespace
specified on the command line.

This patch fixes the bug by setting the Profile object's ns member, if
the --namespace-string option was specified, immediately after the
Profile object is allocated.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-12-15 16:41:35 -06:00
Christian Boltz
51a0d5d863 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:20 +01:00
Christian Boltz
3ab596ed83 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:06:57 +01:00
Christian Boltz
d5824674d1 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:01:19 +01:00
Christian Boltz
3ef80d788a 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:06:07 +01:00
Christian Boltz
d579fc51d4 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:24 +01:00
Christian Boltz
8d68618f0b 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:20 +01:00
Christian Boltz
f6dcade84f Change abstract methods in BaseRule to use NotImplementedError
As Kshitij mentioned, abstract methods should use NotImplementedError
instead of AppArmorBug.

While changing this, I noticed that __repr__() needs to be robust against
NotImplementedError because get_raw() is not available in BaseRule.
Therefore the patch changes __repr__() to catch NotImplementedError.

Of course the change to NotImplementedError also needs several
adjustments in the tests.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
(long before branching off 2.10, therefore I also commit to 2.10)


Note: 2.10 doesn't have test-signal.py, which means it can't be patched ;-)
2015-11-24 00:22:37 +01:00
Christian Boltz
0f4310d301 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:23:31 +01:00
Christian Boltz
84ab95d263 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:26 +01:00
Jamie Strandboge
eb2adf119b 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:52:39 -06:00
Christian Boltz
68041e0d2e Add debug info to profile_storage()
For debugging, it's helpful to know which part of the code initialized a
profile_storage and for which profile and hat this was done.

This patch adds an 'info' array with that information, adds the
corresponding parameters to profile_storage() and changes the callers to
deliver some useful content.


Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.10
2015-11-18 22:02:53 +01:00
Christian Boltz
4c0e6334b5 Fix parsing/storing bare file rules
We replaced parse_audit_allow() with parse_modifiers() in r2833, but
overlooked that parse_modifiers() returns allow/deny as boolean. This
resulted in storing bare file rules in aa[profile][hat]['path'][False]
instead of aa[profile][hat]['path']['allow'] (or True instead of 'deny'
for 'deny file,' rules), with the user-visible result of loosing bare
file rules when saving the profile.

This patch converts the boolean value from parse_modifiers back to a
string.

Note: 2.9 is not affected because the old parse_audit_allow() returns
'allow' or 'deny' as string, not as boolean.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.10
2015-11-18 21:31:45 +01:00
Christian Boltz
73cdd97596 update PYMODULES in tools/Makefile
PYMODULES is used for generating *.pod, so it should include rule/*.PYMODULES


Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for trunk and 2.10
2015-11-18 21:29:25 +01:00
Christian Boltz
dfe58983bb 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:45:47 +01:00
Christian Boltz
07b6148fd1 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:39:33 +01:00
Steve Beattie
d04a03359c Update REPO_URL to point to the apparmor 2.10 branch 2015-11-18 01:32:49 -08:00
John Johansen
1890c13f8a bump parser abi version to force policy recompilation
2.9.x and 2.10 had some time stamp bugs around cache handling that
result in the cache getting a wrong time stamp, and then not getting
correctly updated when policy changes.

Force cache recompiles for these versions by bumping the parser abi

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-11-17 16:21:46 -08:00
Christian Boltz
c97fd38b92 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:44:47 +01:00
Christian Boltz
37ab41bb13 Add __repr__() functions to BaseRule and BaseRuleset
This makes print()ing a class object much more helpful - instead of
    <apparmor.rule.network.NetworkRule object at 0x7f416b239e48>
we now get something like
    <NetworkRule> network inet stream,
(based on get_raw())

A NetworkRuleset will be printed as (also based on get_raw())

<NetworkRuleset>
  network inet stream,
  allow network inet stream, # comment
</NetworkRuleset>

Also add tests to test-network.py to ensure that __repr__() works as
expected.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-28 22:58:56 +01:00
Christian Boltz
cc9cf967b2 Add (abstract) get_clean() method to baserule
Also add a test to ensure it raises an AppArmorBug.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-28 22:52:07 +01:00
Christian Boltz
e700eb04d4 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:00:23 +01:00
Christian Boltz
df57b802f8 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:40:35 +02:00
Christian Boltz
756d622db3 Re-enable check-logprof in profiles 'make check' target
aa-logprof is able to parse all profiles, so there is no longer a
reason to skip this test.

This patch reverts r2097 and r2098 from 2013-01-02.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: John Johansen <john.johansen@canonical.com>
(and now that the tests work even if logprof.conf doesn't exist,
Steve's NACK is no longer valid)
2015-10-20 23:42:41 +02:00
Christian Boltz
274a98d8aa Let 'make check' work without logprof.conf
This patch checks if the cfg object is empty (happens if logprof.conf
doesn't exist). If so, it adds some empty sections to prevent various
failures in code that expects those sections to exist.

Another source of failures was using cfg['section']['setting']. The
patch changes various places to cfg['section'].get('setting') to prevent
those failures. (Those places all have a 'or ...' fallback.)

Finally, find_first_file() in config.py crashed if file_list was Null.
This is fixed by adding an "if file_list:" check before trying to
split() it.

With all those changes applied, 'make check' will work even if
/etc/apparmor/logprof.conf doesn't exist.


The patch also fixes the default value for inactive_profiledir
(I missed aa.py when I changed it to /usr/share/apparmor/extra-profiles/)


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


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:21:51 +02:00
Christian Boltz
bdd8884ab4 Fix handling of interpreters with parameters
If a script contains a hashbang like
    #! /usr/bin/perl -w
aa-autodep created a profile entry like
    "/usr/bin/perl -w" ix,
which is obviously incorrect.

This patch fixes this (by using only the first part of the hashbang line)
and also adds some tests for it.

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


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>

Bug: https://launchpad.net/bugs/1393979
2015-10-20 23:18:43 +02:00
Christian Boltz
d5e9a7ec70 merge script handling into get_interpreter_and_abstraction()
Both create_new_profile() and handle_children() check if the given exec
target is a script and add permissions for the interpreter and a
matching abstraction.

This patch merges that into the get_interpreter_and_abstraction()
function and changes create_new_profile() and handle_children() to use
this function.

A nice side effect is that handle_children() now knows more abstractions
(its original list was incomplete).
The behaviour of create_new_profile() doesn't change.

Also add tests for get_interpreter_and_abstraction() to make sure it
does what we expect.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>

Bug: https://launchpad.net/bugs/1505775
2015-10-20 23:16:41 +02:00
Christian Boltz
19d3b63db3 Add tests for create_new_profile()
These tests ensure that create_new_profile() sets the expected basic
permissions for scripts and non-script files.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:14:42 +02:00
Christian Boltz
58782184a4 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:12:35 +02:00
Christian Boltz
3e5e0c11a0 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:04:23 +02:00
Christian Boltz
3fa19feb43 Parse all parser simple_tests with the utils code
Add a testcase that parses all tests in the parser/tst/simple_tests/
directory with parse_profile_data() to ensure that everything with valid
syntax is accepted, and that all tests marked as FAIL raise an
exception.

This already resulted in
- several patches to fix low-hanging fruits (including some bugs in the
  parser simple_tests itsself)
- a list of tests that don't behave as expected. Those files get their
  expected result reverted to make sure we notice any change in the
  tools behaviour, especially changing to the really expected resulted.
  This method also makes sure that the testcase doesn't report any of
  the known failures.
- a 5% improvement in test coverage - mostly caused by nearly completely
  covering parse_profile_data.
- addition of some missing testcased (as noticed by missing coverage),
  for example several "rule outside of a profile" testcases.

As indicated above, the tools don't work as expected on all test
profiles - most of the failures happen on expected-to-fail tests that
pass parse_profile_data() without raising an exception. There are also
some tests failing despite valid syntax, often with rarely used syntax
like if conditions and qualifier blocks.

Most of the failing (generated) tests are caused by features not
implemented in the tools yet:
- validating dbus rules (currently we just store them without any parsing)
- checks for conflicting x permissions
- permissions before path ("r /foo,")
- 'safe' and 'unsafe' keywords for *x rules
- 'Pux' and 'Cux' permissions (which actually mean PUx and CUx, and get
  rejected by the tools - ideally the generator script should create
  PUx and CUx tests instead)

skip_startswith excludes several generated tests from being run. I know
that skip_startswith also excludes tests that would not fail, but the
generated filenames (especially generated_x/exact-*) don't have a
pattern that I could easily use to exclude less tests - and I'm not too
keen to add a list with 1000 single filenames ;-)


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 23:00:56 +02:00
Christian Boltz
7c02bef563 Get rid of global variable 'logger'
The global variable 'logger' in aa.py is only used by aa-genprof.

This patch changes aa_genprof to use the (new) logger_path() function,
and moves the code for finding the logger path to that function.

Also make the error message more helpful if logger can't be found.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 22:03:58 +02:00
Christian Boltz
52c0494c2f make 'ldd' variable non-global
The 'ldd' variable in aa.py is only used by get_reqs(), therefore move
setting it (based on the configfile) into the function.

get_reqs() doesn't run too often (only called by create_new_profile(),
which means aa-genprof or when adding a Px or Cx rule to a non-existing
profile). This might even lead to a minor performance win - on average,
I'd guess not every aa-logprof run will lead to a completely new profile
or child profile. And, more important, we get rid of a global variable.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-20 20:37:17 +02:00
Christian Boltz
0bc880e3fa Add tests for various rules outside of a profile
All of those tests are expected to fail.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-10-19 21:13:48 +02:00
Christian Boltz
0dc861ef6d Fix missing profile init in create_new_profile()
create_new_profile() didn't init missing required_hats as
profile_storage(), which might lead to crashes when creating a profile
for an application listed in the required_hats config option (= in very
rare cases).

This patch adds the missing profile_storage() call.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-18 22:24:15 +02:00
Christian Boltz
cdc6f74f7e Store filename for includes and hats
This also means the duplicate detection can use the hat's filename instead
of the (possibly wrong) main profile's filename.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-10-18 22:12:53 +02:00
Christian Boltz
2c00e6de9b 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:50:21 +02:00
Steve Beattie
768f11b497 parser: revert changes from commit rev 3248
The changes to the parser made in commit rev 3248 were accidental and
not intended to be committed.
2015-10-14 13:49:26 -07:00
Christian Boltz
a1482f37d8 Add AARE tests for [chars] and [^chars] style globbing to test-aare.py.
With this addition, all globbing styles (as documented in apparmor.d(5))
are covered in the convert_regexp() tests.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-10-14 13:03:16 +02:00
John Johansen
99322d3978 Add LSS presentations about apparmor security model 2015-10-13 15:39:17 -07:00
Christian Boltz
75e3a212f1 load_include(): use include_dir_filelist()
load_include() used a custom os.listdir call instead of
include_dir_filelist() for directory includes, which means it also read
skippable files like *.rpmnew or README. (It seems nobody created a
README inside an included directory, otherwise we'd have seen a
bugreport ;-)

This patch changes load_include() to use include_dir_filelist(). This
function is used in some more places already and removes skippable files
from the file list.


Acked-by <timeout>
2015-10-11 20:34:02 +02:00
Christian Boltz
643ab7dde9 remove unused code from load_include()
load_include() has a "if not incdata:" block which would be entered if
parse_profile_data() returns None. However, parse_profile_data() always
returns a hasher with [incfile][incfile] = profile_storage(), so that
"if not incdata:" never matches.


Acked-by <timeout>
2015-10-11 20:32:22 +02:00
Christian Boltz
b6fc279676 load_include(): avoid loading directory includes multiple times
The "already loaded?" check in load_include() was done at the beginning
of the function, before entering the loop and before the individual
files of directory includes were added to the filelist. This resulted in
a (wrong) "Conflicting profiles" error for directory includes.

This patch moves the "alreay loaded?" check inside the loop, so that
it's executed for all files, including those of directory includes.


Acked-by <timeout>
2015-10-11 20:30:26 +02:00
Christian Boltz
06885e9377 Reset aa and original_aa in read_profiles()
TL;DR: aa-genprof crashes with a wrong 'Conflicting profiles' error.

aa-genprof uses autodep() to create a basic profile, which is then
stored in aa and original_aa. After that, read_profiles() is called,
which reads all profiles (including the new one) from disk, causing a
(wrong) 'Conflicting profiles' error in attach_profile_data() because
the autodep()-generated profile is already there.

Therefore this patch resets aa and original_aa in read_profiles() to
avoid that problem.


Acked-by <timeout>
2015-10-11 20:28:17 +02:00
Christian Boltz
ea9f9aeff2 move tests for convert_regexp() to (new) test-aare.py
The tests for convert_regexp() were hidden in common_test.py, where they
were never executed.

This patch moves them to the new file test-aare.py and also converts the
regex_tests.ini to a tests[] array to have the test data inside the test
file. (All tests from regex_tests.ini are in test-aare.py, and two tests
with prepended and appended path segments were added.)

Also add some tests that check the raw behaviour of convert_regexp() -
the tests "by example" are probably more useful and for sure more
readable ;-) but I want to have some examples of the converted regexes
available.


Acked-by <timeout>
2015-10-11 20:19:35 +02:00
Christian Boltz
807c2dccf0 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:18:22 +02:00
Christian Boltz
9a13402170 Add a new test that was posted on IRC to the test_multi set
This should have been part of the previous commit, but I forgot to add
the files ;-)
2015-10-03 20:22:06 +02:00
Christian Boltz
ddc56bf3ac 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-libapparmor-test_multi.py now also checks all test_multi log lines
against the regex to ensure logparser.py doesn't silently ignore events.

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
2015-10-03 20:18:54 +02:00
Ash Wilson
1a0294129e Fix remount with bind
The parser is incorrectly screening off the bind flags on remount. The
following patch by Ash Wilson fixes this issue

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

Signed-off-by: Ash Wilson <smashwilson@gmail.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-09-21 12:20:19 -07:00
Christian Boltz
562c98d77c 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:06:47 +02:00
Christian Boltz
dbcb634e2e 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>
2015-09-15 14:24:57 +02:00
Christian Boltz
9fe6f652ec 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:00:23 +02:00
Christian Boltz
4794c7c488 Test libapparmor test_multi tests against logparser.py
This testcase will parse all libraries/libapparmor/testsuite/test_multi
tests and compare the result with the *.out files.

It also include a "ToDo list" of keywords that are not yet supported in
the python code - those are typically related to rule types not
supported in the tools yet (dbus, signal etc.).

An interesting special case are exec events with network details:
    testcase01.in, testcase12.in, testcase13.in
which might be hand-made, invalid logs, but nobody remembers ;-)


Acked-by <timeout>
2015-09-05 01:23:43 +02:00
Christian Boltz
a0b9c4c600 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:00 +02:00
Steve Beattie
48801f3290 parser: fix uninitialized policy_cache variable
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-09-01 03:12:08 -07:00
Steve Beattie
1a06c13493 parser: fix cache reference leak
Drop the reference to the libapparmor policy_cache pseudo object when
the parser is done.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-08-31 13:26:14 -07:00
Steve Beattie
cf43130314 libapparmor: fix log parsing memory leaks
Fix memory leaks when parsing dmesg timestamps as well as when handling
message the library does not understand.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-31 13:20:22 -07:00
Steve Beattie
0ff3f14666 libapparmor: fix memory leaks in aalogmisc unit tests.
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-08-27 13:47:52 -07:00
Steve Beattie
9a315c9ef0 parser: make caching tests not fail w/python <= 3.2
In recent commits, Tyler fixed some problems with the caching behavior
of the parser, as well as adjusting and improving the caching test
script to verify these behaviors.

In doing so, the test script adjusts the mtime of various
files and ensures that the written files have the expected mtime
timestamp. Unfortunately, the os.utime() function used to adjust mtime
in python 3.2 (as included in Ubuntu 12.04 LTS) does not update with
nanosecond precision, even though the timestamps returned by os.stat()
do have precision to nanoseconds. This causes the tests to fail when
running under python 3.2 with errors like the following:

  ======================================================================
  FAIL: test_abstraction_newer_rewrites_cache (__main__.AAParserCachingTests)
  ----------------------------------------------------------------------
  Traceback (most recent call last):
    File "/��PKGBUILDDIR��/parser/tst/testlib.py", line 50, in new_unittest_func
      return unittest_func(self)
    File "./caching.py", line 424, in test_abstraction_newer_rewrites_cache
      self._set_mtime(self.abstraction, abstraction_mtime)
    File "./caching.py", line 238, in _set_mtime
      self.assertEquals(os.stat(path).st_mtime, mtime)
  AssertionError: 1440337039.40212 != 1440337039.4021206

The following patch creates a new time stamp equality assertion
function that detects if it's running on python 3.2 or earlier, and
loosens the equality bounds when comparing the passed timestamps. On
python 3.3 and newer, where writing timestamps with nanosecond precision
is supported, the strict equality assertion is used.

(Note: I did not convert all time stamp comparisons, just ones where
the timestamp written and checked could be based on a timestamp
derived from os.stat().)

Reference: https://bugs.python.org/issue12904

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-26 17:39:34 -07:00
Steve Beattie
486e42b221 utils/aa-logprof.pod: fix typo in manpage
Bug: https://bugs.launchpad.net/bugs/1485855
2015-08-25 14:53:55 -07:00
Christian Boltz
318f7d2cb2 Make.rules: sort capabilities with LC_ALL=C
This is needed to make building apparmor.vim reproducable - otherwise
the sorting depends on the locale.

Found by the Debian reproducible project,
https://reproducible.debian.net/rb-pkg/unstable/amd64/apparmor.html


Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-08-25 22:44:58 +02:00
Christian Boltz
68854c5faa Add network mpls and ib to rule/network.py and the apparmor.d manpage
Those two showed up in apparmor.vim when building on latest openSUSE
tumbleweed.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-25 13:27:18 +02:00
Christian Boltz
1078a9f141 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:20:20 +02:00
Tyler Hicks
77d3dcf1cf parser: Don't skip cleanup when the test was skipped
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-18 10:59:21 -05:00
Tyler Hicks
97591bb512 parser: Run caching tests even when apparmorfs is not mounted
The contents of the policy cache files varies based on kernel feature
support found in apparmorfs but the caching tests are mostly about
whether or not a cache file was generated and with the right timestamps.

This patch makes it so that the tests are not entirely skipped when
apparmorfs is not available. Instead, a flat features file will be used
in most cases and only the specific tests that require apparmorfs will
be skipped.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-18 10:59:11 -05:00
Jamie Strandboge
586806907d parser/apparmor_parser.pod: fix typo "sinlge" should be "single"
Bug: https://launchpad.net/bugs/1485530

Signed-Off-By: Jamie Strandboge <jamie@canonical.com>
2015-08-17 09:03:05 -05:00
Tyler Hicks
7c937bb370 parser: Verify cache file mtime in caching tests
This makes several improvements to the parser caching tests to verify
that the parser is properly consuming the mtime of profiles and
abstractions when dealing with the policy cache.

It introduces a simple abstraction file and tests the mtime handling by
changing the mtime on the profile, abstraction, apparmor_parser, and
cache file in various combinations to check the parser's behavior.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-12 12:24:26 -05:00
Tyler Hicks
5c58cdd351 parser: Fix cache file mtime regression
This patch fixes a regression in setting the cache file's timestamp
handling that was introduced in r3079:

  Set cache file tstamp to the mtime of most recent policy file tstamp

The previously used utimes(2) syscall requires a two element timeval
array. The first element in the array is the atime to be used and the
second element is the mtime. The equivalent of a one element timeval
array was being passed to it, resulting in garbage being used for the
mtime value. The utimes(2) syscall either failed, due to the invalid
input, or set mtime to an unexpected value. The return code wasn't being
checked so the failure went unknown.

This patch switches to utimensat(2) for a couple reasons. The UTIME_OMIT
special value allows us to preserve the inode's atime without calling
stat(2) to fetch the atime. It also allows for nanosecond precision
which better aligns with what stat(2) returns on the input profile and
abstraction files. That means that we can have the exact same mtime on
the input profile or abstraction file and the output cache file.

https://launchpad.net/bugs/1484178

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-08-12 12:22:41 -05:00
Steve Beattie
842a592b0d regression tests: make sysctl(2) test a bit more resiliant
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:06:49 -07:00
Christian Boltz
6ce88bb695 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:22 +02:00
Christian Boltz
c9e16d874e Check for duplicate profiles
Having two profiles for the same binary is "technically allowed", but it
leads to interesting[tm] behaviour because one of them "wins" depending
on the load order. To make things even more interesting, the kernel load
order can be different from the tools load order, leading to even more
fun.

Short version: you do _not_ want that situation ;-)

This patch adds a duplicate check to attach_profile_data() so that it
errors out if it finds duplicate profiles or hats, and lists the profile
files that contain them.



Acked-by: Kshitij Gupta <kgupta8592@gmail.com> for both trunk and 2.9.
2015-08-03 01:17:53 +02:00
Christian Boltz
426edf3233 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:14:38 +02:00
Christian Boltz
fd129e1802 Change RE_PROFILE_START to accept variables
Profile name and attachment can contain variables, so the
RE_PROFILE_START regex should accept it.
(Note: the variable content isn't checked.)

Also add some tests with variables.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-03 00:16:23 +02:00
Christian Boltz
61735c60b0 Split logparser.py add_event_to_tree() into multiple functions
add_event_to_tree() is a hard-to-test function because it hands over its
result to add_to_tree().

This patch converts add_event_to_tree() to a simple wrapper function and
moves the main code into parse_event_for_tree() and map_log_type(). These
two new functions return their results and are therefore easier to test.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-08-02 23:58:16 +02:00
Christian Boltz
d95dc87ee7 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:03:02 +02:00
Christian Boltz
8d66d8015f 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:15:31 +02:00
Jamie Strandboge
0ce3f95f8f 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:03:30 -05:00
Jamie Strandboge
4d4fea77de 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:01:46 -05:00
Jamie Strandboge
df27a58931 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:56:27 -05:00
Christian Boltz
986bbf90f9 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:06:57 +02:00
Jamie Strandboge
86f5725c8f [ intrigeri ]
dconf abstraction: allow reading /etc/dconf/**.
That's needed e.g. for Totem on current Debian Jessie.

Acked-By: Jamie Strandboge <jamie@canonical.com>
2015-07-20 10:16:18 -05:00
intrigeri
bdb6855dd3 dconf abstraction: allow reading /etc/dconf/**.
That's needed e.g. for Totem on current Debian Jessie.
2015-07-19 15:42:54 +02:00
Christian Boltz
67da39ff10 drop shebang from apparmor/rule/*.py
The '#!/usr/bin/env python' line in apparmor/rule/*.py is superfluous
and causes "non-executable script" rpmlint warnings on openSUSE.


Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-07-17 21:57:26 +02:00
Steve Beattie
942aaaaa2c common/Version: prepare for 2.10 release 2015-07-14 11:35:33 -07:00
Christian Boltz
7cf219a4b3 Initialize child profile in handle_children()
TL;DR: the answer is "yes" ;-)
(see the patch for the question...)

Long version:
When creating a new child profile with aa-logprof or aa-genprof, the
child profile wasn't properly initialized in handle_children(), which
lead to a crash in delete_duplicates() later because capability etc.
was not set to a CapabilityRuleset etc. class and therefore
profile['capability'] didn't have a .delete_duplicates() method.

Funnily there was already a comment "do we need to init the profile here?"

This patch replaces the question in the comment with the answer.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 20:05:40 +02:00
John Johansen
2d1fc26f54 With the export of more AA_MAY_ defines from apparmor.h
The local defines in the link_subset test collide and result in build
warnings. Replace the defines with a naming that won't collide and
makes it clear a local define for the test is being used.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 10:35:01 -07:00
John Johansen
4ff04c991c Fix: query_label regression test failures
1. The test is using the wrong defines: It is using the defines from the
parser for the packed dfa permissions. This set of permissions is not
meant to be exposed to the outside world

2. The kernel is using the wrong mapping function for the permissions
in the file class. This results in partially exposing the packed
permissions, but even then it doesn't fully line up with the packed
permissions, and is not correct for several of the potential permissions.

Attached is a patch that fixes the test, and moves the two tests that
fail due to the kernel to xpass.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-07-14 10:35:01 -07:00
Steve Beattie
1ef4417f5d regression tests: more ptrace adjustments for arm64 upstream changes
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:29:35 -07:00
Steve Beattie
e5cd1ae073 libapparmor: prepare libtool versioning for impending 2.10 release. 2015-07-14 10:19:25 -07:00
Christian Boltz
b30e85ade2 Add --no-reload option to aa-autodep
Besides adding this feature, this also fixes a crash in tools.py __init__():
    AttributeError: 'Namespace' object has no attribute 'do_reload'


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 01:45:42 +02:00
Christian Boltz
5d5da52a03 fix create_new_profile() to avoid aa-genprof crash
create_new_profile() created a wrong structure for local_profile, which
resulted in an aa-genprof crash directly at startup (in the autodep
phase).

This patch fixes it to use the correct structure.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-14 01:25:06 +02:00
Steve Beattie
71fb983b39 Merge additional German translations 2015-07-11 15:26:50 -07:00
Christian Boltz
4f9a896fa7 replace some spaces with newline in simple_tests
Some of the newly added simple_tests contain lines like
    profile foo@{FOO} { }
which are not supported by the tools because the '}' is in the same line,
while the tools expect \n as rule separator.

This patch changes those tests to
    profile foo@{FOO} {
    }


Acked-by: John Johansen <john.johansen@canonical.com>
2015-07-12 00:23:40 +02:00
Christian Boltz
45cb3d7ec3 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:57:36 +02:00
Christian Boltz
b512d78635 Add DESCRIPTION and EXRESULT to new simple_tests includes
Some of the include files added to simple_tests recently don't live in
one of the main include directories (includes/, includes-preamble/ or
include_tests/) which lets test-parser-simple-tests.py fail because
those files don't contain EXRESULT.

Instead of adding more exceptions to test-parser-simple-tests.py, this
patch adds DESCRIPTION and EXRESULT to those include files.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-07-11 21:54:31 +02:00
Christian Boltz
4acfa81c17 Fix rlimit time units in apparmor.d.pod
- fix double | | between 's' and 'sec'
- remove 'm' which is not supported by the code
- add missing 'd'


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-11 16:56:07 +02:00
Christian Boltz
e59cf31a7b Update RlimitRule to match the parser changes
- allow only a specific set of time units
- optionally allow whitespace between rlimit value and unit
- move check for invalid time units to time_to_int()

Also update the tests:
- add several tests with whitespace between value and unit
- change a test that used the (now invalid) "1m" to "1min"
- change the time_to_int() tests to use 'us' as default unit, and add
  a test with 'seconds' as default unit


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-11 14:05:32 +02:00
Steve Beattie
1a9b613fd5 Add more rlimit equality tests
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-07-10 18:21:07 -07:00
John Johansen
5fd832f004 fix: rlimit unit parsing for time
currently the parser supports ambiguous units like m for time,
which could mean minutes or milliseconds. Fix this and refactor the
time parsing into a single routine.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Steve Beattie <steve@nxnw.org>
2015-07-10 18:16:09 -07:00
John Johansen
28de8fdc40 Fix: Expansion of profile name when it contains aare characters
When @{profile_name} is used within a rule matching expression any
aare expressions should be matched literally and not be interpreted as
aare.

That is
  profile /foo/** { }

needs /foo/** to expand into a regular expression for its attachment
but, /foo/** is also the profiles literal name.  And when trying to
match @{profile_name} in a rule, eg.
  ptrace @{profile_name},

the variable needs to be expaned to
  ptrace /foo/\*\*,

not
  ptrace /foo/**,

that is currently happening.

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

equality tests by
  Tyler Hicks <tyhicks@canonical.com>

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-10 18:11:38 -07:00
John Johansen
2be46bbabc Fix @{profile_name} variable to not be a fqname
The @{profile_name} is incorrectly expanded as a fully qualified path
including its namespace if one was specified in the profile declaration.

ie.
  profile :ns://a {
     ptrace @{profile_name},
     # expands to
     # ptrace :ns://a,
}

This is wrong however because within a profile if a rule refers
to a namespace it will be wrt a sub-namespace.  That is in the above
example the ptrace rule is refering to a profile in a subnamespace
"ns".

Or from the current profile declaration scope
 :ns//ns://a

Instead @{profile_name} should expand into the hname (hierarchical name),
which is the profile hierarchy specification within the namespace the
profile is part of.

In this case
    a

or for a child profile case
  profile :ns://a {
     profile b {
        ptrace @{profile_name},
  }
}

the hname expansion would be
  a//b

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-10 18:11:28 -07:00
John Johansen
835605a647 Add support for variable expansion in profile names, and attachments
allow
  @{FOO}=bar
  /foo@{FOO} { }

to be expanded into
  /foobar { }

and
  @{FOO}=bar baz
  /foo@{FOO} { }

to be expanded into
  /foo{bar,baz} { }
which is used as a regular expression for attachment purposes

Further allow variable expansion in attachment specifications
  profile foo /foo@{FOO} { }

profile name (if begun with profile keyword) and attachments to begin
with a variable
  profile @{FOO} { }
  profile /foo @{FOO} { }
  profile @{FOO} @{BAR} {}

hats
  ^@{FOO}
  hat @{FOO}

and for subprofiles as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-10 18:11:17 -07:00
Launchpad Translations on behalf of apparmor-dev
fd474bb5e1 Launchpad automatic translations update. 2015-07-10 05:19:04 +00:00
Christian Boltz
0792e73ee9 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:12:43 +02:00
John Johansen
50805d80e3 Fix bare include keyword
Fix the regression that caused using 'include' instead of '#include' for
includes to stop working.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 17:19:57 -07:00
Christian Boltz
877fd99c7d Add tests for RE_PROFILE_START and parse_profile_start_line() with unusual whitespace around flags
Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:50:01 +02:00
Christian Boltz
cc4d04a7cc Allow variables in change_profile rules
Now that the parser allows variables in change_profile rules,
the tools should also do that ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:49:10 +02:00
Christian Boltz
0d842eae34 Handle #include <directory> in is_known_rule()
is_known_rule() ignored directory includes, which resulted in asking for
and adding superfluous rules that are already covered by a file in the
included directory.

This patch looks bigger than it is because it moves quite some lines
into the "else:" branch. Everything inside the "else:" just got an
additional whitespace level.

References: https://bugs.launchpad.net/apparmor/+bug/1471425
(however, trunk didn't crash, it "just" ignored directory includes)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:46:01 +02:00
Christian Boltz
16de4ee43d is_known_rule(): check includes recursively
is_known_rule() in aa.py checked only direct includes, but not includes
in the included files. As a result, aa-logprof asked about things that
are already covered by an indirect include.

For example, the dovecot/auth profile includes abstractions/nameservice,
and abstractions/nameservice includes abstractions/nis, which contains
"capability net_bind_service,".
Nevertheless, aa-logprof asked to add capability net_bind_service.

Reproducer: (asks for net_bind_service without this patch, should not
ask for anything after applying the patch):
python3 aa-logprof -d ../profiles/apparmor.d/ -f <(echo 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/usr/lib/dovecot/auth" pid=15454 comm="auth" capability=13  capname="net_bind_service"')

The patch adds code to check include files included by other include
files. Note that python doesn't allow to change a list while looping
over it, therefore we have to use "while includelist" as workaround.

This fixes a regression for network rules (this patch is based on the
old match_net_include() code). Funnily it "only" fixes capability rule
handling (without the "regression" part) because the old
match_cap_include() didn't do the recursive include handling.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-08 22:43:48 +02:00
Christian Boltz
9e601cb3ac 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:32:55 +02:00
Steve Beattie
0e3b8d8fd5 periodic merge from apparmor trunk 2015-07-08 06:44:56 -07:00
Steve Beattie
7307f777c4 AppArmor launchpad translations merge: updates to de.po. 2015-07-08 06:43:20 -07:00
Christian Boltz
ac9f8e2f31 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:15:54 +02:00
Christian Boltz
8c0fe46718 Split off include_dir_filelist() from parse_profile_data() include handling
We need directory listings for #include <directory> in more than one
place, therefore split it off to its own function.

This is a preparation to fix https://bugs.launchpad.net/apparmor/+bug/1471425


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-07 14:11:11 +02:00
Christian Boltz
9d5c0e1b1f NetworkRule: allow TYPE without DOMAIN
Thanks to a bug in the apparmor.d manpage, NetworkRule rejected rules
that contained only TYPE (for example "network stream,"). A bugreport on
IRC and some testing with the parser showed that this is actually
allowed, so NetworkRule should of course allow it.

Note: not strip()ing rule_details is the easiest way to ensure we have
whitespace in front of the TYPE in TYPE-only rules, which is needed by
the RE_NETWORK_DETAILS regex.

Also adjust the tests to the correct behaviour.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-07-07 14:10:17 +02:00
Christian Boltz
4918107a6f Improve exception handling
Instead of always showing a backtrace,
- for AppArmorException (used for profile syntax errors etc.), print only
  the exceptions value because a backtrace is superfluous and would
  confuse users.
- for other (unexpected) exceptions, print backtrace and save detailed
  information in a file in /tmp/ (including variable content etc.) to
  make debugging easier.

This is done by adding the apparmor.fail module which contains a custom
exception handler (using cgitb, except for AppArmorException).

Also change all python aa-* tools to use the new exception handler.

Note: aa-audit did show backtraces only if the --trace option was given.
This is superfluous with the improved exception handling, therefore this
patch removes the --trace option. (The other aa-* tools never had this
option.)


If you want to test the behaviour of the new exception handler, you can
use this script:

#!/usr/bin/python

from apparmor.common import AppArmorException, AppArmorBug
from apparmor.fail import enable_aa_exception_handler

enable_aa_exception_handler()

# choose one ;-)
raise AppArmorException('Harmless example failure')
#raise AppArmorBug('b\xe4d bug!')
#raise Exception('something is broken!')


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-07-06 22:02:34 +02:00
Christian Boltz
714e75299c Make profile flags more whitespace tolerant
As shown in parser/tst/simple_tests/profile/flags/flags_ok_whitespace.sd,
the parser is quite tolerant to additional or missing whitespace around
flags=, while the tools are more strict.

This patch updates the RE_PROFILE_START regex to follow this tolerance.


Acked-by: Steve Beattie <steve@nxnw.org>.
2015-07-06 14:47:05 +02:00
Christian Boltz
f9cae8b1b7 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:45:59 +02:00
Christian Boltz
ece49eefc8 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:44:34 +02:00
Christian Boltz
93941ff7af 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:42:57 +02:00
Christian Boltz
0373df1745 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:25:38 +02:00
Steve Beattie
5a93959068 regression tests: have ptrace use PTRACE_GETREGSET by default
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:24:54 -07:00
Christian Boltz
418241473b Fix rttime default unit in RlimitRule
RlimitRule accidently used 'ms' (milliseconds) as default unit for
rttime rules, but rttime without unit means 'us' (microseconds). This
patch fixes this.

Also add some tests with 'us' as unit, and two more to cover terribly
invalid corner cases (and to improve test coverage by 2 lines ;-)


Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-27 21:52:09 +02:00
Christian Boltz
5ec6eabcdf Use AATest and tmpdir for minitools test
Change minitools tests to use AATest and work inside a tmpdir.

This results in lots of changes ('./profiles' -> self.profile_dir,
local_profilename -> self.local_profilename etc.) and also moves some
code from the global area to AASetup().

Also drop the no longer needed clean_profile_dir() and add linebreaks
in assert* calls with a long error message specified.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-27 01:29:46 +02:00
Christian Boltz
ada85bf219 Add more set_profile_flags() tests
The existing tests didn't test removing all flags.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-26 23:21:29 +02:00
Christian Boltz
1b670fef6c Fix NETWORK RULE in apparmor.d manpage
It's allowed to only specify a TYPE without specifying a DOMAIN.

Also add a missing "]" for QUALIFIERS.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-26 12:46:46 +02:00
John Johansen
8efb5850f2 Move rule simplification into the tree construction phase
The current rule simplification algorithm has issues that need to be
addressed in a rewrite, but it is still often a win, especially for
larger profiles.

However doing rule simplification as a single pass limits what it can
do. We default to right simplification first because this has historically
shown the most benefits. For two reasons
  1. It allowed better grouping of the split out accept nodes that we
     used to do (changed in previous patches)
  2. because trailing regexes like
       /foo/**,
       /foo/**.txt,
     can be combined and they are the largest source of node set
     explosion.

However the move to unique node sets, eliminates 1, and forces 2 to
work within only the single unique permission set on the right side
factoring pass, but it still incures the penalty of walking the whole
tree looking for potential nodes to factor.

Moving tree simplification into the construction phases gets rid of
the need for the right side factoring pass to walk other node sets
that will never combine, and since we are doing simplification we can
do it before the cat and permission nodes are added reducing the
set of nodes to look at by another two.

We do loose the ability to combine nodes from different sets during
the left factoring pass, but experimentation shows that doing
simplification only within the unique permission sets achieve most of
the factoring that a single global pass would achieve.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-25 16:38:04 -06:00
John Johansen
832455de2c Change expr tree construction so that rules are grouped by perms
Currently rules are added to the expression tree in order, and then
tree simplification and factoring is done. This forces simplification
to "search" through the tree to find rules with the same permissions
during right factoring, which dependent on ordering of factoring may
not be able to group all rules of the same permissions.

Instead of having tree factoring do the work to regroup rules with the
same permissions, pregroup them as part of the expr tree construction.
And only build the full tree when the dfa is constructed.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-25 16:38:02 -06:00
John Johansen
5a9300c91c Move the permission map into the rule set
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-25 15:54:15 -06:00
John Johansen
292f3be438 switch away from doing an individual accept node for each perm bit
accept nodes per perm bit where done from the very begining in a
false belief that they would help produce minimized dfas because
a nfa states could share partial overlapping permissions.

In reality they make tree factoring harder, reduce in longer nfa
state sets during dfa construction and do not result in a minimized
dfa.

Moving to unique permission sets, allows us to minimize the number
of nodes sets, and helps reduce recreating each set type multiple
times during the dfa construction.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-25 14:08:55 -06:00
Christian Boltz
f202cc1fd2 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:16:49 +02:00
Steve Beattie
2cbd6c9880 parser: fix make parser_regex missing dependency
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:18:04 -07:00
Tyler Hicks
b786c64b17 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:14:14 -05:00
Christian Boltz
140b88b818 Change aa.py delete_duplicates() to loop over rule classes
That's better than doing copy&paste for each added rule class ;-)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 23:27:06 +02:00
Christian Boltz
f9c60c06d7 severity.py: use re_match_include()
load_variables() used a nearly-correct regex. Drop it and use
re_match_include() instead.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:43:19 +02:00
Christian Boltz
2754e2964b Move re_match_include() to regex.py and improve it
The function is basically a wrapper around a regex, so regex.py is a
much better home.

While on it, rename the regex to RE_INCLUDE, change it to named matches,
use RE_EOL to handle comments and compile it outside the function, which
should result in a (small) performance improvement.

Also rewrite re_match_include(), let it check for empty include
filenames ("#include <>") and let it raise AppArmorException in that
case.

Finally, adjust code calling it to the new location, and add some tests
for re_match_include()


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:41:41 +02:00
Christian Boltz
5e5f8f0001 Add profile_storage()
profile_storage() returns an empty, properly initialized profile.
It doesn't explicitly init all keys (yet) and will be extended over
time, with the final goal to get rid of hasher().

Also change various places in aa.py to use it (instead of an empty
hasher or sub-hasher), and remove various "init rule class (if not done
yet)" cases.

This also avoids a crash in aa-cleanprof remove_duplicate_rules().
Hats weren't properly initialized in aa.py parse_profile_data()
(especially rule classes were missing), which caused a crash because
hasher doesn't support the delete_duplicates() method.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:39:56 +02:00
Christian Boltz
94a2db187a Remove support for writing change hat declarations ("^hat,")
Change hat declarations ("^hat,") are no longer supported (see previous
patch for details). Therefore remove support for writing them.

This also means to completely remove the 'declared' flag, which was only
needed for hat declarations, and was (after the previous patch) always
set to False.

Also add a hat to the cleanprof_test.{in,out} test profile to make sure
aa-cleanprof doesn't break hats, and a hat declaration with the same
name to make sure it gets removed and doesn't break the "real" hat.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:25:39 +02:00
Christian Boltz
d37f777858 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:17:02 +02:00
Christian Boltz
cdb12a9694 Change aa.py to use RlimitRule and RlimitRuleset
Change aa.py to use RlimitRule and RlimitRuleset instead of a sub-hasher
to store and write rlimit rules. In detail:
- drop all rlimit rule parsing from parse_profile_data() and
  serialize_profile_from_old_profile() - instead, just call
  RlimitRule.parse()
- change write_rlimits() to use RlimitRuleset
- add removal of superfluous/duplicate change_profile rules (the old
  code didn't do this)
- update the comment about aa[profile][hat] usage - rlimit and
  change_profile are no longer dicts.

Also cleanup RE_PROFILE_RLIMIT in regex.py - the parenthesis around
'<=' are no longer needed.


Note: This patch is quite small because aa-logprof doesn't ask for
rlimit rules.

I tested all changes manually with aa-cleanprof and aa-logprof (adding
some file rules, rlimit rules kept unchanged)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:12:29 +02:00
Christian Boltz
73dfc75ff4 profiles/Makefile check-parser depends on local/* files
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-19 21:05:49 +02:00
Christian Boltz
7d625e384e check-logprof needs local/* files
check-logprof in profiles/Makefile needs the local/* files.
Add a dependency to make sure they are generated.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-18 22:58:59 +02:00
Tyler Hicks
fa05c2e2e4 libapparmor: Don't apply special SWIG %exception to some functions
Only use the special %exception directive for functions that return a
negative int and set errno upon error.

This prevents, for example, _aa_is_blacklisted() from raising an
exception when it returns -1. This is important because it doesn't set
errno so an exception based on the value of errno would be
unpredictable.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-16 15:51:19 -05:00
Tyler Hicks
d428ef45ea libapparmor: Remove unused path param from _aa_is_blacklisted()
When is_blacklisted() was internal to the parser, it would print an
error message when encountering some file names. If the path parameter
was non-null, the error message would include the file path instead of
the file name.

Now that the function has been moved to libapparmor, callers are
expected to print the appropriate error message if _aa_is_blacklisted()
returns -1. Since the error message printing no longer occurs inside of
_aa_is_blacklisted(), the path parameter can be removed.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-16 15:49:51 -05:00
Tyler Hicks
da52144601 libapparmor: Provide privately exported aa_is_blacklisted() through swig
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-16 15:49:24 -05:00
Tyler Hicks
4d60e07a25 libapparmor: Add README files to the file blacklist
Ignore README files when performing an operation on a list of files.

This matches the behavior of the is_skipped_file() function in aa.py.
The hope is that is_skippable_file() can reuse _aa_is_blacklisted().

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 23:58:45 -05:00
Tyler Hicks
42a66e64ee libapparmor: Store the string len instead of calling strlen() twice
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 23:58:40 -05:00
Tyler Hicks
3e80c75f57 libapparmor: Perform strlen() test before indexing into the string
It looks odd to access the first character of a string before checking
to see if the string's length is zero. This is actually fine, in
practice, since strlen() looks at the first character of the string for
the presence of '\0' which means this is entirely a cosmetic change.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 23:58:29 -05:00
Tyler Hicks
994eb7e3b9 libapparmor: Make swig aware of aa_splitcon(3)
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 18:16:42 -05:00
Tyler Hicks
cb6b450dbf libapparmor: Use extern specifier for new API functions in apparmor.h
Prepend the function prototypes with extern to match the style of the
existing prototypes.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 18:16:42 -05:00
Tyler Hicks
233d553c89 libapparmor: Set errno to EEXIST when only invalid caches are available
The errno values libapparmor's aa_policy_cache_new() uses to indicate
when the cache directory does not exist and when an existing, invalid
cache already exists needed to be separated out. They were both ENOENT
but now the latter situation uses EEXIST.

libapparmor also needed to be updated to not print an error message to
the syslog from aa_policy_cache_new() when the max_caches parameter is
0, indicating that a new cache should not be created, and the cache
directory does not exist. This is an error situation but a debug message
is more appropriate.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 18:16:42 -05:00
Tyler Hicks
2da4200cc0 libapparmor: Create a man page for aa_policy_cache
Create a section 3 man page for the aa_policy_cache family of functions.
Additionally, update the in-code descriptions to match the descriptions
in the man page.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
b7538a6dda libapparmor: Create a man page for aa_kernel_interface
Create a section 3 man page for the aa_kernel_interface family of
functions. Additionally, update the in-code descriptions to match the
descriptions in the man page.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
155a1b0d4a libapparmor: Create a man page for aa_features
Create a section 3 man page for the aa_features family of functions.
Additionally, update the in-code descriptions to match the descriptions
in the man page.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johanse@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
9231d76c35 libapparmor: Migrate aa_policy_cache API to openat() style
The aa_policy_cache_new() and aa_policy_cache_remove() functions are
changed to accept a dirfd parameter.

The cache dirfd (by default, /etc/apparmor.d/cache) is opened earlier in
aa_policy_cache_new(). Previously, the directory wasn't accessed until
later in the following call chain:

  aa_policy_cache_new() -> init_cache_features() -> create_cache()

Because of this change, the logic to create the cache dir must be moved
from create_cache() to aa_policy_cache_new().

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
3d18857dae libapparmor: Migrate aa_kernel_interface API to openat() style
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
350e964e30 libapparmor: Migrate aa_features API to openat() style
Instead of only accepting a path in the aa_features API, accept a
directory file descriptor and a path like then openat() family of
syscalls. This type of interface is better since it can operate exactly
like a path-only interface, by passing AT_FDCWD or -1 as the dirfd.
However, using the dirfd/path combination, it can eliminate string
allocations needed to open files in subdirectories along with the
even more important benefits mentioned in the open(2) man page.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
35f7ab4cdb libapparmor: Clean up function that wraps features dir reading
Make the function prototype for reading a features directory the same
as the function prototype for reading a features file.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
c9c3c09106 libapparmor: Introduce a single function for reading features files
Two different implementations were in use for reading features files.
One for reading a single file and another for reading a single file
after walking a directory. This patch creates a single function that is
used in both cases.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
86de47d08a libapparmor: Use directory file descriptor in _aa_dirat_for_each()
The _aa_dirat_for_each() function used the DIR * type for its first
parameter. It then switched back and forth between the directory file
descriptors, retrieved with dirfd(), and directory streams, retrieved
with fdopendir(), when making syscalls and calling the call back
function.

This patch greatly simplifies the function by simply using directory
file descriptors. No functionality is lost since callers can still
easily use the function after calling dirfd() to retrieve the underlying
file descriptor.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-15 15:11:51 -05:00
Tyler Hicks
014e079261 libapparmor: Allow creating a kernel_interface with a NULL kernel_features
The most common case when creating an aa_kernel_interface object will be
to do so while using the current kernel's feature set for the
kernel_features parameter. Rather than have callers instantiate their
own aa_features object in this situation, aa_kernel_interface_new()
should do it for them if they specify NULL for the kernel_features
parameter.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-15 15:11:51 -05:00
Tyler Hicks
611e891631 libapparmor: Allow creating a policy_cache with a NULL kernel_features
The most common case when creating an aa_policy_cache object will be to
do so while using the current kernel's feature set for the
kernel_features parameter. Rather than have callers instantiate their
own aa_features object in this situation, aa_policy_cache_new() should
do it for them if they specify NULL for the kernel_features parameter.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-15 15:11:51 -05:00
Tyler Hicks
0c19c8d596 libapparmor: Improve documentation of aa_policy_cache_replace_all()
Document that the kernel_interface parameter is optional.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-15 15:11:51 -05:00
Tyler Hicks
3c972e27e5 libapparmor: Adjust some aa_policy_cache function comments
The aa_features object that is passed to aa_policy_cache_new() does not
have to represent the currently running kernel. It may represent a
different kernel, such as a kernel that was just installed, that is not
currently running.

This patch adjusts the function comments to remove mentions of
"... the currently running kernel".

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-15 15:11:51 -05:00
Tyler Hicks
5d6eb1a40f libapparmor: Simplify aa_policy_cache API
This patch changes the aa_policy_cache_new() prototype and gets rid of
aa_policy_cache_is_valid() and aa_policy_cache_create().

The create bool of aa_policy_cache_new() is replaced with a 16 bit
unsigned int used to specify the maximum number of caches that should be
present in the specified cache directory. If the number is exceeded, the
old cache directories are reaped. The definition of "old" is private to
libapparmor and only 1 cache directory is currently supported. However,
that will change in the near future and multiple cache directories will
be supported.

If 0 is specified for the max_caches parameter, no new caches can be
created and only an existing, valid cache can be used. An error is
returned if no valid caches exist in that case.

If UINT16_MAX is specified, an unlimited amount of caches can be created
and reaping is disabled.

This means that 0 to (2^16)-2, or infinite, caches will be supported in
the future.

This change allows for the parser to continue to support the
--skip-bad-cache (by passing 0 for max_caches) and the --write-cache
option (by passing 1 or more for max_caches) without confusing
libapparmor users with the aa_policy_cache_{is_valid,create}()
functions.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-06-15 15:11:50 -05:00
Christian Boltz
5e0d6456e2 Add quotes around '->' at various places in apparmor.d.pod.
Also fix a Cux that should be CUx.


Acked-By: Seth Arnold <seth.arnold@canonical.com> for 2.9 and trunk
2015-06-13 01:01:55 +02:00
John Johansen
7aae13f3df Fix: the default pattern for missing change_onexec id
The default change_onexec id is slightly wrong, it allows matching
'/' as an executable but it really should be anything under /

This results in the equality tests for change_profile failing as it
is different than what specifying /** in a rule does.

We could define rules need to be {/,}** to be equivalent but since
/ can not be an executable change the default value to match what
/** is converted in to.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
3fab352dc4 Extend change_profile tests
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
f364cd7f6f Refactor change_profile to bring ns and none ns target into one rule
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
731718971f Refactor to use a common ns_id for namespace identifiers
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
d5c815783b Fix: refactor change_profile to deal with unexpected TOK_ID error
bison isn't properly handling the 3 options of

TOK_CHANGE_PROFILE opt_id TOK_END_OF_RULE
TOK_CHANGE_PROFILE opt_id TOK_ARROW TOK_ID TOK_END_OF_RULE
TOK_CHANGE_PROFILE opt_id TOK_ARROW TOK_COLON TOK_ID TOK_COLON TOK_END_OF_RULE

specifying
  change_profile /exec,

results in an unexpected TOK_ID error

refactor so that they share the 3 options share a common head which fixes
the problem.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
899cea3396 Fix screening of change_profile permission from file rule entries
While change_profile rules are always created separately from file
rules. The merge phase can result in change_profile rules merging
with file rules, resulting in the change_profile permission being
set when a file rule is created.

Make sure to screen off the change_profile permission, when creating
a file rule.

Note: the proper long term fix is to split file, link and change_profile
rules into their own classes.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
John Johansen
6707489cdc Update change_profile rules to allow specifying the onexec condition
Note: this patch currently overlays onexec with link_name to take
advantage of code already being used on link_name. Ideally what needs
to happen is entry needs to be split into file, link and change_profile
entry classes.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-12 15:25:10 -07:00
Felix Geyer
95cbbe32e0 Respect $CPPFLAGS
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 12:36:15 -07:00
Christian Boltz
5a0d64a70e Get variable names in aa-mergeprof ask_the_questions() in sync with aa.py
Add two variable references (aa and changed) in aa-mergeprof
ask_the_questions() so that the code can use the short name and be more
in sync with aa.py ask_the_questions().

With this patch applied, the "for ruletype in ['capability', 'network']:"
block is in sync, with the exception of the sections that intentionally
differ:
- the check for the profile mode
- the default button selection based on profile mode
- the seen_events counter

The patch also includes some minor whitespace fixes.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-08 22:25:44 +02:00
Christian Boltz
e68d2c70df Add *.orig to .bzrignore
Applying patches often creates *.orig files, and those files are quite
annoying in the "bzr status" output and also in the "unknown" file list
when commiting.

Note: I intentionally don't want to add *.rej files - while those files
should never end up in bzr, they are important enough to be listed in
bzr status output.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-08 22:23:51 +02:00
Christian Boltz
033a35b7d7 split flags_bad.sd
flags_bad.sd contains multiple failures. Split the file into multiple
files with one failure in each and, while on it, using more helpful
filenames.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-08 22:22:07 +02:00
Kshitij Gupta
27b0a571fc Remove re import from cleanprofile.py
The following patch:
- removes re import
- uses apparmor.re_match_include instead of the regex

which also means to use the correct regex instead of
the slightly wrong one cleanprofile.py had

Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-08 01:18:43 +05:30
Kshitij Gupta
255ee31dd4 cleanup import in cleanprofile.py
The cleanprofile.py has an apparmor import, this patch modifies the import to make it consistent with the rest of modules.

Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-07 23:28:53 +05:30
Kshitij Gupta
39b0ac9ba3 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:05:08 +05:30
Christian Boltz
cc4d4715f1 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 some whitespace fixes.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:40:42 +02:00
Christian Boltz
ee10eacff8 Add tests for RlimitRule and RlimitRuleset
This time we only have 98% coverage (some missing and partial) because
I didn't find corner cases that raise some exceptions ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:39:33 +02:00
Christian Boltz
781133c493 Add RlimitRule and RlimitRuleset classes
The class comes with the usual set of features, so I'll only mention a
special feature: the is_covered() and is_equal() functions can even
compare limits with different units (for example they recognize that
2minutes == 120seconds).

Also change RE_PROFILE_RLIMIT:
- make it a bit more strict (the old one accepted any chars, including
  spaces, for rlimit and value)
- convert it to named matches
- '<=' isn't optional - remove the '?' (but keep the parenthesis to
  avoid breaking parsing in aa.py)
- allow rules with no spaces around '<='


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:38:02 +02:00
Christian Boltz
35c7df4194 split off parse_comment() from parse_modifiers()
This is needed for rule types that don't have modifiers in their regex, for
example rlimit rules.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:32:41 +02:00
Christian Boltz
b28c01c2c3 change aa-cleanprof to use reload_profile()
aa-cleanprof (actually clean_profile() in tools.py) used reload_base()
from aa.py which sends the parser output to /dev/null. This had two
effects:
- aa-cleanprof ignored the --no-reload parameter
- there was no error message because reload_base() /dev/null's the
  parser output

This patch changes clean_profile() to use reload_profile() from tools.py
(which honors the --no-reload option).

Also add a TODO note to aa.py reload_base(), the (AFAIK only) winner of
the 'useless use of cat' award in the AppArmor code.
We should really change it to use reload_profile(), even if that means
moving the function from tools.py to aa.py or common.py. And it should
not /dev/null the apparmor_parser output. ;-)


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


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:31:03 +02:00
Christian Boltz
9877075a4b 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>
2015-06-06 14:29:44 +02:00
Christian Boltz
76c30b12de 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>
2015-06-06 14:28:55 +02:00
Christian Boltz
3ccbc2e65d 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:25:41 +02:00
Christian Boltz
ac665528ea 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".

Note: The aa-cleanprof test is still failing because of a bug in
tools.py, but will be fixed by the next patch.
See https://bugs.launchpad.net/apparmor/+bug/1416346 for details.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-06-06 14:24:12 +02:00
Christian Boltz
2421ded8fe 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>
2015-06-06 14:23:02 +02:00
Christian Boltz
e88148d0c8 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.


--fixes lp:1458480
2015-06-06 14:21:21 +02:00
Christian Boltz
59c5683526 Add support for change_profile rules to aa-mergeprof
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:19:59 +02:00
Christian Boltz
48159853b5 Add logprof_header_localvars() to change_profileRule
The function will return the 'Exec Condition' and the 'Target Profile'
as nice list to use in aa-logprof (once we have support for
change_profile in logparser.py) and aa-mergeprof.

Also add some tests to ensure the correct result.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:19:09 +02:00
Christian Boltz
cac52fbf23 Import some aa.py functions into aa-mergeprof by name
This allows to drop the "apparmor.aa." prefix in ask_the_question() to
get the code more in sync with aa.py ask_the_question().


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:17:25 +02:00
Christian Boltz
41912ec027 Change aa.py ask_the_questions() to use the aa-mergeprof code for network rules
Replace the code in aa.py ask_the_questions() that handles network rules
with the ask_the_questions() code initially copied from aa-mergeprof.

This means to convert the network/netdomain log events to a
NetworkRuleset stored in the log_obj hasher, and then let the code from
aa-mergeprof operate on this hasher.

The user interface is mostly unchanged, with two exceptions:
- options always displayed, even if there is only one option
- some slightly changed texts

If you didn't understand why there's a need for the previous patch, this
one should explain it :-)

This also ends up fixing at least one bug where the 'audit' keyword
wasn't listed as a separate qualifier, but instead showed up smooshed
into the Network Family header.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:15:38 +02:00
Christian Boltz
1ad4ef8221 Change aa.py ask_the_questions() to use the aa-mergeprof code for capabilities
Replace the code in aa.py ask_the_questions() that handles capabilities
with the ask_the_questions() code from aa-mergeprof.

This means to convert the capability log events to a CapabilityRuleset
stored in the (new) log_obj hasher, and then let the code from
aa-mergeprof operate on this hasher.

Most of the code after the "aa-mergeprof also has this code" comment is
a direct copy of the aa-mergeprof code, with the following changes:
- filter for profile mode (enforce/complain)
- set default button (allow or deny) based on profile mode
- keep seen_events counter happy (even if it isn't displayed anywhere)
- replace apparmor.aa.foo with just foo

The user interface is mostly unchanged, with two exceptions:
- options always displayed, even if there is only one option
- some slightly changed texts


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:13:44 +02:00
Christian Boltz
6b0387e21e Fix available buttons after switching network 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.


I propose this patch for trunk and 2.9.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
2015-06-06 14:11:29 +02:00
Christian Boltz
8f3688c8d7 aa-mergeprof: move creating the headers for capabilty and network rules inside the loop
Move the code to set q.headers, q.functions and q.default for network
and capability rules inside the "while not done" loop. This ensures to
always have valid headers (for example, after changing the audit
qualifier, the severity was "lost" before) and avoids some duplicated
code.

Also drop a useless "if True:" condition and change the whitespace of
the following lines.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:09:38 +02:00
Christian Boltz
bc259033f9 Replace duplicate code in aa-mergeprof with a loop
Now that the handling for capability and network rules is the same,
wrap the former network rule-only code with
    for ruletype in ['capability', 'network']:
and delete the superfluous ;-) capabiltiy code block.

Needless to say that future updates for other rule types will be
quite easy ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:08:47 +02:00
Christian Boltz
902f88b0bb Add and use logprof_header() and logprof_header_localvars() in *Rule classes
BaseRule:
- add logprof_header() - sets the 'Qualifier' (audit, allow/deny) header
  if a qualifier is specified, calls logprof_header_localvars() and then
  returns an array of headers to display in aa-logprof and aa-mergeprof
- add logprof_header_localvars() - dummy function that needs to be
  implemented in the child classes

NetworkRule: add logprof_header_localvars() - adds 'Network Family'
and 'Socket Type' to the headers

CapabilityRule: add logprof_header_localvars() - adds 'Capability' to
the headers

Also change aa-mergeprof to use rule_obj.logprof_header() for network
and capability rules. This means deleting lots of lines (that moved to
the *Rule classes) and also deleting the last differences between
capabiltiy and network rules.

Finally add tests for the newly added functions.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:04:11 +02:00
Christian Boltz
babebceaf3 Unify code for network and capability rules in aa-mergeprof
This means:

a) for capability rules:
   -  move audit and deny to a new "Qualifier" header (only displayed if
      non-empty)
   -  always display options, even if only one is available
   -  use available_buttons(), which means to add the CMD_AUDIT_* button
   -  add handling for CMD_AUDIT_* button
   -  CMD_ALLOW: only add rule_obj if the user didn't select a #include
   -  move around some code to get it in sync with network rule handling

b) for network rules
   -  move audit and deny to a new "Qualifier" header (only displayed if
      non-empty)
   -  call rule_obj.severity() (not implemented for network rules, does
      nothing)
   -  change messages to generic 'Adding %s to profile.'
   -  move around some code to get it in sync with capability rule
      handling

The only remaining difference is in q.headers[] and the variables
feeding it:
- capability rules show "Capability: foo"
- network rules show "Network Family: foo" and "Socket type: bar"



Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:02:02 +02:00
Christian Boltz
b79fbc9be4 Change aa-logprof and aa-mergeprof to read the severity from CapabilityRule
Note: the   != sev_db.NOT_IMPLEMENTED:   check in aa-mergeprof is
superfluous for capabilities, but will become useful once this code
block is used for other rule types.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 14:01:01 +02:00
Christian Boltz
45cd3618ba Implement severity() in CapabilityRule
Also implement handling for the special capability value '__ALL__' in
severity.py, which is used for 'capability,' rules (aa-mergeprof might
need to display the severity for such a rule).

Finally, add some tests for severity() in test-capability.py and a test
for '__ALL__' in test-severity.py.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 13:59:11 +02:00
Christian Boltz
b067cfc12c Add severity() to BaseRule class
severity() will, surprise!, return the severity of a rule, or
sev_db.NOT_IMPLEMENTED if a *Rule class doesn't implement the severity()
function.

Also add the NOT_IMPLEMENTED constant to severity.py, and a test to
test-baserule.py that checks the return value in BaseRule.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 13:56:26 +02:00
John Johansen
4ed04c8ada add support for rule prefixes to change_profile rules
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-06 01:28:43 -07:00
John Johansen
df568c979a Add support for bare change_profile rule
allow specifying the change_profile keyword

  change_profile,

to grant all permissions change_profile permissions

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-06 01:28:27 -07:00
John Johansen
0b00b5d482 Fix: variable expansion for link target
link rules with a variable in the link target, eg.
   link /foo -> @{var},

do not currently have the variable expanded

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-06 01:28:12 -07:00
John Johansen
9460aa042d Fix: link rules to accept a variable
currently
  link @{foo} -> /bar,
  link /bar -> @{foo}
  link @{foo} -> @{bar},

all fail due to illegal TOK_SET_VAR

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-06 01:27:59 -07:00
John Johansen
b47ac55a9a add query helper for link permissions
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-06 01:27:49 -07:00
John Johansen
a6b6c3cf06 add helper fn to query file path permissions
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-06 01:26:03 -07:00
John Johansen
0cba060d7a Rename AA_MAY_XXX permission bits that conflict with new layout
The parser currently is still using the old permission layout, the kernel
uses a newer layout that allows for more permission bits. The newer
newer permission layout is needed by the library to query the kernel,
however that causes some of the permission bits to be redefined.

Rename the permission bits that cause redefination warnings to use
AA_OLD_MAY_XXX

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-06 01:25:49 -07:00
John Johansen
5d0e6c26b7 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).

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-06 01:22:53 -07:00
John Johansen
c2bbe64ab1 Use mtime instead of ctime for cache file
When caching was converted to use mtime instead of ctime, the cache
file timestamp did not get switched over. This means we are comparing
the cache file's ctime against the policy file's mtime. Which can make
the cache look newer than it really is.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-06 01:22:43 -07:00
John Johansen
69868cda18 add man page for aa_query_label
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-04 02:59:32 -07:00
Steve Beattie
23a2d8b68c This patch fixes several formatting issues with the apparmor.d man page:
- missing formatting code prefixes, usually I for BNFish arguments
 - added blank lines before preformatted sections as the html formatter
   wasn't treating them as seperate from the preceding text (also, they
   generated podchecker warnings)
 - fixed a grammar issue
 - fixed link description text block that was mistakenly indented and
   thus treated as preformatted text
 - moved the "Qualifier Blocks" subsection out of the =over/=back as
   all the pod tools did not like this and it caused podchecker to exit
   with an error, breaking builds that ran make check on the parser
   tree.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-02 16:05:37 -07:00
John Johansen
d7436a872c Rename requires_features and have_features
Rename require_features to require_kernel_features and
       have_features to kernel_features

to indicate they are tests for kernel features, as now there are tests
for parser features and in the future there might be library features
as well.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-02 01:00:29 -07:00
John Johansen
119c751951 The regression tests have issue on backport kernels when the userspace
has not been updated. The issue is that the regression tests detect the
kernel features set and generate policy that the parser may not be able
to compile.

Augment the regressions tests with a couple simple functions to test what
is supported by the parser, and update the test conditionals to use them.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-06-02 01:00:29 -07:00
John Johansen
2d31e2c113 add ability to parser dmesg output as a log file
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-02 01:00:29 -07:00
John Johansen
7cc75c44fa Add log parser test for change_profile
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-06-02 01:00:29 -07:00
John Johansen
4afcf91162 Add documentation of qualifier blocks to apparmor.d man page
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-02 01:00:29 -07:00
John Johansen
04dfc5d975 Add missing I<ALIAS RULE> to B<COMMA RULES> pattern
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-02 01:00:29 -07:00
John Johansen
d506ecfd4d apparmor.d.pod: refactor profile file, profile, subprofile, hat patterns
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-02 01:00:29 -07:00
John Johansen
8ffec9357d apparmor.d.pod: create RULES grouping and cleanup profile PROFILE rule
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-06-02 01:00:29 -07:00
Tyler Hicks
631804e8a7 parser: Document the --features-file option in apparmor_parser(8)
This option was previously only documented in the --help output.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-06-01 11:29:37 -05:00
Launchpad Translations on behalf of apparmor-dev
9f670bed0e Launchpad automatic translations update.
Bug: https://launchpad.net/bugs/1466812
2015-06-01 05:08:17 +00:00
Christian Boltz
01a43e5f1b Convert test-capability.py to AATest
I decided to use a "small" solution for now, which basically means
s/unittest.TestCase/AATest/, cleanup of some setUp() and renaming the
remaining setUp() functions to AASetup().

This doesn't mean an instant win (like in test-severity.py), but allows
to add tests with a tests[] array.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 23:43:27 +02:00
Christian Boltz
5eb796044b Change test-severity.py to use 'unknown' as default rank, and fix the bugs it found
To be able to distinguish between severity 10 and unknown severity,
change AASetup to specify 'unknown' as default rank, and change the
expected result to 'unknown' where it's expected.

Also change the "expected rank %d" to "%s" because it can be a string
now, and add a test that contains directories with different severity
in one variable.

After these changes, handle_variable_rank() errors out with
    TypeError: unorderable types: str() > int()
so fix it by
- initializing rank with the default rank (instead of none)
- explicitely check that rank and rank_new are != the default rank before
  doing a comparison

A side effect is another bugfix - '@{HOME}/sys/@{PROC}/overcommit_memory'
is severity 4, not 10 or unknown (confirmed by reading severity.db).


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 23:39:14 +02:00
Christian Boltz
2f6059767e Convert test-severity.py to use the AATest class
This simplifies test-severity.py a lot:
- lots of test functions are replaced with tests[] arrays
- tempdir handling and cleanup is now done automagically

Even if test-severity.py shrunk by 65 lines, all tests are still there.

There's even an addition - SeverityTestCap now additionally verifies the
result of rank_capability().


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 23:31:56 +02:00
Christian Boltz
cf4eb0182c severity.py: change rank_capability() to not expect the CAP_ prefix
Change rank_capability() so that it doesn't expect the CAP_ prefix.
This makes usage easier because callers can simply hand over the
capability name.

Also change rank() to call rank_capability() without the CAP_ prefix.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 23:29:52 +02:00
Christian Boltz
99b2f67d3c severity.py: rename handle_capability() to rank_capability()
It's only used inside severity.py until now, but I plan to change that
and want a better function name ;-)


Acked-by: Steve Beattie <steve@nxnw.org>.
2015-05-29 23:10:11 +02:00
Christian Boltz
0fd30653fd Use generic names in aa-mergeprof
Replace rule-specific names with generic names:
- s/'capability'/ruletype/
- s/cap_obj/rule_obj/
- s/'network'/ruletype/
- s/net_obj/rule_obj/

Also set ruletype at the beginning of each block.

The long-term goal is to have
    for ruletype in ['capability', 'network', ...]:
with common code to handle all rule types, and having common names makes
it easier to compare the blocks.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 23:03:51 +02:00
Christian Boltz
0461c60a6e cleanup superfluous variable assignments in aa-mergeprof
aa-mergeprof has some sections where it first resets the 'deleted'
variable, and then overwrites it again a line or two later.
This patch removes the superfluous variable resets.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 13:01:37 +02:00
Christian Boltz
8d348b328b let parse_profile_data() check for in-file duplicate profiles
Add a check to parse_profile_data() to detect if a file contains two
profiles with the same name.

Note: Two profiles with the same name, but in different files, won't be
detected by this check.

Also add basic tests to ensure that a valid profile gets parsed, and two
profiles with the same name inside the same file raise an exception.

(Sidenote: these simple tests improve aa.py coverage from 9% to 12%,
which also confirms the function is too long ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 13:00:32 +02:00
Christian Boltz
5fa5125fd4 Add tempdir and tempfile handling to AATest
Add writeTmpfile() to AATest to write a file into the tmpdir. If no
tmpdir exists yet, automatically create one.

createTmpdir() is a separate function so that it's possible to manually
create the tmpdir (for example, if a test needs an empty tmpdir).

Also add a tearDown() function to delete the tmpdir again. This function
calls self.AATeardown() to avoid the need for super() in child classes.

Finally, simplify AaTestWithTempdir in test-aa.py to use createTmpdir()
and add an example for AATeardown() to test-example.py.



Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 12:55:38 +02:00
Christian Boltz
78505f3057 drop unused match_net_include() and match_net_includes() from aa.py
aa-mergeprof no longer calls match_net_includes(), which means the
function can be dropped.

After that, match_net_include() is also unused, so also drop it.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 01:41:35 +02:00
Christian Boltz
c795a1f228 Update aa-mergeprof to use the NetworkRule(set) class layout
aa-mergeprof still used the old aa[profile][hat][allow]['netdomain']
which no longer gets populated. This resulted in not asking for merging
any network rules.

This patch changes ask_the_question() to the NetworkRule(set) layout.
Besides that,
- don't ask for network rules that are already covered.
  Using is_known_rule() also fixes
  https://bugs.launchpad.net/apparmor/+bug/1382241
- include the audit keyword in the "Network Family" headline
  (I'd prefer to just use the get_clean() rule, but that's another topic)
- hide "(A)llow" when merging a deny rule
- as a side effect of using NetworkRule, fix crashes for 'network,' and
  'network foo,' rules

To avoid having to repeat the list of available "buttons" and the logic
to update that list, add a available_buttons() function that returns the
list of available buttons depending on rule_obj.deny and rule_obj.audit
to aa.py, and import it into mergeprof.

I tested all changes manually.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-29 01:12:38 +02:00
Christian Boltz
7728556972 Update aa-mergeprof to use the CapabilityRule(set) class layout
aa-mergeprof still used the old aa[profile][hat][allow]['capability']
which no longer gets populated - which resulted in not asking for
merging any capabilities.

Actually (and funnily),
-                if other.aa[profile][hat].get(allow, False):
-                    continue
resulted in never merging capability rules even before the change to
CapabilityRule(set) - this was meant as optimization, but a "not" was
missing in the condition ;-) so it always skipped capability rules.

The patch changes ask_the_question to the CapabilityRule(set) layout.
Besides that,
- include the audit and deny keywords in the "Capability" headline
  (I'd prefer to just use the get_clean() rule, but that's another topic)
- hide "(A)llow" when merging a deny rule
- don't ask for capabilities that are already covered

Also delete match_cap_includes() from aa.py, which is no longer used.


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

Bug: https://launchpad.net/bugs/1382241
2015-05-29 00:17:02 +02:00
Christian Boltz
534715c2e2 Drop old RE_PROFILE_CHANGE_PROFILE regex from regex.py
Also rename RE_PROFILE_CHANGE_PROFILE_2 to RE_PROFILE_CHANGE_PROFILE
and update apparmor/rule/change_profile.py to use the changed name.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-28 22:26:34 +02:00
Christian Boltz
98383c0816 Change aa.py to use ChangeProfileRule and ChangeProfileRuleset
Change aa.py to use ChangeProfileRule and ChangeProfileRuleset instead
of a sub-hasher to store and write change_profile rules. In detail:
- drop all the change_profile rule parsing from parse_profile_data() and
  serialize_profile_from_old_profile() - instead, just call
  ChangeProfileRule.parse()
- change write_change_profile to use ChangeProfileRuleset
- add removal of superfluous/duplicate change_profile rules (the old
  code didn't do this)

Note that this patch is much smaller than the NetworkRule and
CapabilityRule patches because aa-logprof doesn't ask for adding
change_profile rules - adding that is something for a later patch.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-28 22:25:30 +02:00
Christian Boltz
70f9334cd9 Add tests for ChangeProfileRule and ChangeProfileRuleset
As usual, those classes have 100% test coverage.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-28 22:23:32 +02:00
Christian Boltz
59d4011033 Add ChangeProfileRule and ChangeProfileRuleset classes
Add utils/apparmor/rule/change_profile.py with the ChangeProfileRule and
ChangeProfileRuleset classes. These classes are meant to handle
change_profile rules.

In comparison to the current code in aa.py, ChangeProfileRule has some
added features:
- support for audit and allow/deny keywords (for which John promised a
  parser patch really soon)
- support for change_profile rules with an exec condition


Also add the improved regex RE_PROFILE_CHANGE_PROFILE_2 to regex.py.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-28 22:22:56 +02:00
Christian Boltz
f26b035e90 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
2015-05-28 22:14:37 +02:00
Tyler Hicks
5349536ff8 tests: Add query_label.sh tests for file queries
A number of simple query tests based on read and write perms of files
and directories.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-05-28 14:48:53 -05:00
Tyler Hicks
afde1cc53a tests: Adjust query_label.sh to query a different profile
The test program was querying its own profile. Adjust the profile
generation so that a separate profile is generated and have query_label
query the separate profile.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-05-28 14:48:50 -05:00
Tyler Hicks
a566935d64 tests: Make query_label accept file queries
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-05-28 14:48:46 -05:00
Launchpad Translations on behalf of apparmor-dev
6bcf697731 Launchpad automatic translations update. 2015-05-25 05:09:25 +00:00
Launchpad Translations on behalf of apparmor-dev
ab671b30be Launchpad automatic translations update. 2015-05-21 05:07:49 +00:00
Tyler Hicks
20c2c4c171 libapparmor: Fix pod2man warning in aa_splitcon(3)
*** WARNING: 2 unescaped <> in paragraph at line 43 in file aa_splitcon.pod

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-05-19 21:46:23 -05:00
Tyler Hicks
c6e395c08f libapparmor: Strip a trailing newline character in aa_splitcon(3)
Adjust the internal splitcon() function to strip a single trailing
newline character when the bool strip_newline argument is true.

aa_getprocattr_raw(2) needs to set strip_newline to true since the
kernel appends a newline character to the end of the AppArmor contexts
read from /proc/>PID>/attr/current.

aa_splitcon(3) also sets strip_newline to true since it is unknown
whether the context is originated from a location that appends a newline
or not.

aa_getpeercon_raw(2) does not set strip_newline to true since it is
unexpected for the kernel to append a newline to the the buffer returned
from getsockopt(2).

This patch also creates tests specifically for splitcon() and updates
the aa_splitcon(3) man page.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:31:53 -05:00
Tyler Hicks
8fffe4c721 libapparmor: Add unit tests for aa_splitcon()
Test confinement context splitting, using aa_splitcon(3), with and
without a valid mode pointer.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:30:39 -05:00
Tyler Hicks
014093dedc libapparmor: Add aa_splitcon() public function
Create a new libapparmor public function that allows external code to
split an AppArmor confinement context.

This is immediately useful for code that retrieves a D-Bus peer's
AppArmor confinement context using the
org.freedesktop.DBus.GetConnectionCredentials bus method.

https://launchpad.net/bugs/1430532

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:28:47 -05:00
Tyler Hicks
4879b46b13 libapparmor: Detect errors when splitting confinement contexts
The parse_confinement_mode() function returned NULL when a confinement
mode was not present (unconfined) and when it could not properly parse
the confinement context. The two situations should be differentiated
since the latter should be treated as an error.

This patch reworks parse_confinement_mode() to split a confinement
context and, optionally, assign the mode string. If a parsing error is
encountered, NULL is returned to indicate error.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:20:51 -05:00
Tyler Hicks
f6df1c7516 libapparmor: Clean up confinement context's unconfined check
Use the passed in confinement context string size to improve the
comparison by only doing the string comparison if the size matches and
removing the possibility of reading past the end of the buffer.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:20:37 -05:00
Tyler Hicks
6d8827594a libapparmor: Don't count NUL terminator byte
When passing the size of the confinement context to
parse_confinement_mode(), don't include the NUL terminator byte in the
size.

It is confusing to count the NUL terminator as part of the string's
length. This change makes it so that, after a few additional changes,
parse_confinement_mode() can be exposed as part of libapparmor's public
API.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 21:20:21 -05:00
Tyler Hicks
81f932531c tests: Verify aa_getpeercon() return value
This patch modifies the socketpair.c test to verify the return value of
aa_getpeercon() based upon the expected label and expected mode lengths.

The test had to be changed slightly so that the returned mode, from
aa_getpeercon(), was preserved. It was being overwritten with the
special NO_MODE value.

This change helps to make sure that future changes to the code behind
aa_getpeercon() does not unintentionally change the function's return
value.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-19 21:19:56 -05:00
Christian Boltz
9b5ff659b0 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 and also results in some profile cleanup)


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


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-19 01:25:26 +02:00
Christian Boltz
c2973f0b7b 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:20:49 +02:00
Christian Boltz
bb56f039a8 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:35:51 +02:00
Steve Beattie
c477af77b4 Periodic sync up with apparmor trunk branch. 2015-05-16 10:11:36 -07:00
Steve Beattie
bd3d21e0bc Merge from launchpad translations project. Changes include:
- added and updated Portuguese translations
- added Hungarian, Russian, Polish strings
2015-05-16 10:05:48 -07:00
Christian Boltz
407280c7f5 Delete apparmor/rule/ python cache files in "make clean"
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-11 21:57:55 +02:00
Christian Boltz
481de7e655 move quote_if_needed() to apparmor.rule
quote_if_needed() will be used by the upcoming ChangeProfileRule class,
which means it must be moved out of aa.py to avoid an import loop.
rule/__init__.py looks like a better place.

Also re-import quote_if_needed() into aa.py because it's still needed
there by various functions.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-05-09 13:20:57 +02:00
Christian Boltz
7167632350 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:09:08 +02:00
Steve Beattie
257bc75aa1 parser: merge fix from intrigeri to techdoc timestamp generator to
ensure reproducible builds across timezone variations.
2015-05-05 08:06:49 -07:00
intrigeri
7cf81576c2 Make techdoc.pdf reproducible even in face of timezone variations. 2015-05-03 13:42:39 +02:00
Steve Beattie
6e77515072 Merge typo fix from intrigeri (issue caught by lintian).
Acked-by: Steve Beattie <steve@nxnw.org>
2015-05-01 11:37:55 -07:00
intrigeri
ff0965eee0 parser/dbus.cc: fix "accesss" typo. 2015-05-01 10:25:57 +02:00
Christian Boltz
606c753501 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>
2015-04-29 01:03:17 +02:00
Christian Boltz
ea1033926f AATest: don't limit diff length
Add setUp() to AATest that sets "self.maxDiff = None" (unlimited).
This gives us unlimited array diffs everywhere where AATest is used.

Also rename several setUp() functions in test-regex_matches.py to
AASetup() to avoid that the shiny new AATest setUp() gets overwritten.


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


As requested by Steve, also add an example AASetup() to test-example.py.
2015-04-28 23:37:49 +02:00
Christian Boltz
b56e7b3dfe Add profiles/apparmor.d/local/*.* to .bzrignore
This ignores the sniplets generated by profiles/Makefile, but doesn't
ignore local/README because it doesn't have a dot in its name.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-04-27 21:38:56 +02:00
Christian Boltz
332ee0cba7 Update list of network domains in apparmor.d manpage
Add several missing network DOMAINs to the apparmor.d manpage.

The list is based on the list that utils/vim/Makefile generates.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-04-27 21:37:47 +02:00
Christian Boltz
412f525d5b 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:33:06 +02:00
Christian Boltz
c9fe061525 Use *Rule.match() in aa.py
Replace usage of RE_PROFILE_CAP and RE_PROFILE_NETWORK with
CapabilityRule.match() and NetworkRule.match() calls.
This also means aa.py doesn't need to import those regexes anymore.

As a side effect of this change, test-regex_matches.py needs a small
fix because it imported RE_PROFILE_CAP from apparmor.aa instead of
apparmor.regex.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-04-26 22:02:01 +02:00
Christian Boltz
6dade51f92 Add match() and _match() class methods to rule classes
Add match() and _match() class methods to rule classes:
- _match() returns a regex match object for the given raw_rule
- match() converts the _match() result to True or False

The primary usage is to get an answer to the question "is this raw_rule
your job?". (For a moment, I thought about naming the function
*Rule.myjob() instead of *Rule.match() ;-)

My next patch will change aa.py to use *Rule.match() instead of directly
using RE_*, which will make the import list much shorter and hide
another implementation detail inside the rule classes.

Also change _parse() to use _match() instead of the regex, and add some
tests for match() and _match().


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-04-26 21:59:12 +02:00
Christian Boltz
f340126ec1 Convert existing code to use NetworkRule and NetworkRuleset
Change aa.py to use NetworkRule and NetworkRuleset instead of a
sub-hasher to store, check and write network rules. In detail:
- drop profile_known_network() and use is_known_rule() instead
- replace match_net_includes() usage with match_includes() calls
- drop delete_net_duplicates(), use the code in NetworkRule and
  NetworkRuleset instead
- make match_net_includes() (still used by aa-mergeprof) a wrapper for
  match_includes()
- drop all the network rule parsing from parse_profile_data() and
  serialize_profile_from_old_profile() - instead, just call
  NetworkRule.parse()
- now that write_net_rules() got fixed, drop it ;-)
- change write_netdomain to use NetworkRuleset
- drop netrules_access_check() - that's is_covered() now
- use 'network' instead of 'netdomain' as storage keyword (log events
  still use 'netdomain')

Also update cleanprofile.py to use the NetworkRuleset class.
This also means to delete the (now superfluous) delete_net_duplicates()
function.

Finally, there are some changes in regex.py:
- change RE_PROFILE_NETWORK in regex.py to named matches and to use
  RE_COMMA_EOL (not only RE_EOL)
- drop the no longer needed RE_NETWORK_FAMILY and RE_NETWORK_FAMILY_TYPE
  (rule/network.py has regexes that check against the list of available
  keywords)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-26 21:54:38 +02:00
Christian Boltz
30688225ab Add tests for NetworkRule
Add utils/test/test-network.py with tests for NetworkRule and
NetworkRuleset.

The tests are hopefully self-explaining, so let me just mention the most
important things:
- I started to play with namedtuple, which looks very useful (see "exp")
- the test loops make the tests much more readable (compare with
  test-capability.py!) and make it easy to add some more tests
- 100% coverage :-)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-26 21:53:32 +02:00
Christian Boltz
aae519b2c9 Add NetworkRule and NetworkRuleset classes
Add utils/apparmor/rule/network.py with the NetworkRule and
NetworkRuleset classes. These classes are meant to handle network rules.

In comparison to the existing code in aa.py, relevant news are:
- the keywords are checked against a list of allowed domains, types and
  protocols (these lists are based on what the utils/vim/Makefile
  generates - on the long term an autogenerated file with the keywords
  for all rule types would be nice ;-)
- there are variables for domain and type_or_protocol instead of
  first_param and second_param. (If someone is bored enough to map the
  protocol "shortcuts" to their expanded meaning, that shouldn't be too
  hard.)
- (obviously) more readable code because we have everything at one place
  now
- some bugs are fixed along the way (for example, "network foo," will now
  be kept, not "network foo bar," - see my last mail about
  write_net_rules() for details)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-26 21:50:31 +02:00
Christian Boltz
b83f457c1e Make sure aa-cleanprof de-duplicates capability rules
CleanProf.remove_duplicate_rules() didn't call
  $profile['capability'].delete_duplicates()
because aa-cleanprof sets same_file=True.

Fix this by calling delete_duplicates(None) so that it
only checks the profile against itsself.

Note: this is only needed if the to-be-cleaned profile doesn't
contain any include rules - with includes present, the
"for inc in includes:" block already called delete_duplicates()


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-26 21:49:04 +02:00
Launchpad Translations on behalf of apparmor-dev
831f37b198 Launchpad automatic translations update. 2015-04-25 05:07:37 +00:00
Christian Boltz
764e3b1fc0 Implement in-profile de-duplication in BaseRuleset
Implement in-profile de-duplication in BaseRuleset (currently affects
"only" CapabilityRuleset, but will also work for all future *Ruleset
classes).

Also change 'deleted' to be a simple counter and add some tests that
verify the in-profile deduplication.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-04-24 23:53:21 +02:00
Christian Boltz
f3fe8fcd92 Move test_parse_modifiers_invalid() to test-baserule.py
test_parse_modifiers_invalid() uses a hand-broken ;-) regex to parse
only the allow/deny/audit keywords. This test applies to all rule types
and doesn't contain anything specific to capability or other rules,
therefore it should live in test-baserule.py

Moving that test also means to move the imports for parse_modifiers and
re around (nothing else in test-capability.py needs them).


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-22 22:08:24 +02:00
Christian Boltz
d800f99d9d Add tests for Baserule
Add some tests for the Baserule class to cover the 3 functions that must
be re-implemented in each rule class. This means we finally get 100%
test coverage for apparmor/rule/__init__.py ;-)


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-22 22:05:10 +02:00
Christian Boltz
682e23e1cd 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:01:34 +02:00
Launchpad Translations on behalf of apparmor-dev
1a254613f0 Launchpad automatic translations update. 2015-04-18 05:07:20 +00:00
Christian Boltz
47a811f2f5 Fix typo in CapabilityRule exception message
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-04-17 23:36:00 +02:00
Christian Boltz
57ee8ee5b2 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:10:44 +02:00
Steve Beattie
f35a54c169 profiles: update postfix-common abstraction
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:32:50 -07:00
Christian Boltz
cc946bca8d 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:01:10 +02:00
Christian Boltz
1f9474e653 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:58:24 +02:00
Christian Boltz
a108416ae0 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.


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:50:35 +02:00
Christian Boltz
8374749f5d Add a missing check in rule class is_covered()
"capability foo".is_covered("deny capability foo") should return False
even if check_allow_deny is False.

Also add some tests with check_allow_deny=False.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-14 00:52:55 +02:00
Christian Boltz
da21e0c006 Add libapparmor test-driver and some Makefile.in to .bzrignore.
Also add libraries/libapparmor/swig/perl/Makefile.perle (noticed and
proposed by Steve)

With these changes, "bzr status" is clean again after "make distclean"


Acked-by: Steve Beattie <steve@nxnw.org>.
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-04-14 00:44:49 +02:00
Christian Boltz
51ce5f2758 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:20:31 +02:00
Christian Boltz
6ed926332f 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:15:18 +02:00
Steve Beattie
03b5a470bf profiles: allow ubuntu-helpers to generate texlive fonts
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:14:48 -07:00
Christian Boltz
301449a96e 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:08 +02:00
Christian Boltz
7189347ace 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:27:50 +02:00
Launchpad Translations on behalf of apparmor-dev
a47675d68c Launchpad automatic translations update. 2015-04-04 05:07:07 +00:00
Christian Boltz
a313b674f7 simplify serialize_parse_profile_start()
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-03 17:32:06 +02:00
Christian Boltz
0dc795d181 fix is_skippable_dir() and add tests
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-03 17:29:44 +02:00
Christian Boltz
20cfa21695 replace RE_PROFILE_START
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-03 17:28:03 +02:00
Christian Boltz
a0a044f346 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-03 17:26:26 +02:00
Christian Boltz
bb3c972de9 [patch] make set_profile_flags more strict
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 ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-03 17:25:18 +02:00
Christian Boltz
38b1e3d30f rewrite set_profile_flags() to use write_header()
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

Note: test_set_flags_10, test_set_flags_12 and test_set_flags_nochange_09
will fail with this patch applied. The next patch will fix that.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-03 17:20:14 +02:00
Christian Boltz
b705af0221 Remove 'common' symlinks from .bzrignore
The Makefiles don't create/need the 'common' symlinks since some time,
which also means we no longer need to have them in .bzrignore.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-02 23:48:26 +02:00
Christian Boltz
67ae278436 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:39:00 +02:00
Christian Boltz
f78f11b3a5 Add all __pycache__ directories to .bzrignore
Luckily .bzrignore supports the ** notation ;-)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-02 22:27:15 +02:00
Christian Boltz
7ad490e266 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-02 13:33:14 +02:00
Christian Boltz
df6fce1a91 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-02 13:31:27 +02:00
Christian Boltz
eb0553f11f [patch] rewrite parse_profile_start()
Rewrite parse_profile_start() in aa.py to a more readable version.
The behaviour remains unchanged (and is covered by tests).

The patch also updates the comment about the internal struct of
aa[profile][hat] - initial_comment was missing.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-04-02 13:30:01 +02:00
Christian Boltz
87c5679b91 add tests for RE_PROFILE_START_2 and parse_profile_start_line()
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-02 11:42:28 +02:00
Christian Boltz
6651d4a3ee test new parameters of write_header()
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-02 01:31:22 +02:00
Christian Boltz
b81400185d [patch] extend and partially rewrite write_header()
- 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-02 01:30:01 +02:00
Christian Boltz
e0a8ed7673 add attachment to parse_profile_start() return values
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-01 23:58:29 +02:00
Christian Boltz
0478f6bb11 Add support for attachments to write_header()
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-01 23:50:04 +02:00
Christian Boltz
80e33751c9 add tests for write_header()
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-01 23:48:50 +02:00
Christian Boltz
35382be8d0 add tests for set_profile_flags() (and some fun)
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-01 23:43:29 +02:00
Christian Boltz
b8f0a5cbb2 convert serialize_parse_profile_start() to use parse_profile_start_line()
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.



Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-01 10:58:27 +02:00
Christian Boltz
90efcd7a92 add tests for serialize_parse_profile_start() to test-aa.py
to document the function's behaviour.

Acked-by: Steve Beattie <steve@nxnw.org>
2015-04-01 10:57:24 +02:00
Christian Boltz
3ef67876cb add forgotten test-example.py
The commit message for r2976 says:

    [...]
    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>

but I forgot to add test-example.py to bzr, which I hereby do.
2015-04-01 10:55:33 +02:00
Christian Boltz
4ad6f486f8 update test-aa.py to match parse_profile_start() and get_profile_flags() changes
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-03-31 22:45:45 +02:00
Christian Boltz
da35c243d9 add and use parse_profile_start_line()
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.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-31 22:44:18 +02:00
Christian Boltz
d0d101779a Convert test-regex_matches.py to the new tests[] loop.
The test behaviour is the same with and without this patch - 166 tests
run, all successful.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-31 22:31:36 +02:00
Christian Boltz
7e8191400f add better loop support to common_test.py
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-03-31 22:29:06 +02:00
Steve Beattie
573cfb6b04 fix two issues for older releases
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:46:45 -07:00
Steve Beattie
60332f87a2 profiles: update dnsmasq profile for lxc support
Merge 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:05:09 -07:00
Cameron Norman
26676135c2 usr.sbin.dnsmasq: add lxc-net paths 2015-03-29 20:49:09 -07:00
Jamie Strandboge
0fda13bfa5 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>

Bug: https://launchpad.net/bugs/1403468
2015-03-28 07:18:17 -05:00
Jamie Strandboge
4951c29c11 incorporate feedback from Seth Arnold:
- fix typo in comment
- error() instead of warn() if can't find specified group
2015-03-28 07:16:22 -05:00
Jamie Strandboge
316c615644 merge from trunk 2015-03-27 17:25:23 -05:00
Jamie Strandboge
9e33b760cd implement tests for --include-templates-dir and --include-policy-groups-dir 2015-03-27 16:34:32 -05:00
Jamie Strandboge
0438db70b5 utils/aa-easyprof.pod: corrections for --show-templates and
--show-policy-groups
2015-03-27 16:33:35 -05:00
Jamie Strandboge
2652642c27 update copyright year for modified files 2015-03-26 17:14:52 -05:00
Jamie Strandboge
f47c54984d add --include-templates-dir and --include-policy-groups-dir options to
easyprof to support framework policy on snappy
2015-03-26 16:59:05 -05:00
Tyler Hicks
0d06dfa24c libapparmor: Fix FTBFS when secure_getenv() is not available
Allow libapparmor to build on older systems where secure_getenv() is
still named __secure_getenv(). This snippet was taken from the glibc
wiki:

 https://sourceware.org/glibc/wiki/Tips_and_Tricks/secure_getenv

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-26 16:25:16 -05:00
Tyler Hicks
5a17ffb598 libapparmor: Fix memory leak when freeing aa_policy_cache objects
The two internal aa_features objects weren't being unreferenced when the
aa_policy_cache object was being freed.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-26 10:19:50 -05:00
Tyler Hicks
6da919d400 tests: Add regression tests for the aa_policy_cache API
The aa_features and aa_kernel_interface APIs get a little bit of
testing, as well.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-26 10:19:46 -05:00
Tyler Hicks
fc8d3d4edc libapparmor: Don't leak memory after a realloc(3) failure
realloc() returns NULL when it fails. Using the same pointer to specify
the buffer to reallocate *and* to store realloc()'s return value will
result in a leak of the previously allocated buffer upon error.

These issues were discovered by cppcheck.

Note that 'buffer' in write_policy_fd_to_iface() has the autofree
attribute so it must not be manually freed if the realloc(3) fails as
it'll be automatically freed.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
95bbb0ab3f libapparmor: Remove casts while allocating memory
The libapparmor library is built with gcc, while the parser is built
with g++. The parser code needs to cast pointers returned from the
malloc(3) family of calls. However, code removed from the parser to
libapparmor can drop the casts.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
126472b561 libapparmor: Protect _aa_autofree users from freeing bad pointers
Creates a libapparmor function, _aa_asprintf(), which sets the *strp to
NULL on error. This is needed for all of the users of the _aa_autofree
cleanup attribute because the value of *strp is undefined when
asprintf() fails and that could result in _aa_autofree() being passed a
pointer value that it should not free.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
d862fa8d4c parser: Remove atomic ops
The parser no longer has a need for the atomic operations since all
callers have been moved to libapparmor.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
333e3cc8d8 libapparmor: Move the aa_policy_cache API
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
9a073b8f87 parser: Lift globals from create_cache()
With create_cache() headed for libapparmor, we can't use the show_cache
or write_cache globals.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
ae231a8812 libapparmor: Add macro for the gcc "unused" attribute
As code is moved from the parser to libapparmor, the libapparmor code
base will need to have the "unused" macro defined. This macro will need
to be duplicated in the parser and libapparmor due to it being a
compiler-specific macro that shouldn't be exported from libapparmor.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
7630b8aeb8 libapparmor: Move the aa_kernel_interface API
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
4b829aa53e libapparmor: Rename kernel_interface.c to kernel.c
The existing kernel_interface.c file collides with the expected file
name of the implementation of the aa_kernel_interface API.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
c8b93aed48 libapparmor: Move the aa_features API
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
1d60aca8a8 parser: Don't use gettext(3) in code that will be moved to libapparmor
Remove the use of the "_" macro, which translates into gettext(3), from
code that will be used from the parser to libapparmor since libapparmor
will not support gettext(3) for debug messages and syslog messages.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
ab181805f7 libapparmor: Temporarily duplicate the parser's atomic ops
The parser's copy of the two atomic operations will be removed once the
new API's (aa_features, aa_policy_cache, aa_kernel_interface) are moved
from the parser to libapparmor.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
deec20512b libapparmor: Move over the lib functions needed by cache loading code
The function names must be prepended with "_aa_" since they're going to
be exported from libapparmor. The code bases using the _aa_autofree(),
_aa_autoclose(), and _aa_autofclose() will need to internally alias
those functions to the previously used autofree, autoclose, and
autofclose names.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
6b200b6f08 libapparmor: Add basic logging functionality
This patch adds equivalents of the parser's PDEBUG() and PERROR()
functions to libapparmor.

It does not add gettext(3) support to libapparmor since these are
messages that only developers will see (debug builds with
LIBAPPARMOR_DEBUG=1) or messages that go to the syslog.

PDEBUG() does nothing unless libapparmor is built with --enable-debug.
It prints to stderr if libapparmor is built with --enable-debug and the
LIBAPPARMOR_DEBUG environment variable is set.

PERROR() uses syslog(LOG_ERR, ...) by default. The message is sent to
the syslog and to stderr if libapparmor is built with --enable-debug and
the LIBAPPARMOR_DEBUG environment variable is set.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
27ac220535 libapparmor: Require and build libapparmor with C99 mode
This is needed for some of the parser functionality that will be moved
to libapparmor. In the short term, only the 'bool' type is needed but it
makes sense to simply require a C99 compliant compiler for libapparmor
since the parser is being rewritten in C++. The use of C99 will reduce
future headaches when moving code between the two code bases.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
2879cf217a libapparmor: Create a private API
This patch creates a private API in libapparmor in which upstream
provides no guarantees in regards to ABI stability.

A new header file, <sys/apparmor_private.h>, is created. The "_aa"
prefix will be used for symbols belonging to the private API.

To kick things off, a library friendly version of is_blacklisted() is
moved into libapparmor.

The purpose of a private libapparmor API is to prevent duplicated code
between the parser and libapparmor. This becomes an issue as we prepare
to move chunks of the parser into libapparmor.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
7e218b758d parser: Add aa_policy_cache function to replace all policies
This may be useful for something like an init daemon that simply wants
to load all cached binaries without worrying about any sort of policy
compilation.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:27 -05:00
Tyler Hicks
9aa29f4117 parser: Finalize the aa_kernel_interface API
Create new, ref, and unref functions for aa_kernel_interface. The "new"
function allows for the caller to pass in an aa_features object that is
then used to check if the kernel supports set load operations.
Additionally, the "new" function allows for the apparmorfs path to be
discovered once instead of during every policy load.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
f2154ca65d parser: Use aa_kernel_interface API in parser_interface.c
__sd_serialize_profile() had a duplicated implementation for writing to
apparmorfs interface files after a profile compilation. This patch
migrates it to the new aa_kernel_interface API.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
a23b6a1f81 parser: Shove binary file and fd reading into kernel_interface.c
This is the start of the kernel_interface API that allows callers to
specify a buffer, a file path, or a file descriptor that should be
copied to the proper kernel interface for loading, replacing, or
removing in-kernel policies.

Support exists for reading from a file path or file descriptor into a
buffer and then writing that buffer to the appropriate apparmorfs
interface file.

An aa_kernel_interface_write_policy() function is also provided for
callers that want to route a buffer to an arbitrary file descriptor
instead of to an apparmorfs file. This is useful when an admin instructs
apparmor_parser to write to stdout or a file.

Additionally, it removes some parser-specific globals from the
kernel_interface.c file, such as OPTION_{ADD,REPLACE,REMOVE}, in
preparation for moving the code into a library.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
8553727414 parser: Add policy cache function for cache removal
This function allows for a policy cache to be removed without having a
previously instatiated aa_policy_cache object. It simply works off of a
path.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
f0fcf23231 parser: Create initial interface for policy cache
This API has the same look-and-feel of the previous aa_features API.

The cache setup code was heavily dependent on globals set by CLI
options. Options such as "skip the read cache", or "skip the write
cache", or "don't clear the cache if it isn't valid", won't be useful
for all aa_policy_cache API users so some of that logic was lifted out
of the API. The constructor function still provides a bool parameter
that specifies if the cache should be created or not.

If the policy cache is invalid (currently meaning that the cache
features file doesn't match the kernel features file), then a new
aa_policy_cache object is still created but a call to
aa_policy_cache_is_valid() will return false. The caller can then decide
what to do (create a new valid cache, stop, etc.)

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d93d00cca9 parser: Deprecate the --create-cache-dir option
This option adds unneeded complexity to the parser CLI and the upcoming
aa_policy_cache API. Get rid of it and simply create the cache dir if
--write-cache is specified.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
5b85282e9f parser: Create aa_features function to write features to a file
This patch removes the final dependency on callers needing access to the
features string so aa_features_get_string() can go away.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
4d1fa49c37 parser: Add functions for features support tests
Defines a function that can be called to test features support. It is
string based which allows the support tests to work with new kernel
features without any changes.

The use of global variables in the parser to store and check features
support is still preserved. The parser should probably move over to
passing the aa_features object around but that's left for later.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
0742edf5ba parser: Add features comparison function
This is a simple aa_features equality test. Placing it behind a function
call allows us to do something more complex than a simple string
comparison later.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
f896a64152 parser: Remove exits from features code
This is done in preparation for moving the features code to a library.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
45ac621f26 parser: Begin to flesh out library interface for features
The aa_features_new_*() functions create an aa_features object. They can
be thought of as the constructor of aa_features objects. A number of
constructors are available depending on whether the features are coming
from a file in the policy cache, a string specified on the command line,
or from apparmorfs.

The aa_features_ref() and aa_features_unref() functions are used to grab
and give up references to an aa_features. When the ref count hits zero,
all allocated memory is freed. Like with free(), aa_features_unref() can
be called with a NULL pointer for convenience.

Pre-processor macros are hidden behind functions so that they don't
become part of our ABI when we move this code into libapparmor later on.

A temporary convenience function, aa_features_get_string(), is provided
while code that uses aa_features is migrated from expecting raw features
string access to something more abstract. The function will be removed
in an upcoming patch.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
3091940d31 parser: Clean up snprintf_buffer()
snprintf_buffer() needed to be modified in order to properly return error
conditions up the stack, instead of exiting, but there were some other
cleanups that it could use.

It was obviously implemented with the features_struct in mind so this
patch simplifies the input parameters by directly accepting a
features_struct pointer. Also, the name is changed to reflect that it is
intended to work on a features_struct instead of an arbritrary buffer.

A quick sanity check is added to make sure that the features_struct.pos
value isn't pointing past the end of the buffer.

The printf(3) family of functions can return a negative value upon error
so a check of the return value of vsnprintf(3) is added.

Finally, the return values of the function are simplified to 0 on
success or -1, with errno set, on error. This is possible since
features_struct.pos can be internally updated after a successful
vsnprintf(3).

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
a417a51724 parser: Add support for atomic inc and dec
These operations will be used for grabbing and releasing references to
objects. They leverage the GCC builtins for atomic operations.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
22993081c8 parser: Lift force_clear_cache handling from setup_cache()
This keeps us from having to use the force_clear_cache global in
policy_cache.c.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d2e3f806c0 parser: Don't use the basedir global in setup_cache()
Require the caller of setup_cache() to pass in a valid cache location
string. This removes the use of the basedir global from the
policy_cache.c file.

Additionally, it is no longer necessary to return the "cache dir" path
from setup_cache() since it will always be the same as the input path.
The return value is changed to an int so an error code can be returned
instead of using exit().

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
d02bb58b70 parser: Get rid of the cacheloc global
Modify setup_cache() to accept the user-supplied cacheloc and return the
validated or created cache directory. The caller must then track that
variable and pass it into any parser/policy_cache.c functions that need
it.

The main reason for this change is that the cache location and the cache
directory will soon be two different paths. The cache location will
typically be the parent of the cache directory.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
Tyler Hicks
0f12effabf parser: Move policy cache initialization code into its own function
This patch moves the logic that sets up the policy into a new function
in policy_cache.c

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
2a082ee543 parser: Move policy cache functionality into policy_cache.c
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Fixed build failures]
[tyhicks: Fixed bug where a warning was being printed when it shouldn't]
[tyhicks: Forward ported to trunk]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
4970d40e0d Add fns to handle profile removal to the kernel interface
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported patch to trunk]
[tyhicks: remove commented out code]
[tyhicks: fix use after free]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
4e712f6c8d split routines for loading binary policy into its own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Handle inverted return from find_subdomainfs_mountpoint()]
[tyhicks: Link test progs to libapparmor to fix make check build fail]
[tyhicks: Migrate from opendir() to open() for opening apparmorfs]
[tyhicks: Make some of the split out functions static]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
076bc6be7a With the auto cleanup changes we can now directly return the value if we have a cache hit.
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported patch to trunk]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
f62cc5c6bf Use the gcc cleanup extension attribute to handle closing temp files
While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
82904cf0e6 Use the gcc cleanup extension attribute to handle freeing temp allocations
While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
2015-03-25 17:09:26 -05:00
John Johansen
2dd3fa9383 split the policy cache handling fns into their own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Don't move globals in favor of lifting those out later]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
4959e2e2a8 Move feature handling code into its own file
Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported patch to trunk]
[tyhicks: Don't move set_supported_features()]
[tyhicks: Don't move set_features_by_match_file()]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
c85bca38f5 fix cache write to not happen when skip-bad-cache is specified
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-03-25 17:09:25 -05:00
John Johansen
2b240461a7 change cache check so that debugging can see which file caused failure
Currently the cache tracks the most recent timestamp of parsed files
and then compares that to the cache timestamp. This unfortunately
prevents the parser from being able to know which files caused the
cache check failure.

Rework the cache check so that there is a debug option, and that
the cache file timestamp is set first so that we can output
a deug message for each file that causes a cache check failure.

Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Forward ported to trunk and minor cleanups]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-25 17:09:25 -05:00
Tyler Hicks
afb3cd0b06 parser: Honor USE_SYSTEM make variable in libapparmor_re
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-25 17:09:25 -05:00
Seth Arnold
ec3c202ca2 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 14:58:31 -07:00
Steve Beattie
95ae1c5e8b tests: work around systemd mounting / shared in pivot_root tests
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>
2015-03-24 15:59:44 -07:00
John Johansen
471f90e499 Fix unresolved Merge conflict in apparmor.d.pod RLIMIT RULE
Signed-off-by: John Johansen <john.johansen@canonical.com>
2015-03-24 14:56:40 -07:00
John Johansen
553d98cf9c Add basic documentation of apparmor rlimit controls
buglink: https://launchpad.net/bugs/1429202

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:54:10 -07:00
John Johansen
ebef7d0ca1 update apparmor.d man page to file rule pattern
Update the file rule pattern to show it is possible to specify a bare
file rule. Eg.

  file,

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:53:03 -07:00
John Johansen
a41a887c17 Fix use of FILEGLOB in apparmor.d.pod
Refactor FILEGLOB so that it means both quoted and unquoted file globs.

Also
FILEGLOB was uncorrectly referenced in a few places where it should have
allowed for quoting.

There were also a few places that provided a parameter description with
FILEGLOB without defining that that is full equivalent to FILEGLOB.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:58 -07:00
John Johansen
4ba7f860ac Add basic info about link rules to apparmor.d man page
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:51 -07:00
John Johansen
c92b5c71e5 Update apparmor.d man page to document file rules with leading permissions
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:43 -07:00
John Johansen
6c5cf445c4 Update exec transition documentation.
Add miss ix and ux fallback permission modes, named profile transitions.
Also fix the file access modes and rule pattern to properly reflect
what is allowed.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:36 -07:00
John Johansen
cf68b13042 Add basic documentation of change_profile rules to apparmor.d man page
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:31 -07:00
John Johansen
45df80b972 Update qualifier information in the man page
Consolidate and update the qualifier information in the man page.
Most of the rule qualifiers where duplicated instead of being pulled
into a common section.

Also the rule qualifiers where missing the 'allow' qualifier.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:24 -07:00
John Johansen
7fb067c9d6 Update capability rule description in man page
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-24 03:52:16 -07:00
Steve Beattie
11db55a2fc parser: Expand Equality tests touchups
- 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: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-03-23 11:55:48 -07:00
Steve Beattie
cecbcb0912 parser: make equality.sh honor env variable VERBOSE
- 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.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-03-23 11:45:45 -07:00
John Johansen
0bfad115cd 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.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-23 11:39:44 -07:00
John Johansen
80285dfafb parser: fix compilation failure of deny link rules
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

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-23 11:25:48 -07:00
Christian Boltz
727f3948ec 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:56:41 +01:00
Steve Beattie
ef4e59256b parser: fix equality and valgrind test scripts to use features file
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:35:08 -07:00
Steve Beattie
1b1a0d448d parser: fix warning in net_find_af_name
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:12:09 -07:00
Tyler Hicks
a11a39dd28 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:29 -05:00
Tyler Hicks
92c3b802db 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:27 -05:00
Tyler Hicks
8700b5297a 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:24 -05:00
Tyler Hicks
98ca025c5c 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:19 -05:00
John Johansen
d22a867723 Fix compilation of audit modifiers
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:05:55 -07:00
Launchpad Translations on behalf of apparmor-dev
556babd125 Launchpad automatic translations update. 2015-03-18 05:08:23 +00:00
Launchpad Translations on behalf of apparmor-dev
17397a655b Launchpad automatic translations update. 2015-03-11 05:08:58 +00:00
Christian Boltz
0636dea5c6 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:08:17 +01:00
Steve Beattie
5b92ef4b10 parser: adjust parser.conf example Include statements
The parser.conf example statement for Include statements used
/etc/apparmor.d/abstractions which is unlikely to make anyone enabling
it happy as our shipped and example policies all include the
'abstractions/' directory in the relative paths. This patch adjusts the
example and provides a second example, based on an enabled entry as
shipped in Ubuntu.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-03-09 10:43:13 -07:00
Christian Boltz
6eb46b7b0c klogd, syslog-ng and syslogd moved from /sbin/ to /usr/sbin/ on openSUSE.
Therefore this patch updates the profile to follow the move and makes
sure the profiles are actually used.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-07 21:16:11 +01:00
Christian Boltz
d1900f42c7 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:30:55 +01:00
Christian Boltz
05f78ee733 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>


---------- trunk only, unclear for 2.9 --------------
2015-03-07 13:26:10 +01:00
Christian Boltz
411436e32b 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:25:24 +01:00
Christian Boltz
0c216daa9f 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:24:19 +01:00
Steve Beattie
ce19fe7fde profiles: add mir abstraction
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:46:11 -08:00
Alain BENEDETTI
f29e4a3965 utils/aa-status: don't crash when non-ASCII mountpoints are in use
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:17:05 -08:00
Tyler Hicks
15e9f2790e 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
2867f0d656 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:17:05 +01:00
Steve Beattie
98c6087c54 regression tests: fix gcc-5 inline confusion
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: Seth Arnold <seth.arnold@canonical.com>
2015-03-03 11:38:40 -08:00
Steve Beattie
fc3a7f49cf 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 fixes from Philip Withnall and Simon McVittie.
2015-03-03 11:33:34 -08:00
Christian Boltz
7262b71d47 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:15:00 +01:00
Christian Boltz
55a2809a5a 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>
2015-03-02 21:12:12 +01:00
Christian Boltz
485fde8c50 split flags_bad5.sd parser test into multiple tests
flags_bad5.sd contains tests to ensure the debug flag is no longer
accepted.

However, the file contains multiple expected failures, which means that
it will still fail as long as at least one of them fails. This patch
splits each test into its own file to ensure each of them fails.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 19:56:07 +01:00
Christian Boltz
49bc4efa1e Add parser tests for empty flags (which result in "syntax error")
Acked-by: Steve Beattie <steve@nxnw.org>
2015-03-02 19:48:30 +01:00
Christian Boltz
c469b92afb 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>
2015-03-02 19:36:20 +01:00
Tyler Hicks
54841a1986 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:50:17 -06:00
Tyler Hicks
4bb5fb6003 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:50:14 -06:00
Tyler Hicks
6d1bcdf549 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:50:11 -06:00
Tyler Hicks
65b0048aae 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:50:07 -06:00
Christian Boltz
cec9b0d09f cleanup smbd profiles
The smbd profile contains /{,var/}run/cups/cups.sock rw, which is
covered by abstractions/cups-client and therefore superfluous.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-28 21:35:18 +01:00
Christian Boltz
0166960844 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>



Also update test-capability.py - it contains a test that needs
    'error_code': 0,
added to avoid a failure.

Patch by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-02-28 14:09:45 +01:00
Steve Beattie
d0304227e6 profiles: add geary email client to ubuntu-email abstraction
Merge from Cameron Norman <camerontnorman@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-27 23:24:11 -08:00
Felix Geyer
e2eebe08a8 profiles: allow aspell access to /usr/share/aspell/
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:14:03 -08:00
Steve Beattie
a3433dc170 profiles: add support for /etc/pki/ in ssl certs abstraction
These appear to be related to the update-ca-trust tool.

Thanks to Gregor Dschung.
2015-02-27 22:42:06 -08:00
Christian Boltz
4939f7ce14 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:24:11 +01:00
Philip Withnall
8782872fe2 Remove unused net_find_af_val function, and network_families array
Like net_find_af_name, this assumed that AF_* values were consecutive.

[smcv: split out from a larger patch, added commit message,
removed dead declaration]
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
2015-02-27 16:20:31 +00:00
Philip Withnall
097c520293 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). In addition,
the code that parses <sys/socket.h> does not recognise AF_DECnet (12)
due to the lower-case letters, leading to a gap betwen AF_ROSE (11)
and AF_NETBEUI (13).

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

[smcv: split out from a larger patch, added commit message]
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
2015-02-27 16:20:31 +00:00
Christian Boltz
c913956554 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:19:00 +01:00
Steve Beattie
35bbe528d2 parser: fix more gcc 5 compilation problems
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 14:55:13 -08:00
Christian Boltz
608f6493be delete traces of program-chunks directory from apparmor.d(5)
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-02-26 18:44:22 +01:00
Cameron Norman
4803eb7fa2 abstractions/ubuntu-email: add geary 2015-02-22 20:23:04 -08:00
Christian Boltz
064697e791 require logfile only for aa-logprof and aa-genprof
Make sure most tools (for example aa-complain) don't error out if
no logfile can be found. (For obvious reasons, aa-logprof and
aa-genprof will still require a logfile ;-)

This is done by moving code from the global area in aa.py to the new
function set_logfile(), which is called by aa-logprof and aa-genprof.

While on it,
- rename apparmor.filename to apparmor.logfile
- move the error handling for user-specified logfile from aa-genprof
  and aa-logprof to aa.py set_logfile()

Note: I'd have prefered to hand over the logfile as parameter to
do_logprof_pass(), but that would break last_audit_entry_time() in
aa-genprof which requires the log filename before do_logprof_pass()
is called.

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


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2015-02-20 21:36:55 +01:00
Seth Arnold
4ec29a7e29 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
2015-02-12 13:20:57 -08:00
John Johansen
a0706d3a46 And the related patch to fix globbing for af_unix abstract names
Abstract af_unix socket names can contain a null character, however the
aare to pcre conversion explicitly disallows null characters because they
are not valid characters for pathnames. Fix this so that they type of
globbing is selectable.

this is a partial fix for

Bug: http://bugs.launchpad.net/bugs/1413410

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-12 10:19:16 -08:00
John Johansen
daa07671c7 Currently the parser does escape processing in multiple places, this can result in failures if not handled properly
The lexer front end currently incorrectly processes the \000 \x00 \d00 escape sequence resulting in a null character being embedded in the processed string, this results in the string not being full processed later.

The aare to pcre regex conversion fn also incorrectly strips out the \00, and any other escape sequence it doesn't know about, resulting in incorrect strings being passed to the backend. Fix this by passing through any valid escape sequence that is not handled by the fn.

this is a partial fix for
Bug: http://bugs.launchpad.net/bugs/1413410

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-12 10:17:44 -08:00
Tyler Hicks
236ed1cf3a tests: Update code to correctly use the terms context and label
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-09 18:46:51 -06:00
Tyler Hicks
011777f483 mod_apparmor: Update code to correctly use the terms context and label
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-09 18:46:49 -06:00
Tyler Hicks
98a71b5120 libapparmor: Update code to correctly use the terms context and label
Adjust the libapparmor function prototypes, variable names, and comments
that incorrectly used the name "con" when referring to the label.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-09 18:46:46 -06:00
Tyler Hicks
e08f940413 libapparmor: Document the terms context and label in aa_getcon(2)
The correct usage of the terms context and label is not clear in the
aa_getcon(2) man page. The aa_getcon(2) family of functions are also
prototyped incorrectly since the *con parameter represents a label and
not a context.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2015-02-09 18:46:42 -06:00
Christian Boltz
9d471cdd73 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:16:29 +01:00
Christian Boltz
68a19c4943 Raise an exception if sub_str_to_mode() is called with invalid mode
string or if a mode_char is not in MODE_HASH.

Also update the testcase for "asdf42" (which raises AppArmorBug now)
and add a test that simulates MODE_HASH and MODE_MAP_SET getting out
of sync (tests the second part of the if condition).


Acked-by: Steve Beattie <steve@nxnw.org>
2015-02-03 12:47:36 +01:00
Christian Boltz
5365e12dc9 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:52:07 +01:00
Gregor Dschung
f14150c594 added /etc/pki/trust to the ssl_certs-profile 2015-01-31 16:51:17 +01:00
Christian Boltz
9f1ba65471 rename _clean to pod_clean in Makefiles
Since the Makefile cleanup, the _clean target is only used to delete
manpages etc. generated from *.pod files.

This patch renames the _clean target to pod_clean to make it obvious
what it does.


Acked-by: John Johansen <john.johansen@canonical.com>
2015-01-30 22:15:53 +01:00
Christian Boltz
da8230fe95 remove superfluous/outdated comment about m / ix
For the records: the valid statement from the comment is:
    # m is not implied by ix


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2015-01-30 21:08:17 +01:00
John Johansen
03d7c37650 Currently the parser does escape processing in multiple places, this can result in failures if not handled properly
The lexer front end currently incorrectly processes the \000 \x00 \d00 escape sequence resulting in a null character being embedded in the processed string, this results in the string not being full processed later.

The aare to pcre regex conversion fn also incorrectly strips out the \00, and any other escape sequence it doesn't know about, resulting in incorrect strings being passed to the backend. Fix this by passing through any valid escape sequence that is not handled by the fn.

this is a partial fix for
Bug: http://bugs.launchpad.net/bugs/1413410

Signed-off-by: John Johansen <john.johansen@canonical.com>
2015-01-29 14:54:08 -08:00
Christian Boltz
3e74935279 move the DISTRO variable definition from common/Make.rules to
parser/Makefile (which is the only Makefile that uses the DISTRO
variable)

Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-28 22:44:35 +01:00
Christian Boltz
70efe0cb53 delete superfluous 'dist_clean' target from parser/Makefile
'dist_clean' deletes files that are already deleted by 'clean', which
means it's superfluous.


Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-28 22:40:00 +01:00
Steve Beattie
a157966205 libapparmor: more Makefile cleanups
Get rid of the relics in libapparmor's Makefile.am for generating
tarballs from svn, which is no longer relevant. Also clean generated
manpages during make clean rather than just make maintainer-clean.
2015-01-26 15:39:10 -08:00
Steve Beattie
109c7c625f common: more Make.rules cruft removal
This patch removes a bunch of the per-directory tarball and rpm
generation cruft that is no longer needed now that we've been
distributing a unified tarball in our releases.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2015-01-23 16:01:14 -08:00
Steve Beattie
f19eb31f23 Entire tree: makefile cruft removal
- drop the symlink magic of the common/ directory, and just include
  files directly from there.
- update comments indicating required steps to take when including
  common/Make.rules
- drop make clean steps that refer to no longer generated tarballs,
  specfiles, and symlinks to the common directory/Make.rules.
- don't silence clean steps if VERBOSE is set

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian "Ghostbuster" Boltz <apparmor@cboltz.de>
2015-01-23 15:52:09 -08:00
Christian Boltz
0da2be8432 Add a "common_Make.rules_is_a_bad_target" target to common/Make.rules to
make sure nothing accidently hits the first-best target (well,
first-not-so-good would better describe the rpm target ;-)

Also add a dummy "all:" target to the toplevel Makefile with a short
hint towards README.

(see "[patch] fun with the toplevel Makefile") on the ML for the fun
that lead to this patch)


Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-23 20:40:40 +01:00
Jamie Strandboge
024e7ddf41 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:30:46 -06:00
Launchpad Translations on behalf of apparmor-dev
f44af220d4 Launchpad automatic translations update. 2015-01-21 05:32:44 +00:00
Christian Boltz
bb11ad3551 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:55:15 +01:00
Christian Boltz
d30cdf06e4 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>
2015-01-17 11:04:12 +01:00
Christian Boltz
60b05ab1b9 rule class - split out common parts from is_covered()
Split is_covered() in capability.py into
- is_covered_localparts() for rule-specific code
- is_covered() for common code - located in __init__.py

The object type comparison now uses type(self) and a slightly different
error message to make it usable everywhere.

Also rename rule_obj to other_rule which is more self-explaining
(inspired by the parameter name in the is_covered() dummy in __init__.py).


v2:
- remove check_allow_deny and check_audit parameters from
  is_covered_localvars()


Acked-by: Steve Beattie <steve@nxnw.org>
2015-01-16 14:59:49 +01:00
Christian Boltz
7085b53583 let make coverage fail if one of the tests fail
If one of the testcases fail, this goes unnoticed in "make coverage".
This patch changes the Makefile so that test failures let
"make coverage" fail.

You can use   make COVERAGE_IGNORE_FAILURES=true coverage   to build
coverage data even if some tests fail.

Signed-off-by: Steve Beattie <steve@nxnw.org>
(which was most probably meant as an Acked-by)

Also Acked-by: <timeout> ;-)
2015-01-16 14:45:16 +01:00
Steve Beattie
28450b432e utils: fix python install for rule/ subdirectory
For reasons that are unclear, python's setuptools doesn't install
recursively from a directory, meaning that on make install, the new
Rules/Ruleset classes were not being installed. This patch causes
the rule subdirectory to be included.

Bug: https://bugs.launchpad.net/bugs/1407437

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2015-01-13 13:03:11 -08:00
Christian Boltz
f289bb509e delete unused variable in test_invalid_variable_double_definition()
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2014-12-25 15:38:20 +01:00
Christian Boltz
8b05b3ae26 delete unused functions check_include_syntax() and check_profile_syntax() in aa.py
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2014-12-24 16:54:57 +01:00
Christian Boltz
5040499d04 improve severity.py test coverage
adds some tests for severity.py and improves the test coverage to
nearly 100% (only 3 partial left).

Added tests and details (all in SeverityVarsTest):
- move writing the tunables file from setUp() into _init_tunables() for
  more flexibility (allows to specify other file content)
- test adding to a variable (+=)
- test #include
- make sure double definition of a variable fails
- make sure redefinition of non-existing variable fails

BTW: even the comment added to VARIABLE_DEFINITIONS contributes to
the coverage ;-)

severity.py passes all added tests, however I should note that including
a non-existing file is silently ignored.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
2014-12-24 15:42:05 +01:00
Christian Boltz
c4deb6a5ca 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>
2014-12-22 17:56:37 +01:00
Christian Boltz
05dd00aea8 update and cleanup usr.sbin.dovecot profile
Adds #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/

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

Acked-by: John Johansen <john.johansen@canonical.com>
2014-12-22 17:49:28 +01:00
Christian Boltz
d07249969a 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>
2014-12-22 17:41:59 +01:00
Christian Boltz
6126487638 update the mysqld profile in the extras directory to
something that works on my servers ;-)


Acked-by: John Johansen <john.johansen@canonical.com>
2014-12-22 17:36:13 +01:00
Launchpad Translations on behalf of apparmor-dev
3596cc189e Launchpad automatic translations update. 2014-12-19 05:44:14 +00:00
Christian Boltz
5af5ebc412 fix network rule description in apparmor.d.pod
Acked-by: John Johansen <john.johansen@canonical.com>
2014-12-19 02:14:26 +01:00
Steve Beattie
2273a47e26 utils: make parse() be a class method for all rule types
This patch hides raw_rule within the BaseRule class by making parse() be
a class method for all the rule types, implemented via a rule-specific
abstract method _parse() that returns a parsed Rule object.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-12-16 14:17:33 -08:00
Christian Boltz
e259b2d652 utils: use capability rule class in aa.py and cleanprof.py
This patch integrated the new capability rule class into aa.py and
cleanprof.py.

Patch changes:
  v6:
      - fix logic around same_file in cleanprofile.py that was causing
        capabilities to be deleted when they weren't covered by an
        abstraction.
  v5:
      - merge my changes into Christian's original patches
      - use CapabilityRule.parse() for parsing raw capability rules and
	getting a CapabilityRule instance back
      - cope with move of parse_modifiers back into rule/__init__.py.

Originally-by: Christian Boltz <apparmor@cboltz.de>
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-12-16 14:13:25 -08:00
Christian Boltz
c55a466dc9 utils: add tests for capability rules classes
Patch changes:
  v5:
     - merge my changes into Christian's original patches
     - update to use CapabilityRule.parse() as the entry point for
       parsing raw rules and getting a CapabilityRule instance in
       return.

Originally-by: Christian Boltz <apparmor@cboltz.de>
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-12-16 14:11:18 -08:00
Christian Boltz
e7ae4bc8e8 utils: add base and capability rule classes
This patch adds four classes - two "base" classes and two specific for
capabilities:

utils/apparmor/rule/__init__.py:

    class base_rule(object):
        Base class to handle and store a single rule

    class base_rules(object):
        Base class to handle and store a collection of rules

utils/apparmor/rule/capability.py:

    class capability_rule(base_rule):
        Class to handle and store a single capability rule

    class capability_rules(base_rules):
        Class to handle and store a collection of capability rules

Changes:
  v5:
    - flattened my changes into Christian's patches
    - pull parse_modifiers into rule/__init__.py
    - pull parse_capability into rule/capability.py
    - make CapabiltyRule.parse() be the class/static method for parsing
      raw capability rules.
    - parse_capability: renamed inlinecomment and rawrule to comment
      and raw_rule to be consistent with CapabilityRule fields.

Originally-by: Christian Boltz <apparmor@cboltz.de>
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-12-16 14:06:31 -08:00
Steve Beattie
5125fca9bc Adjust version in preparation for 2.10/3.0 development. 2014-12-16 13:45:47 -08:00
987 changed files with 25920 additions and 4718 deletions

View File

@@ -18,13 +18,13 @@ parser/*.8
parser/*.7.html
parser/*.5.html
parser/*.8.html
parser/common
parser/apparmor_parser
parser/libapparmor_re/regexp.cc
parser/techdoc.aux
parser/techdoc.log
parser/techdoc.pdf
parser/techdoc.toc
profiles/apparmor.d/local/*.*
libraries/libapparmor/Makefile
libraries/libapparmor/Makefile.in
libraries/libapparmor/aclocal.m4
@@ -41,20 +41,32 @@ 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/af_protos.h
libraries/libapparmor/src/change_hat.lo
libraries/libapparmor/src/features.lo
libraries/libapparmor/src/grammar.lo
libraries/libapparmor/src/kernel.lo
libraries/libapparmor/src/kernel_interface.lo
libraries/libapparmor/src/libaalogparse.lo
libraries/libapparmor/src/libimmunix_warning.lo
libraries/libapparmor/src/policy_cache.lo
libraries/libapparmor/src/private.lo
libraries/libapparmor/src/scanner.lo
libraries/libapparmor/src/libapparmor.pc
libraries/libapparmor/src/libapparmor.la
libraries/libapparmor/src/libimmunix.la
libraries/libapparmor/src/grammar.c
@@ -70,12 +82,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/pm_to_blib
libraries/libapparmor/swig/python/LibAppArmor.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/ruby/Makefile
libraries/libapparmor/swig/ruby/Makefile.in
libraries/libapparmor/testsuite/.deps
@@ -94,10 +114,6 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
libraries/libapparmor/testsuite/test_multi/out
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
@@ -165,4 +181,5 @@ tests/regression/apparmor/unix_fd_server
tests/regression/apparmor/unlink
tests/regression/apparmor/xattrs
tests/regression/apparmor/coredump
./utils/apparmor/__pycache__
**/__pycache__/
*.orig

View File

@@ -1,8 +1,12 @@
#
#
OVERRIDE_TARBALL=yes
.PHONY: all
all:
@echo "*** See README for information how to build AppArmor ***"
exit 1
include common/Make.rules
COMMONDIR=common
include ${COMMONDIR}/Make.rules
DIRS=parser \
profiles \
@@ -14,7 +18,7 @@ DIRS=parser \
#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
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.10
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"

View File

@@ -17,13 +17,7 @@ NAME:=apache2-mod_apparmor
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
include $(COMMONDIR)/Make.rules
TARGET:=mod_apparmor.so
MANPAGES=mod_apparmor.8
@@ -92,9 +86,9 @@ install: ${TARGET} ${MANPAGES}
make install_manpages DESTDIR=${DESTDIR}
.PHONY: clean
clean: _clean
clean: pod_clean
rm -rf .libs
rm -f *.la *.lo *.so *.o *.slo Make.rules
rm -f *.la *.lo *.so *.o *.slo
.PHONY: check
check: check_pod_files

View File

@@ -137,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_con, *aa_mode, *aa_hat;
char *aa_label, *aa_mode, *aa_hat;
const char *vhost_uri;
debug_dump_uri(r);
@@ -201,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_con, &aa_mode);
aa_ret = aa_getcon(&aa_label, &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_con, aa_mode);
"AA checks: aa_getcon result is '%s', mode '%s'", aa_label, aa_mode);
/* TODO: use libapparmor get hat_name fn here once it is implemented */
aa_hat = strstr(aa_con, "//");
aa_hat = strstr(aa_label, "//");
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
aa_hat += 2; /* skip "//" */
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
@@ -226,7 +226,7 @@ aa_enter_hat(request_rec *r)
scfg->hat_name);
}
}
free(aa_con);
free(aa_label);
}
return OK;

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 documenation for more
E<lt>LocationMatchE<gt> directive (see the Apache documentation 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

View File

@@ -16,15 +16,8 @@
NAME=pam_apparmor
all:
COMMONDIR=../../common/
MAKE_RULES=common/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
include $(COMMONDIR)/Make.rules
ifdef USE_SYSTEM
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
@@ -60,7 +53,7 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
AA_LDLIBS = -lapparmor
endif
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
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
@@ -87,7 +80,5 @@ install: $(NAME).so
install -m 555 $(NAME).so $(SECDIR)/
.PHONY: clean
clean: ${MAKE_RULES}
clean:
rm -f core core.* *.so *.o *.s *.a *~
rm -f ${NAME}-*.tar.gz Make.rules

View File

@@ -111,6 +111,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
sizeof(magic_token));
if (retval < 0) {
pam_syslog(pamh, LOG_ERR, "Can't read from /dev/urandom\n");
close(fd);
return PAM_PERM_DENIED;
}
} while ((magic_token == 0) || (retval != sizeof(magic_token)));

View File

@@ -17,13 +17,7 @@ NAME = tomcat_apparmor
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
include $(COMMONDIR)/Make.rules
LIB = lib
CATALINA_HOME = /usr/share/tomcat5
@@ -34,7 +28,6 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install: $(SPECFILE)
install:
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -17,13 +17,7 @@ NAME = tomcat_apparmor
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
include $(COMMONDIR)/Make.rules
LIB = lib
CATALINA_HOME = /usr/share/tomcat55
@@ -34,7 +28,6 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install: $(SPECFILE)
install:
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2010 Canonical, Ltd.
# Copyright (C) 2010-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
@@ -15,17 +15,21 @@
# 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 the SHASS
# product.
# Make.rules - common make targets and variables for building AppArmor
#
# NOTES:
# - 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
# 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
DISTRIBUTION=AppArmor
VERSION=$(shell cat common/Version)
VERSION=$(shell cat $(COMMONDIR)/Version)
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
@@ -41,106 +45,8 @@ define nl
endef
# 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, python2 python3)
endif
@@ -155,24 +61,18 @@ pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
.PHONY: version
.SILENT: version
version:
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
echo $(VERSION)
.PHONY: repo_version
.SILENT: repo_version
repo_version:
$(value REPO_VERSION_CMD)
.PHONY: build_dir
build_dir: $(BUILDRPMSUBDIRS)
$(BUILDRPMSUBDIRS):
mkdir -p $(BUILDRPMSUBDIRS)
.PHONY: _clean
.SILENT: _clean
_clean:
-[ -z "${NAME}" ] || rm -f ${NAME}-${VERSION}-*.tar.gz
.PHONY: pod_clean
ifndef VERBOSE
.SILENT: pod_clean
endif
pod_clean:
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
# =====================
@@ -182,7 +82,7 @@ _clean:
# =====================
# 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)
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' | LC_ALL=C sort)
.PHONY: list_capabilities
list_capabilities: /usr/include/linux/capability.h
@@ -198,7 +98,7 @@ list_capabilities: /usr/include/linux/capability.h
# 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_UNSPEC PF_UNIX
FILTER_FAMILIES=PF_UNIX
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')

View File

@@ -1 +1 @@
2.9.2
2.10.3

View File

@@ -24,13 +24,7 @@ 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
include $(COMMONDIR)/Make.rules
MODDIR = Immunix
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
@@ -56,9 +50,8 @@ install:
ifndef VERBOSE
.SILENT: clean
endif
clean: _clean
clean: pod_clean
rm -f core core.* *.o *.s *.a *~
rm -f Make.rules
rm -rf staging/ build/
.PHONY: check

Binary file not shown.

View File

@@ -4,22 +4,4 @@ SRCDIR = src
SUBDIRS = doc src include swig testsuite
REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
fi)
REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
/usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
fi)
RELEASE_DIR = $(NAME)-$(VERSION)-${REPO_VERSION}
SVNTARBALL = $(NAME)-$(VERSION)-${REPO_VERSION}.tar.gz
SVNTAR = /bin/tar czvp -h --exclude .svn --exclude CVS --exclude .cvsignore --exclude ${SVNTARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
distball: clean
rm -rf $(RELEASE_DIR)
svn export -r $(REPO_VERSION) $(REPO_URL) $(RELEASE_DIR)
$(SVNTAR) -f $(SVNTARBALL) $(RELEASE_DIR)
rm -rf $(RELEASE_DIR)
EXTRA_DIST = AUTHORS ChangeLog COPYING.LGPL INSTALL NEWS README

View File

@@ -38,6 +38,6 @@ aclocal
echo "Running autoconf"
autoconf --force
echo "Running libtoolize"
libtoolize --automake -c
libtoolize --automake -c --force
echo "Running automake"
automake -ac

View File

@@ -14,6 +14,14 @@ PKG_PROG_PKG_CONFIG
AC_PATH_PROG([SWIG], [swig])
AC_MSG_CHECKING([whether the libapparmor debug output should be enabled])
AC_ARG_ENABLE([debug_output],
[AS_HELP_STRING([--enable-debug-output], [generate the libapparmor debug output [[default=no]]])],
[AC_MSG_RESULT([$enableval])],
[enable_debug_output=no]
[AC_MSG_RESULT([$enable_debug_output])])
AS_IF([test "$enable_debug_output" = "yes"], [AC_DEFINE([ENABLE_DEBUG_OUTPUT], [1], [debug output])])
AC_MSG_CHECKING([whether the libapparmor man pages should be generated])
AC_ARG_ENABLE(man_pages,
[AS_HELP_STRING([--enable-man-pages], [generate the libapparmor man pages [[default=yes]]])],
@@ -71,14 +79,19 @@ AM_CONDITIONAL(HAVE_PERL, test x$with_perl = xyes)
AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h stdint.h)
AC_CHECK_HEADERS(unistd.h stdint.h syslog.h)
AC_CHECK_FUNCS(asprintf)
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
AM_PROG_CC_C_O
AC_C_CONST
AM_PROG_LIBTOOL
AC_PROG_CC_C99
if test "$ac_cv_prog_cc_c99" = "no"; then
AC_MSG_ERROR([C99 mode is required to build libapparmor])
fi
AC_OUTPUT(
Makefile
doc/Makefile

View File

@@ -5,14 +5,14 @@ PODCHECKER = podchecker
if ENABLE_MAN_PAGES
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3
PODS = $(subst .2,.pod,$(man_MANS))
PODS = $(subst .2,.pod,$(man_MANS)) $(subst .3,.pod,$(man_MANS))
EXTRA_DIST = $(man_MANS) $(PODS)
## delete man pages at maintainer-clean
BUILT_SOURCES = $(man_MANS)
## delete man pages at make clean
CLEANFILES = $(man_MANS)
%.2: %.pod
$(PODCHECKER) -warnings -warnings $<
@@ -23,4 +23,13 @@ BUILT_SOURCES = $(man_MANS)
--stderr \
$< > $@
%.3: %.pod
$(PODCHECKER) -warnings -warnings $<
$(POD2MAN) \
--section=3 \
--release="AppArmor $(VERSION)" \
--center="AppArmor" \
--stderr \
$< > $@
endif

View File

@@ -40,16 +40,15 @@ An AppArmor profile applies to an executable program; if a portion of
the program needs different access permissions than other portions,
the program can "change profile" to a different profile. To change into a
new profile, it can use the aa_change_profile() function to do so. It passes
in a pointer to the I<profile> to transition to. Transitioning to another
profile via aa_change_profile() is permanent and the process is not
permitted to transition back to the original profile. Confined programs
wanting to use aa_change_profile() need to have rules permitting changing
to the named profile. See apparmor.d(8) for details.
in a pointer to the I<profile> to transition to. Confined programs wanting to
use aa_change_profile() need to have rules permitting changing to the named
profile. See apparmor.d(8) for details.
If a program wants to return out of the current profile to the
original profile, it should use aa_change_hat(2) instead.
original profile, it may use aa_change_hat(2). Otherwise, the two profiles must
have rules permitting changing between the two profiles.
Open file descriptors are not remediated after a call to aa_change_profile()
Open file descriptors may not be remediated after a call to aa_change_profile()
so the calling program must close(2) open file descriptors to ensure they
are not available after calling aa_change_profile(). As aa_change_profile()
is typically used just before execve(2), you may want to use open(2) or
@@ -84,8 +83,8 @@ Insufficient kernel memory was available.
=item B<EPERM>
The calling application is not confined by apparmor, or the no_new_privs
bit is set.
The calling application is confined by apparmor and the no_new_privs bit is
set.
=item B<EACCES>

View File

@@ -0,0 +1,148 @@
# 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 adhere 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 - an opaque object representing a set of AppArmor kernel features
aa_features_new - create a new aa_features object based on a path
aa_features_new_from_string - create a new aa_features object based on a string
aa_features_new_from_kernel - create a new aa_features object based on the current kernel
aa_features_ref - increments the ref count of an aa_features object
aa_features_unref - decrements the ref count and frees the aa_features object when 0
aa_features_write_to_file - write a string representation of an aa_features object to a file
aa_features_is_equal - equality test for two aa_features objects
aa_features_supports - provides aa_features object support status
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_features aa_features;>
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
B<int aa_features_new_from_kernel(aa_features **features);>
B<aa_features *aa_features_ref(aa_features *features);>
B<void aa_features_unref(aa_features *features);>
B<int aa_features_write_to_file(aa_features *features, int dirfd, const char *path);>
B<bool aa_features_is_equal(aa_features *features1, aa_features *features2);>
B<bool aa_features_supports(aa_features *features, const char *str);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_features> object contains information about the AppArmor features
supported by a kernel. The feature support information is based upon the files
AppArmor represents in securityfs, which is typically found at
/sys/kernel/security/apparmor/features/. That information may be parsed and
turned into a string or flat file in order to represent a set of features of a
kernel that is not currently running.
The aa_features_new() function creates an I<aa_features> object based upon a
directory file descriptor and path. The I<path> can point to a file or
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. The
allocated I<features> object must be freed using aa_features_unref().
The aa_features_new_from_string() function is similar except that it accepts a
NUL-terminated string representation of the AppArmor features as the I<string>
argument. The length of the features string, not counting the NUL-terminator,
must be specified as the I<size> argument. The allocated I<features> object
must be freed using aa_features_unref().
The aa_features_new_from_kernel() function creates an I<aa_features> object
from the current running kernel. The allocated I<features> object must be freed
using aa_features_unref().
aa_features_ref() increments the reference count on the I<features> object.
aa_features_unref() decrements the reference count on the I<features> object
and releases all corresponding resources when the reference count reaches zero.
The aa_features_write_to_file() function writes a string representation of the
I<features> object to the file specified by the I<dirfd> and I<path>
combination.
aa_features_is_equal() can be used to detect if the I<features1> and
I<features2> objects are equal. The definition of equality is private to
libapparmor and may be changed in ways that do not break backward
compatibility.
The aa_features_supports() function can be used to query the I<features> object
to determine if a feature is supported. The I<str> argument should be equal to
the path, relative to the "apparmor/features/" directory of securityfs, of the
feature to query. For example, to test if policy version 6 is supported, I<str>
would be "policy/versions/v6".
=head1 RETURN VALUE
The aa_features_new() family of functions return 0 on success and I<*features>
will point to an I<aa_features> object that must be freed by
aa_features_unref(). -1 is returned on error, with errno set appropriately, and
I<*features> will be set to NULL.
aa_features_ref() returns the value of I<features>.
aa_features_write_to_file() returns 0 on success. -1 is returned on error, with
errno set appropriately.
aa_features_is_equal() returns true if I<features1> and I<features2> are equal
and false if they are not equal.
aa_features_supports() returns true if the feature represented by I<str> is
supported and false if it is not supported.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_features> family of functions that return -1 on error.
=head1 NOTES
All aa_features functions described above are present in libapparmor version
2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
openat(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -34,27 +34,38 @@ B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len, char **mode);>
B<int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);>
B<int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);>
B<int aa_gettaskcon(pid_t target, char **con, char **mode);>
B<int aa_gettaskcon(pid_t target, char **label, char **mode);>
B<int aa_getcon(char **con, char **mode);>
B<int aa_getcon(char **label, char **mode);>
B<int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);>
B<int aa_getpeercon(int fd, char **con, char **mode);>
B<int aa_getpeercon(int fd, char **label, char **mode);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_getcon function gets the current AppArmor confinement context for the
current task. The confinement context is usually just the name of the AppArmor
profile restricting the task, but it may include the profile namespace or in
some cases a set of profile names (known as a stack of profiles). The returned
string *con should be freed using free(), but the returned string *mode should
not be freed. The *con and *mode strings come from a single buffer allocation
and are separated by a NUL character.
current task. The confinement context consists of a label and a mode. The label
is usually just the name of the AppArmor profile restricting the task, but it
may include the profile namespace or in some cases a set of profile names
(known as a stack of profiles). The mode is a string that describes how the
kernel is enforcing the policy defined in the profile. Profiles loaded in
"enforce" mode will result in enforcement of the policy defined in the profile
as well as reporting policy violation attempts. Profiles in "complain" mode
will not enforce policy but instead report policy violation attempts.
Some examples of possible returned *label strings are "unconfined", "/sbin/dhclient",
and "Firefox". The string can consist of any non-NUL characters but it will be
NUL-terminated. The *label string must be freed using free().
The possible *mode strings are "enforce" and "complain". Additionally, *mode may
be NULL when *label is "unconfined". B<The *mode string must not be freed>. The
*label and *mode strings come from a single buffer allocation and are separated
by a NUL character.
The aa_gettaskcon function is like the aa_getcon function except it will work
for any arbitrary task in the system.
@@ -120,7 +131,7 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2) and
L<http://wiki.apparmor.net>.
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
aa_splitcon(3) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -0,0 +1,162 @@
# 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 adhere 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_kernel_interface - an opaque object representing the AppArmor kernel interface for policy loading, replacing, and removing
aa_kernel_interface_new - create a new aa_kernel_interface object from an optional path
aa_kernel_interface_ref - increments the ref count of an aa_kernel_interface object
aa_kernel_interface_unref - decrements the ref count and frees the aa_kernel_interface object when 0
aa_kernel_interface_load_policy - load a policy from a buffer into the kernel
aa_kernel_interface_load_policy_from_file - load a policy from a file into the kernel
aa_kernel_interface_load_policy_from_fd - load a policy from a file descriptor into the kernel
aa_kernel_interface_replace_policy - replace a policy in the kernel with a policy from a buffer
aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel with a policy from a file
aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel with a policy from a file descriptor
aa_kernel_interface_remove_policy - remove a policy from the kernel
aa_kernel_interface_write_policy - write a policy to a file descriptor
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_kernel_interface aa_kernel_interface;>
B<int aa_kernel_interface_new(aa_kernel_interface **kernel_interface, aa_features *kernel_features, const char *apparmorfs);>
B<aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);>
B<void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);>
B<int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
B<int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
B<int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
B<int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
B<int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
B<int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
B<int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface, const char *fqname);>
B<int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_kernel_interface> object contains information about the AppArmor
kernel interface for policy loading, replacing, and removing.
The aa_kernel_interface_new() function creates an I<aa_kernel_interface> object
based on an optional I<aa_features> object and an optional path to the apparmor
directory of securityfs, which is typically found at
"/sys/kernel/security/apparmor/". If I<kernel_features> is NULL, then the
features of the current kernel are used. When specifying a valid
I<kernel_features> object, it must be compatible with the features of the
currently running kernel. If I<apparmorfs> is NULL, then the default location
is used. The allocated I<kernel_interface> object must be freed using
aa_kernel_interface_unref().
aa_kernel_interface_ref() increments the reference count on the
I<kernel_interface> object.
aa_kernel_interface_unref() decrements the reference count on the
I<kernel_interface> object and releases all corresponding resources when the
reference count reaches zero.
The aa_kernel_interface_load() family of functions load a policy into the
kernel. The operation will fail if a policy of the same name is already loaded.
Use the aa_kernel_interface_replace() family of functions if you wish to
replace a previously loaded policy with a new policy of the same name. The
aa_kernel_interface_replace() functions can also be used to load a policy that
does not correspond to a previously loaded policy.
When loading or replacing from a buffer, the I<buffer> will contain binary
data. The I<size> argument must specify the size of the I<buffer> argument.
When loading or replacing from a file, the I<dirfd> and I<path> combination are
used to specify the location of the file. See the openat(2) man page for
examples of I<dirfd> and I<path>.
It is also possible to load or replace from a file descriptor specified by the
I<fd> argument. The file must be open for reading and the file offset must be
set appropriately.
The aa_kernel_interface_remove_policy() function can be used to unload a
previously loaded policy. The fully qualified policy name must be specified
with the I<fqname> argument. The operation will fail if a policy matching
I<fqname> is not found.
The aa_kernel_interface_write_policy() function allows for a policy, which is
stored in I<buffer> and consists of I<size> bytes, to be written to a file
descriptor. The I<fd> must be open for writing and the file offset must be set
appropriately.
=head1 RETURN VALUE
The aa_kernel_interface_new() function returns 0 on success and
I<*kernel_interface> will point to an I<aa_kernel_interface> object that must
be freed by aa_kernel_interface_unref(). -1 is returned on error, with errno
set appropriately, and I<*kernel_interface> will be set to NULL.
aa_kernel_features_ref() returns the value of I<kernel_features>.
The aa_kernel_interface_load() family of functions, the
aa_kernel_interface_replace() family of functions,
aa_kernel_interface_remove(), and aa_kernel_interface_write_policy()
return 0 on success. -1 is returned on error, with errno set appropriately.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_kernel_interface> family of functions that return -1 on error.
=head1 NOTES
All aa_kernel_interface functions described above are present in libapparmor
version 2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_features(3), openat(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -0,0 +1,125 @@
# 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 adhere 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_policy_cache - an opaque object representing an AppArmor policy cache
aa_policy_cache_new - create a new aa_policy_cache object from a path
aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
aa_policy_cache_remove - removes all policy cache files under a path
aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<typedef struct aa_policy_cache aa_policy_cache;>
B<int aa_policy_cache_new(aa_policy_cache **policy_cache, aa_features *kernel_features, int dirfd, const char *path, uint16_t max_caches);>
B<aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);>
B<void aa_policy_cache_unref(aa_policy_cache *policy_cache);>
B<int aa_policy_cache_remove(int dirfd, const char *path);>
B<int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The I<aa_policy_cache> object contains information about a set of AppArmor
policy cache files. The policy cache files are the binary representation of a
human-readable AppArmor profile. The binary representation is the form that is
loaded into the kernel.
The aa_policy_cache_new() function creates an I<aa_policy_cache> object based
upon a directory file descriptor and path. The I<path> must point to a
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. If
I<kernel_features> is NULL, then the features of the current kernel are used.
When specifying a valid I<kernel_features> object, it must be the compatible
with the features of the kernel of interest. The value of I<max_caches> should
be equal to the number of caches that should be allowed before old caches are
automatically reaped. The definition of what is considered to be an old cache
is private to libapparmor. Specifying 0 means that no new caches should be
created and only existing, valid caches may be used. Specifying UINT16_MAX
means that a new cache may be created and that the reaping of old caches is
disabled. The allocated I<aa_policy_cache> object must be freed using
aa_policy_cache_unref().
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
object.
aa_policy_cache_unref() decrements the reference count on the I<policy_cache>
object and releases all corresponding resources when the reference count
reaches zero.
The aa_policy_cache_remove() function deletes all of the policy cache files
based upon a directory file descriptor and path. The I<path> must point to a
directory. See the openat(2) man page for examples of I<dirfd> and I<path>.
The aa_policy_cache_replace_all() function can be used to perform a policy
replacement of all of the cache policies in the cache directory represented by
the I<policy_cache> object. If I<kernel_interface> is NULL, then the current
kernel interface is used. When specifying a valid I<kernel_interface> object,
it must be the interface of the currently running kernel.
=head1 RETURN VALUE
The aa_policy_cache_new() function returns 0 on success and I<*policy_cache>
will point to an I<aa_policy_cache> object that must be freed by
aa_policy_cache_unref(). -1 is returned on error, with errno set appropriately,
and I<*policy_cache> will be set to NULL.
aa_policy_cache_ref() returns the value of I<policy_cache>.
aa_policy_cache_remove() and aa_policy_cache_replace_all() return 0 on success.
-1 is returned on error, with errno set appropriately.
=head1 ERRORS
The errno value will be set according to the underlying error in the
I<aa_policy_cache> family of functions that return -1 on error.
=head1 NOTES
All aa_policy_cache functions described above are present in libapparmor
version 2.10 and newer.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_features(3), aa_kernel_interface(3), openat(2) and
L<http://wiki.apparmor.net>.
=cut

View File

@@ -0,0 +1,137 @@
# 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 adhere 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_query_label - query access permission associated with a label
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_query_label((uint32_t mask, char *query, size_t size,
int *allowed, int *audited);>
B<int aa_query_file_path((uint32_t mask, const char *label, size_t label_len,
const char *path, int *allowed, int *audited);>
B<int aa_query_file_path_len((uint32_t mask, const char *label,
size_t label_len, const char *path, size_t path_len,
int *allowed, int *audited);>
B<int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);>
B<int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_query_label function fetches the current permissions granted by the
specified I<label> in the I<query> string.
The query is a raw binary formatted query, containing the label and
permission query to make. The returned I<allowed> and I<audited> values are
interpreted boolean values, simple stating whether the query is allowed and
if it is audited.
The mask of the query string is a bit mask of permissions to query and is
class type dependent (see AA_CLASS_xxx) entries in I<sys/apparmor.h>.
The format of the query string is also dependent on the B<AA_CLASS> and as
such the the aa_query_xxx helper functions should usually be used instead
of directly using I<aa_query_label>. If directly using the interface the
I<query> string is required to have a header of B<AA_QUERY_CMD_LABEL_SIZE>
that will be used by I<aa_query_label>.
The B<aa_query_file_path> and B<aa_query_file_path_len> functions are helper
function that assemble a properly formatted file path query for the
B<aa_query_label> function. The I<label> is a valid apparmor label as
returned by I<aa_splitcon> with I<label_len> being the length of the I<label>.
The I<path> is any valid filesystem path to query permissions for. For the
B<aa_query_file_path_len> variant the I<path_len> parameter specifies the
number of bytes in the I<path> to use as part of the query.
The B<aa_query_link_path> and B<aa_query_link_path_len> functions are helper
functions that assemble a properly formatted link path query for the
B<aa_query_label> function. The I<link_len> and I<target_len> parameters
specify the number of bytes in the I<link> and I<target> to use as part of
the query.
=head1 RETURN VALUE
On success 0 is returned, and the I<allowed> and I<audited> parameters
contain a boolean value of 0 not allowed/audited or 1 allowed/audited. On
error, -1 is returned, and errno(3) is set appropriately.
=head1 ERRORS
=over 4
=item B<EINVAL>
The requested I<mask> is empty.
The I<size> of the query is E<lt> the query B<AA_QUER?Y_CMD_LABEL_SIZE>
The apparmor kernel module is not loaded or the he kernel interface access
interface is not available
=item B<ENOMEM>
Insufficient memory was available.
=item B<EACCES>
Access to the specified I<label> or query interface was denied.
=item B<ENOENT>
The specified I<label> does not exist or is not visible.
=item B<ERANGE>
The confinement data is too large to fit in the supplied buffer.
=back
=head1 NOTES
The label permissions returned are only valid for the time of the
query and can change at any point in the future.
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_getcon(2), aa_splitcon(3)
and L<http://wiki.apparmor.net>.
=cut

View File

@@ -0,0 +1,72 @@
# 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 adhere 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_splitcon - split the confinement context into a label and mode
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<char *aa_splitcon(char *con, char **mode);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_splitcon() function splits a confinement context into separate label
and mode strings. The @con string is modified so that the label portion is NUL
terminated. The enforcement mode is also NUL terminated and the parenthesis
surrounding the mode are removed. If @mode is non-NULL, it will point to the
first character in the enforcement mode string on success.
The Linux kernel's /proc/E<lt>PIDE<gt>/attr/current interface appends a
trailing newline character to AppArmor contexts that are read from that file.
If @con contains a single trailing newline character, it will be stripped by
aa_splitcon() prior to all other processing.
=head1 RETURN VALUE
Returns a pointer to the first character in the label string. NULL is returned
on error.
=head1 EXAMPLE
Context Label Mode
----------------------------- ------------------ -------
unconfined unconfined NULL
unconfined\n unconfined NULL
/bin/ping (enforce) /bin/ping enforce
/bin/ping (enforce)\n /bin/ping enforce
/usr/sbin/rsyslogd (complain) /usr/sbin/rsyslogd complain
=head1 BUGS
None known. If you find any, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
aa_getcon(2) and L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,3 +1,3 @@
apparmor_hdrdir = $(includedir)/sys
apparmor_hdr_HEADERS = apparmor.h
apparmor_hdr_HEADERS = apparmor.h apparmor_private.h

View File

@@ -18,6 +18,7 @@
#ifndef _SYS_APPARMOR_H
#define _SYS_APPARMOR_H 1
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -26,10 +27,31 @@ __BEGIN_DECLS
/*
* Class of public mediation types in the AppArmor policy db
*/
#define AA_CLASS_FILE 2
#define AA_CLASS_DBUS 32
/* Permission flags for the AA_CLASS_FILE mediation class */
#define AA_MAY_EXEC (1 << 0)
#define AA_MAY_WRITE (1 << 1)
#define AA_MAY_READ (1 << 2)
#define AA_MAY_APPEND (1 << 3)
#define AA_MAY_CREATE (1 << 4)
#define AA_MAY_DELETE (1 << 5)
#define AA_MAY_OPEN (1 << 6)
#define AA_MAY_RENAME (1 << 7)
#define AA_MAY_SETATTR (1 << 8)
#define AA_MAY_GETATTR (1 << 9)
#define AA_MAY_SETCRED (1 << 10)
#define AA_MAY_GETCRED (1 << 11)
#define AA_MAY_CHMOD (1 << 12)
#define AA_MAY_CHOWN (1 << 13)
#define AA_MAY_LOCK 0x8000
#define AA_EXEC_MMAP 0x10000
#define AA_MAY_LINK 0x40000
#define AA_MAY_ONEXEC 0x20000000
#define AA_MAY_CHANGE_PROFILE 0x40000000
/* Permission flags for the AA_CLASS_DBUS mediation class */
#define AA_DBUS_SEND (1 << 1)
#define AA_DBUS_RECEIVE (1 << 2)
@@ -57,16 +79,18 @@ extern int aa_change_onexec(const char *profile);
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
extern char *aa_splitcon(char *con, char **mode);
/* Protypes for introspecting task confinement
* Please see the aa_getcon(2) manpage for information
*/
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
extern int aa_getcon(char **con, char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **label,
char **mode);
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
extern int aa_getcon(char **label, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
extern int aa_getpeercon(int fd, char **con, char **mode);
extern int aa_getpeercon(int fd, char **label, char **mode);
/* A NUL character is used to separate the query command prefix string from the
* rest of the query string. The query command sizes intentionally include the
@@ -77,6 +101,17 @@ extern int aa_getpeercon(int fd, char **con, char **mode);
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
int *audit);
extern int aa_query_file_path_len(uint32_t mask, const char *label,
size_t label_len, const char *path,
size_t path_len, int *allowed, int *audited);
extern int aa_query_file_path(uint32_t mask, const char *label,
const char *path, int *allowed, int *audited);
extern int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);
extern int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);
#define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
#define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
@@ -102,6 +137,58 @@ extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
#define aa_change_hat_vargs(T, X...) \
(aa_change_hat_vargs)(T, __macroarg_counter(X), X)
typedef struct aa_features aa_features;
extern int aa_features_new(aa_features **features, int dirfd, const char *path);
extern int aa_features_new_from_string(aa_features **features,
const char *string, size_t size);
extern int aa_features_new_from_kernel(aa_features **features);
extern aa_features *aa_features_ref(aa_features *features);
extern void aa_features_unref(aa_features *features);
extern int aa_features_write_to_file(aa_features *features,
int dirfd, const char *path);
extern bool aa_features_is_equal(aa_features *features1,
aa_features *features2);
extern bool aa_features_supports(aa_features *features, const char *str);
typedef struct aa_kernel_interface aa_kernel_interface;
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
aa_features *kernel_features,
const char *apparmorfs);
extern aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);
extern void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);
extern int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
const char *buffer, size_t size);
extern int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
int dirfd,
const char *path);
extern int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface,
int fd);
extern int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
const char *buffer, size_t size);
extern int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
int dirfd,
const char *path);
extern int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface,
int fd);
extern int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
const char *fqname);
extern int aa_kernel_interface_write_policy(int fd, const char *buffer,
size_t size);
typedef struct aa_policy_cache aa_policy_cache;
extern int aa_policy_cache_new(aa_policy_cache **policy_cache,
aa_features *kernel_features,
int dirfd, const char *path,
uint16_t max_caches);
extern aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
extern void aa_policy_cache_unref(aa_policy_cache *policy_cache);
extern int aa_policy_cache_remove(int dirfd, const char *path);
extern int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
aa_kernel_interface *kernel_interface);
__END_DECLS
#endif /* sys/apparmor.h */

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library 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/>.
*/
#ifndef _SYS_APPARMOR_PRIVATE_H
#define _SYS_APPARMOR_PRIVATE_H 1
#include <stdio.h>
#include <sys/stat.h>
__BEGIN_DECLS
int _aa_is_blacklisted(const char *name);
void _aa_autofree(void *p);
void _aa_autoclose(int *fd);
void _aa_autofclose(FILE **f);
int _aa_asprintf(char **strp, const char *fmt, ...);
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
int (* cb)(int, const char *, struct stat *, void *));
__END_DECLS
#endif /* sys/apparmor_private.h */

View File

@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
# For more information, see:
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
#
AA_LIB_CURRENT = 3
AA_LIB_REVISION = 1
AA_LIB_AGE = 2
AA_LIB_CURRENT = 4
AA_LIB_REVISION = 0
AA_LIB_AGE = 3
SUFFIXES = .pc.in .pc
@@ -46,9 +46,9 @@ af_protos.h: /usr/include/netinet/in.h
LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" $< > $@
lib_LTLIBRARIES = libapparmor.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
@@ -63,7 +63,15 @@ CLEANFILES = libapparmor.pc
tst_aalogmisc_SOURCES = tst_aalogmisc.c
tst_aalogmisc_LDADD = .libs/libapparmor.a
check_PROGRAMS = tst_aalogmisc
tst_features_SOURCES = tst_features.c
tst_features_LDADD = .libs/libapparmor.a
tst_kernel_SOURCES = tst_kernel.c
tst_kernel_LDADD = .libs/libapparmor.a
tst_kernel_LDFLAGS = -pthread
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
TESTS = $(check_PROGRAMS)
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 2014
* 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 <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/apparmor.h>
#include "private.h"
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
#define STRING_SIZE 8192
struct aa_features {
unsigned int ref_count;
char string[STRING_SIZE];
};
struct features_struct {
char *buffer;
int size;
char *pos;
};
struct component {
const char *str;
size_t len;
};
static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
{
va_list args;
int i, remaining = fst->size - (fst->pos - fst->buffer);
if (remaining < 0) {
errno = EINVAL;
PERROR("Invalid features buffer offset\n");
return -1;
}
va_start(args, fmt);
i = vsnprintf(fst->pos, remaining, fmt, args);
va_end(args);
if (i < 0) {
errno = EIO;
PERROR("Failed to write to features buffer\n");
return -1;
} else if (i >= remaining) {
errno = ENOBUFS;
PERROR("Feature buffer full.");
return -1;
}
fst->pos += i;
return 0;
}
/* load_features_file - opens and reads a file into @buffer and then NUL-terminates @buffer
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
* @path: name of the file
* @buffer: the buffer to read the features file into (will be NUL-terminated on success)
* @size: the size of @buffer
*
* Returns: The number of bytes copied into @buffer on success (not counting
* the NUL-terminator), else -1 and errno is set. Note that @size must be
* larger than the size of the file or -1 will be returned with errno set to
* ENOBUFS indicating that @buffer was not large enough to contain all of the
* file contents.
*/
static int load_features_file(int dirfd, const char *path,
char *buffer, size_t size)
{
autoclose int file = -1;
char *pos = buffer;
ssize_t len;
file = openat(dirfd, path, O_RDONLY);
if (file < 0) {
PDEBUG("Could not open '%s'\n", path);
return -1;
}
PDEBUG("Opened features \"%s\"\n", path);
if (!size) {
errno = ENOBUFS;
return -1;
}
/* Save room for a NUL-terminator at the end of @buffer */
size--;
do {
len = read(file, pos, size);
if (len > 0) {
size -= len;
pos += len;
}
} while (len > 0 && size);
/**
* Possible error conditions:
* - len == -1: read failed and errno is already set so return -1
* - len > 0: read() never returned 0 (EOF) meaning that @buffer was
* too small to contain all of the file contents so set
* errno to ENOBUFS and return -1
*/
if (len) {
if (len > 0)
errno = ENOBUFS;
PDEBUG("Error reading features file '%s': %m\n", path);
return -1;
}
/* NUL-terminate @buffer */
*pos = 0;
return pos - buffer;
}
static int features_dir_cb(int dirfd, const char *name, struct stat *st,
void *data)
{
struct features_struct *fst = (struct features_struct *) data;
/* skip dot files and files with no name */
if (*name == '.' || !strlen(name))
return 0;
if (features_snprintf(fst, "%s {", name) == -1)
return -1;
if (S_ISREG(st->st_mode)) {
int len;
int remaining = fst->size - (fst->pos - fst->buffer);
len = load_features_file(dirfd, name, fst->pos, remaining);
if (len < 0)
return -1;
fst->pos += len;
} else if (S_ISDIR(st->st_mode)) {
if (_aa_dirat_for_each(dirfd, name, fst, features_dir_cb))
return -1;
}
if (features_snprintf(fst, "}\n") == -1)
return -1;
return 0;
}
static int load_features_dir(int dirfd, const char *path,
char *buffer, int size)
{
struct features_struct fst = { buffer, size, buffer };
if (_aa_dirat_for_each(dirfd, path, &fst, features_dir_cb)) {
PDEBUG("Failed evaluating %s\n", path);
return -1;
}
return 0;
}
static bool islbrace(int c)
{
return c == '{';
}
static bool isrbrace(int c)
{
return c == '}';
}
static bool isnul(int c)
{
return c == '\0';
}
static bool isbrace(int c)
{
return islbrace(c) || isrbrace(c);
}
static bool isbrace_or_nul(int c)
{
return isbrace(c) || isnul(c);
}
static bool isbrace_space_or_nul(int c)
{
return isbrace(c) || isspace(c) || isnul(c);
}
static size_t tokenize_path_components(const char *str,
struct component *components,
size_t max_components)
{
size_t i = 0;
memset(components, 0, sizeof(*components) * max_components);
if (!str)
return 0;
while (*str && i < max_components) {
const char *fwdslash = strchrnul(str, '/');
/* Save the token if it is not "/" */
if (fwdslash != str) {
components[i].str = str;
components[i].len = fwdslash - str;
i++;
}
if (isnul(*fwdslash))
break;
str = fwdslash + 1;
}
return i;
}
/**
* walk_one - walk one component of a features string
* @str: a pointer to the current position in a features string
* @component: the component to walk
* @is_top_level: true if component is a top-level component
*
* Imagine a features string such as:
*
* "feat1 { subfeat1.1 subfeat1.2 } feat2 { subfeat2.1 { subfeat2.1.1 } }"
*
* You want to know if "feat2/subfeat2.1/subfeat2.8" is valid. It will take 3
* invocations of this function to determine if that string is valid. On the
* first call, *@str will point to the beginning of the features string,
* component->str will be "feat2", and is_top_level will be true since feat2 is
* a top level feature. The function will return true and *@str will now point
* at the the left brace after "feat2" in the features string. You can call
* this function again with component->str being equal to "subfeat2.1" and it
* will return true and *@str will now point at the left brace after
* "subfeat2.1" in the features string. A third call to the function, with
* component->str equal to "subfeat2.8", will return false and *@str will not
* be changed.
*
* Returns true if the walk was successful and false otherwise. If the walk was
* successful, *@str will point to the first encountered brace after the walk.
* If the walk was unsuccessful, *@str is not updated.
*/
static bool walk_one(const char **str, const struct component *component,
bool is_top_level)
{
const char *cur;
uint32_t brace_count = 0;
size_t i = 0;
/* NULL pointers and empty strings are not accepted */
if (!str || !*str || !component || !component->str || !component->len)
return false;
cur = *str;
/**
* If @component is not top-level, the first character in the string to
* search MUST be '{'
*/
if (!is_top_level) {
if (!islbrace(*cur))
return false;
cur++;
}
/**
* This loop tries to find the @component in *@str. When this loops
* completes, cur will either point one character past the end of the
* matched @component or to the NUL terminator of *@str.
*/
while(!isnul(*cur) && i < component->len) {
if (!isascii(*cur)) {
/* Only ASCII is expected */
return false;
} else if (islbrace(*cur)) {
/* There's a limit to the number of left braces */
if (brace_count == UINT32_MAX)
return false;
brace_count++;
} else if (isrbrace(*cur)) {
/* Check for unexpected right braces */
if (brace_count == 0)
return false;
brace_count--;
}
/**
* Move to the next character in @component if we're not inside
* of braces and we have a character match
*/
if (brace_count == 0 && *cur == component->str[i])
i++;
else
i = 0;
cur++;
}
/* Return false if a full match was not found */
if (i != component->len) {
return false;
} else if (!isbrace_space_or_nul(*cur))
return false;
/**
* This loop eats up valid (ASCII) characters until a brace or NUL
* character is found so that *@str is properly set to call back into
* this function
*/
while (!isbrace_or_nul(*cur)) {
if (!isascii(*cur))
return false;
cur++;
}
*str = cur;
return true;
}
/**
* aa_features_new - create a new aa_features object based on a path
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: path to a features file or directory
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new(aa_features **features, int dirfd, const char *path)
{
struct stat stat_file;
aa_features *f;
int retval;
*features = NULL;
if (fstatat(dirfd, path, &stat_file, 0) == -1)
return -1;
f = calloc(1, sizeof(*f));
if (!f) {
errno = ENOMEM;
return -1;
}
aa_features_ref(f);
retval = S_ISDIR(stat_file.st_mode) ?
load_features_dir(dirfd, path, f->string, STRING_SIZE) :
load_features_file(dirfd, path, f->string, STRING_SIZE);
if (retval == -1) {
int save = errno;
aa_features_unref(f);
errno = save;
return -1;
}
*features = f;
return 0;
}
/**
* aa_features_new_from_string - create a new aa_features object based on a string
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
* @string: a NUL-terminated string representation of features
* @size: the size of @string, not counting the NUL-terminator
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new_from_string(aa_features **features,
const char *string, size_t size)
{
aa_features *f;
*features = NULL;
/* Require size to be less than STRING_SIZE so there's room for a NUL */
if (size >= STRING_SIZE)
return ENOBUFS;
f = calloc(1, sizeof(*f));
if (!f) {
errno = ENOMEM;
return -1;
}
aa_features_ref(f);
memcpy(f->string, string, size);
f->string[size] = '\0';
*features = f;
return 0;
}
/**
* aa_features_new_from_kernel - create a new aa_features object based on the current kernel
* @features: will point to the address of an allocated and initialized
* aa_features object upon success
*
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
* NULL
*/
int aa_features_new_from_kernel(aa_features **features)
{
return aa_features_new(features, -1, FEATURES_FILE);
}
/**
* aa_features_ref - increments the ref count of an aa_features object
* @features: the features
*
* Returns: the features
*/
aa_features *aa_features_ref(aa_features *features)
{
atomic_inc(&features->ref_count);
return features;
}
/**
* aa_features_unref - decrements the ref count and frees the aa_features object when 0
* @features: the features (can be NULL)
*/
void aa_features_unref(aa_features *features)
{
if (features && atomic_dec_and_test(&features->ref_count))
free(features);
}
/**
* aa_features_write_to_file - write a string representation of an aa_features object to a file
* @features: the features
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: the path to write to
*
* Returns: 0 on success, -1 on error with errno set
*/
int aa_features_write_to_file(aa_features *features,
int dirfd, const char *path)
{
autoclose int fd = -1;
size_t size;
ssize_t retval;
char *string;
fd = openat(dirfd, path,
O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1)
return -1;
string = features->string;
size = strlen(string);
do {
retval = write(fd, string, size);
if (retval == -1)
return -1;
size -= retval;
string += retval;
} while (size);
return 0;
}
/**
* aa_features_is_equal - equality test for two aa_features objects
* @features1: the first features (can be NULL)
* @features2: the second features (can be NULL)
*
* Returns: true if they're equal, false if they're not or either are NULL
*/
bool aa_features_is_equal(aa_features *features1, aa_features *features2)
{
return features1 && features2 &&
strcmp(features1->string, features2->string) == 0;
}
/**
* aa_features_supports - provides aa_features object support status
* @features: the features
* @str: the string representation of a feature to check
*
* Example @str values are "dbus/mask/send", "caps/mask/audit_read", and
* "policy/versions/v7".
*
* Returns: a bool specifying the support status of @str feature
*/
bool aa_features_supports(aa_features *features, const char *str)
{
const char *features_string = features->string;
struct component components[32];
size_t i, num_components;
/* Empty strings are not accepted. Neither are leading '/' chars. */
if (!str || str[0] == '/')
return false;
/**
* Break @str into an array of components. For example,
* "mount/mask/mount" would turn into { "mount", 5 } as the first
* component, { "mask", 4 } as the second, and { "mount", 5 } as the
* third
*/
num_components = tokenize_path_components(str, components,
sizeof(components) / sizeof(*components));
/* At least one valid token is required */
if (!num_components)
return false;
/* Ensure that all components are valid and found */
for (i = 0; i < num_components; i++) {
if (!walk_one(&features_string, &components[i], i == 0))
return false;
}
return true;
}

View File

@@ -166,9 +166,15 @@ aa_record_event_type lookup_aa_event(unsigned int type)
%token TOK_SYSLOG_KERNEL
%token TOK_SYSLOG_USER
%destructor { free($$); } TOK_QUOTED_STRING TOK_ID TOK_MODE TOK_DMESG_STAMP
%destructor { free($$); } TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE TOK_TIME
%destructor { free($$); } TOK_HEXSTRING TOK_TYPE_OTHER TOK_MSG_REST
%destructor { free($$); } TOK_IP_ADDR
%%
log_message: audit_type
| dmesg_type
| syslog_type
| audit_dispatch
;
@@ -199,6 +205,10 @@ other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
}
;
dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
;
syslog_type:
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
@@ -418,7 +428,7 @@ _parse_yacc(char *str)
int parser_return;
ret_record = NULL;
ret_record = (aa_log_record *) malloc(sizeof(aa_log_record));
ret_record = malloc(sizeof(aa_log_record));
_init_log_record(ret_record);

View File

@@ -0,0 +1,982 @@
/*
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
* Copyright 2009-2010 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library 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/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <mntent.h>
#include <inttypes.h>
#include <pthread.h>
#include <sys/apparmor.h>
#include "private.h"
/* some non-Linux systems do not define a static value */
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
#define symbol_version(real, name, version) \
__asm__ (".symver " #real "," #name "@" #version)
#define default_symbol_version(real, name, version) \
__asm__ (".symver " #real "," #name "@@" #version)
#define UNCONFINED "unconfined"
#define UNCONFINED_SIZE strlen(UNCONFINED)
/**
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
* @mnt: returns buffer with the mountpoint string
*
* Returns: 0 on success else -1 on error
*
* NOTE: this function only supports versions of apparmor using securityfs
*/
int aa_find_mountpoint(char **mnt)
{
struct stat statbuf;
struct mntent *mntpt;
FILE *mntfile;
int rc = -1;
if (!mnt) {
errno = EINVAL;
return -1;
}
mntfile = setmntent("/proc/mounts", "r");
if (!mntfile)
return -1;
while ((mntpt = getmntent(mntfile))) {
char *proposed = NULL;
if (strcmp(mntpt->mnt_type, "securityfs") != 0)
continue;
if (asprintf(&proposed, "%s/apparmor", mntpt->mnt_dir) < 0)
/* ENOMEM */
break;
if (stat(proposed, &statbuf) == 0) {
*mnt = proposed;
rc = 0;
break;
}
free(proposed);
}
endmntent(mntfile);
if (rc == -1)
errno = ENOENT;
return rc;
}
/**
* aa_is_enabled - determine if apparmor is enabled
*
* Returns: 1 if enabled else reason it is not, or 0 on error
*
* ENOSYS - no indication apparmor is present in the system
* ENOENT - enabled but interface could not be found
* ECANCELED - disabled at boot
* ENOMEM - out of memory
*/
int aa_is_enabled(void)
{
int serrno, fd, rc, size;
char buffer[2];
char *mnt;
/* if the interface mountpoint is available apparmor is enabled */
rc = aa_find_mountpoint(&mnt);
if (rc == 0) {
free(mnt);
return 1;
}
/* determine why the interface mountpoint isn't available */
fd = open("/sys/module/apparmor/parameters/enabled", O_RDONLY);
if (fd == -1) {
if (errno == ENOENT)
errno = ENOSYS;
return 0;
}
size = read(fd, &buffer, 2);
serrno = errno;
close(fd);
errno = serrno;
if (size > 0) {
if (buffer[0] == 'Y')
errno = ENOENT;
else
errno = ECANCELED;
}
return 0;
}
static inline pid_t aa_gettid(void)
{
#ifdef SYS_gettid
return syscall(SYS_gettid);
#else
return getpid();
#endif
}
static char *procattr_path(pid_t pid, const char *attr)
{
char *path = NULL;
if (asprintf(&path, "/proc/%d/attr/%s", pid, attr) > 0)
return path;
return NULL;
}
/**
* parse_unconfined - check for the unconfined label
* @con: the confinement context
* @size: size of the confinement context (not including the NUL terminator)
*
* Returns: True if the con is the unconfined label or false otherwise
*/
static bool parse_unconfined(char *con, int size)
{
return size == UNCONFINED_SIZE &&
strncmp(con, UNCONFINED, UNCONFINED_SIZE) == 0;
}
/**
* splitcon - split the confinement context into a label and mode
* @con: the confinement context
* @size: size of the confinement context (not including the NUL terminator)
* @strip_newline: true if a trailing newline character should be stripped
* @mode: if non-NULL and a mode is present, will point to mode string in @con
* on success
*
* Modifies the @con string to split it into separate label and mode strings.
* If @strip_newline is true and @con contains a single trailing newline, it
* will be stripped on success (it will not be stripped on error). The @mode
* argument is optional. If @mode is NULL, @con will still be split between the
* label and mode (if present) but @mode will not be set.
*
* Returns: a pointer to the label string or NULL on error
*/
static char *splitcon(char *con, int size, bool strip_newline, char **mode)
{
char *label = NULL;
char *mode_str = NULL;
char *newline = NULL;
if (size == 0)
goto out;
if (strip_newline && con[size - 1] == '\n') {
newline = &con[size - 1];
size--;
}
if (parse_unconfined(con, size)) {
label = con;
goto out;
}
if (size > 3 && con[size - 1] == ')') {
int pos = size - 2;
while (pos > 0 && !(con[pos] == ' ' && con[pos + 1] == '('))
pos--;
if (pos > 0) {
con[pos] = 0; /* overwrite ' ' */
con[size - 1] = 0; /* overwrite trailing ) */
mode_str = &con[pos + 2]; /* skip '(' */
label = con;
}
}
out:
if (label && strip_newline && newline)
*newline = 0; /* overwrite '\n', if requested, on success */
if (mode)
*mode = mode_str;
return label;
}
/**
* aa_splitcon - split the confinement context into a label and mode
* @con: the confinement context
* @mode: if non-NULL and a mode is present, will point to mode string in @con
* on success
*
* Modifies the @con string to split it into separate label and mode strings. A
* single trailing newline character will be stripped from @con, if found. The
* @mode argument is optional. If @mode is NULL, @con will still be split
* between the label and mode (if present) but @mode will not be set.
*
* Returns: a pointer to the label string or NULL on error
*/
char *aa_splitcon(char *con, char **mode)
{
return splitcon(con, strlen(con), true, mode);
}
/**
* aa_getprocattr_raw - get the contents of @attr for @tid into @buf
* @tid: tid of task to query
* @attr: which /proc/<tid>/attr/<attr> to query
* @buf: buffer to store the result in
* @len: size of the buffer
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
*
* Returns: size of data read or -1 on error, and sets errno
*/
int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode)
{
int rc = -1;
int fd, ret;
char *tmp = NULL;
int size = 0;
if (!buf || len <= 0) {
errno = EINVAL;
goto out;
}
tmp = procattr_path(tid, attr);
if (!tmp)
goto out;
fd = open(tmp, O_RDONLY);
free(tmp);
if (fd == -1) {
goto out;
}
tmp = buf;
do {
ret = read(fd, tmp, len);
if (ret <= 0)
break;
tmp += ret;
size += ret;
len -= ret;
if (len < 0) {
errno = ERANGE;
goto out2;
}
} while (ret > 0);
if (ret < 0) {
int saved;
if (ret != -1) {
errno = EPROTO;
}
saved = errno;
(void)close(fd);
errno = saved;
goto out;
} else if (size > 0 && buf[size - 1] != 0) {
/* check for null termination */
if (buf[size - 1] != '\n') {
if (len == 0) {
errno = ERANGE;
goto out2;
} else {
buf[size] = 0;
size++;
}
}
if (splitcon(buf, size, true, mode) != buf) {
errno = EINVAL;
goto out2;
}
}
rc = size;
out2:
(void)close(fd);
out:
return rc;
}
#define INITIAL_GUESS_SIZE 128
/**
* aa_getprocattr - get the contents of @attr for @tid into @label and @mode
* @tid: tid of task to query
* @attr: which /proc/<tid>/attr/<attr> to query
* @label: allocated buffer the label is stored in
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: size of data read or -1 on error, and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode)
{
int rc, size = INITIAL_GUESS_SIZE/2;
char *buffer = NULL;
if (!label) {
errno = EINVAL;
return -1;
}
do {
char *tmp;
size <<= 1;
tmp = realloc(buffer, size);
if (!tmp) {
free(buffer);
return -1;
}
buffer = tmp;
memset(buffer, 0, size);
rc = aa_getprocattr_raw(tid, attr, buffer, size, mode);
} while (rc == -1 && errno == ERANGE);
if (rc == -1) {
free(buffer);
*label = NULL;
if (mode)
*mode = NULL;
} else
*label = buffer;
return rc;
}
static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
{
int rc = -1;
int fd, ret;
char *ctl = NULL;
if (!buf) {
errno = EINVAL;
goto out;
}
ctl = procattr_path(tid, attr);
if (!ctl)
goto out;
fd = open(ctl, O_WRONLY);
if (fd == -1) {
goto out;
}
ret = write(fd, buf, len);
if (ret != len) {
int saved;
if (ret != -1) {
errno = EPROTO;
}
saved = errno;
(void)close(fd);
errno = saved;
goto out;
}
rc = 0;
(void)close(fd);
out:
if (ctl) {
free(ctl);
}
return rc;
}
int aa_change_hat(const char *subprofile, unsigned long token)
{
int rc = -1;
int len = 0;
char *buf = NULL;
const char *fmt = "changehat %016lx^%s";
/* both may not be null */
if (!(token || subprofile)) {
errno = EINVAL;
goto out;
}
if (subprofile && strnlen(subprofile, PATH_MAX + 1) > PATH_MAX) {
errno = EPROTO;
goto out;
}
len = asprintf(&buf, fmt, token, subprofile ? subprofile : "");
if (len < 0) {
goto out;
}
rc = setprocattr(aa_gettid(), "current", buf, len);
out:
if (buf) {
/* clear local copy of magic token before freeing */
memset(buf, '\0', len);
free(buf);
}
return rc;
}
/* original change_hat interface */
int __change_hat(char *subprofile, unsigned int token)
{
return aa_change_hat(subprofile, (unsigned long) token);
}
int aa_change_profile(const char *profile)
{
char *buf = NULL;
int len;
int rc;
if (!profile) {
errno = EINVAL;
return -1;
}
len = asprintf(&buf, "changeprofile %s", profile);
if (len < 0)
return -1;
rc = setprocattr(aa_gettid(), "current", buf, len);
free(buf);
return rc;
}
int aa_change_onexec(const char *profile)
{
char *buf = NULL;
int len;
int rc;
if (!profile) {
errno = EINVAL;
return -1;
}
len = asprintf(&buf, "exec %s", profile);
if (len < 0)
return -1;
rc = setprocattr(aa_gettid(), "exec", buf, len);
free(buf);
return rc;
}
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
int aa_change_hatv(const char *subprofiles[], unsigned long token)
{
int size, totallen = 0, hatcount = 0;
int rc = -1;
const char **hats;
char *pos, *buf = NULL;
const char *cmd = "changehat";
/* both may not be null */
if (!token && !(subprofiles && *subprofiles)) {
errno = EINVAL;
goto out;
}
/* validate hat lengths and while we are at it count how many and
* mem required */
if (subprofiles) {
for (hats = subprofiles; *hats; hats++) {
int len = strnlen(*hats, PATH_MAX + 1);
if (len > PATH_MAX) {
errno = EPROTO;
goto out;
}
totallen += len + 1;
hatcount++;
}
}
/* allocate size of cmd + space + token + ^ + vector of hats */
size = strlen(cmd) + 18 + totallen + 1;
buf = malloc(size);
if (!buf) {
goto out;
}
/* setup command string which is of the form
* changehat <token>^hat1\0hat2\0hat3\0..\0
*/
sprintf(buf, "%s %016lx^", cmd, token);
pos = buf + strlen(buf);
if (subprofiles) {
for (hats = subprofiles; *hats; hats++) {
strcpy(pos, *hats);
pos += strlen(*hats) + 1;
}
} else
/* step pos past trailing \0 */
pos++;
rc = setprocattr(aa_gettid(), "current", buf, pos - buf);
out:
if (buf) {
/* clear local copy of magic token before freeing */
memset(buf, '\0', size);
free(buf);
}
return rc;
}
/**
* change_hat_vargs - change_hatv but passing the hats as fn arguments
* @token: the magic token
* @nhat: the number of hats being passed in the arguments
* ...: a argument list of const char * being passed
*
* change_hat_vargs can be called directly but it is meant to be called
* through its macro wrapper of the same name. Which automatically
* fills in the nhats arguments based on the number of parameters
* passed.
* to call change_hat_vargs direction do
* (change_hat_vargs)(token, nhats, hat1, hat2...)
*/
int (aa_change_hat_vargs)(unsigned long token, int nhats, ...)
{
va_list ap;
const char *argv[nhats+1];
int i;
va_start(ap, nhats);
for (i = 0; i < nhats ; i++) {
argv[i] = va_arg(ap, char *);
}
argv[nhats] = NULL;
va_end(ap);
return aa_change_hatv(argv, token);
}
/**
* aa_gettaskcon - get the confinement context for task @target in an allocated buffer
* @target: task to query
* @label: pointer to returned buffer with the label
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context or -1 on error and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_gettaskcon(pid_t target, char **label, char **mode)
{
return aa_getprocattr(target, "current", label, mode);
}
/**
* aa_getcon - get the confinement context for current task in an allocated buffer
* @label: pointer to return buffer with the label if successful
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context or -1 on error and sets errno
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and may > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getcon(char **label, char **mode)
{
return aa_gettaskcon(aa_gettid(), label, mode);
}
#ifndef SO_PEERSEC
#define SO_PEERSEC 31
#endif
/**
* aa_getpeercon_raw - get the confinement context of the socket's peer (other end)
* @fd: socket to get peer confinement context for
* @buf: buffer to store the result in
* @len: initially contains size of the buffer, returns size of data read
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
*
* Returns: length of confinement context including null termination or -1 on
* error if errno == ERANGE then @len will hold the size needed
*/
int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode)
{
socklen_t optlen = *len;
int rc;
if (optlen <= 0 || buf == NULL) {
errno = EINVAL;
return -1;
}
rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &optlen);
if (rc == -1 || optlen <= 0)
goto out;
/* check for null termination */
if (buf[optlen - 1] != 0) {
if (optlen < *len) {
buf[optlen] = 0;
optlen++;
} else {
/* buf needs to be bigger by 1 */
rc = -1;
errno = ERANGE;
optlen++;
goto out;
}
}
if (splitcon(buf, optlen - 1, false, mode) != buf) {
rc = -1;
errno = EINVAL;
goto out;
}
rc = optlen;
out:
*len = optlen;
return rc;
}
/**
* aa_getpeercon - get the confinement context of the socket's peer (other end)
* @fd: socket to get peer confinement context for
* @label: pointer to allocated buffer with the label
* @mode: if non-NULL and a mode is present, will point to mode string in @label
*
* Returns: length of confinement context including null termination or -1 on error
*
* Guarantees that @label and @mode are null terminated. The length returned
* is for all data including both @label and @mode, and maybe > than
* strlen(@label) even if @mode is NULL
*
* Caller is responsible for freeing the buffer returned in @label. @mode is
* always contained within @label's buffer and so NEVER do free(@mode)
*/
int aa_getpeercon(int fd, char **label, char **mode)
{
int rc, last_size, size = INITIAL_GUESS_SIZE;
char *buffer = NULL;
if (!label) {
errno = EINVAL;
return -1;
}
do {
char *tmp;
last_size = size;
tmp = realloc(buffer, size);
if (!tmp) {
free(buffer);
return -1;
}
buffer = tmp;
memset(buffer, 0, size);
rc = aa_getpeercon_raw(fd, buffer, &size, mode);
/* size should contain actual size needed if errno == ERANGE */
} while (rc == -1 && errno == ERANGE && size > last_size);
if (rc == -1) {
free(buffer);
*label = NULL;
if (mode)
*mode = NULL;
size = -1;
} else
*label = buffer;
return size;
}
static pthread_once_t aafs_access_control = PTHREAD_ONCE_INIT;
static char *aafs_access = NULL;
static void aafs_access_init_once(void)
{
char *aafs;
int ret;
ret = aa_find_mountpoint(&aafs);
if (ret < 0)
return;
ret = asprintf(&aafs_access, "%s/.access", aafs);
if (ret < 0)
aafs_access = NULL;
free(aafs);
}
/* "allow 0x00000000\ndeny 0x00000000\naudit 0x00000000\nquiet 0x00000000\n" */
#define QUERY_LABEL_REPLY_LEN 67
/**
* aa_query_label - query the access(es) of a label
* @mask: permission bits to query
* @query: binary query string, must be offset by AA_QUERY_CMD_LABEL_SIZE
* @size: size of the query string must include AA_QUERY_CMD_LABEL_SIZE
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int query_label(uint32_t mask, char *query, size_t size, int *allowed,
int *audited)
{
char buf[QUERY_LABEL_REPLY_LEN];
uint32_t allow, deny, audit, quiet;
int fd, ret, saved;
if (!mask || size <= AA_QUERY_CMD_LABEL_SIZE) {
errno = EINVAL;
return -1;
}
ret = pthread_once(&aafs_access_control, aafs_access_init_once);
if (ret) {
errno = EINVAL;
return -1;
} else if (!aafs_access) {
errno = ENOMEM;
return -1;
}
fd = open(aafs_access, O_RDWR);
if (fd == -1) {
if (errno == ENOENT)
errno = EPROTONOSUPPORT;
return -1;
}
memcpy(query, AA_QUERY_CMD_LABEL, AA_QUERY_CMD_LABEL_SIZE);
errno = 0;
ret = write(fd, query, size);
if (ret != size) {
if (ret >= 0)
errno = EPROTO;
/* IMPORTANT: This is the only valid error path that can have
* errno set to ENOENT. It indicates that the subject label
* could not be found by the kernel.
*/
(void)close(fd);
return -1;
}
ret = read(fd, buf, QUERY_LABEL_REPLY_LEN);
saved = errno;
(void)close(fd);
errno = saved;
if (ret != QUERY_LABEL_REPLY_LEN) {
errno = EPROTO;
return -1;
}
ret = sscanf(buf, "allow 0x%8" SCNx32 "\n"
"deny 0x%8" SCNx32 "\n"
"audit 0x%8" SCNx32 "\n"
"quiet 0x%8" SCNx32 "\n",
&allow, &deny, &audit, &quiet);
if (ret != 4) {
errno = EPROTONOSUPPORT;
return -1;
}
*allowed = mask & ~(allow & ~deny) ? 0 : 1;
if (!(*allowed))
audit = 0xFFFFFFFF;
*audited = mask & ~(audit & ~quiet) ? 0 : 1;
return 0;
}
/* export multiple aa_query_label symbols to compensate for downstream
* releases with differing symbol versions. */
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
/**
* aa_query_file_path_len - query access permissions for a file @path
* @mask: permission bits to query
* @label: apparmor label
* @label_len: length of @label (does not include any terminating nul byte)
* @path: file path to query permissions for
* @path_len: length of @path (does not include any terminating nul byte)
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_file_path_len(uint32_t mask, const char *label, size_t label_len,
const char *path, size_t path_len, int *allowed,
int *audited)
{
autofree char *query = NULL;
/* + 1 for null separator */
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + path_len;
query = malloc(size + 1);
if (!query)
return -1;
memcpy(query + AA_QUERY_CMD_LABEL_SIZE, label, label_len);
/* null separator */
query[AA_QUERY_CMD_LABEL_SIZE + label_len] = 0;
query[AA_QUERY_CMD_LABEL_SIZE + label_len + 1] = AA_CLASS_FILE;
memcpy(query + AA_QUERY_CMD_LABEL_SIZE + label_len + 2, path, path_len);
return aa_query_label(mask, query, size , allowed, audited);
}
/**
* aa_query_file_path - query access permissions for a file @path
* @mask: permission bits to query
* @label: apparmor label
* @path: file path to query permissions for
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_file_path(uint32_t mask, const char *label, const char *path,
int *allowed, int *audited)
{
return aa_query_file_path_len(mask, label, strlen(label), path,
strlen(path), allowed, audited);
}
/**
* aa_query_link_path_len - query access permissions for a hard link @link
* @label: apparmor label
* @label_len: length of @label (does not include any terminating nul byte)
* @target: file path that hard link will point to
* @target_len: length of @target (does not include any terminating nul byte)
* @link: file path of hard link
* @link_len: length of @link (does not include any terminating nul byte)
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited)
{
autofree char *query = NULL;
int rc;
/* + 1 for null separators */
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + target_len +
1 + link_len;
size_t pos = AA_QUERY_CMD_LABEL_SIZE;
query = malloc(size);
if (!query)
return -1;
memcpy(query + pos, label, label_len);
/* null separator */
pos += label_len;
query[pos] = 0;
query[++pos] = AA_CLASS_FILE;
memcpy(query + pos + 1, link, link_len);
/* The kernel does the query in two parts we could similate this
* doing the following, however as long as policy is compiled
* correctly this isn't requied, and it requires and extra round
* trip to the kernel and adds a race on policy replacement between
* the two queries.
*
rc = aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
if (rc || !*allowed)
return rc;
*/
pos += 1 + link_len;
query[pos] = 0;
memcpy(query + pos + 1, target, target_len);
return aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
}
/**
* aa_query_link_path - query access permissions for a hard link @link
* @label: apparmor label
* @target: file path that hard link will point to
* @link: file path of hard link
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
* @audited: upon successful return, will be 1 if query should be audited and 0
* if not
*
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
* ENOENT, the subject label in the query string is unknown to the
* kernel.
*/
int aa_query_link_path(const char *label, const char *target, const char *link,
int *allowed, int *audited)
{
return aa_query_link_path_len(label, strlen(label), target,
strlen(target), link, strlen(link),
allowed, audited);
}

File diff suppressed because it is too large Load Diff

View File

@@ -51,3 +51,49 @@ APPARMOR_2.9 {
local:
*;
} APPARMOR_1.1;
APPARMOR_2.10 {
global:
aa_query_file_path;
aa_query_file_path_len;
aa_query_link_path;
aa_query_link_path_len;
aa_features_new;
aa_features_new_from_string;
aa_features_new_from_kernel;
aa_features_ref;
aa_features_unref;
aa_features_write_to_file;
aa_features_is_equal;
aa_features_supports;
aa_kernel_interface_new;
aa_kernel_interface_ref;
aa_kernel_interface_unref;
aa_kernel_interface_load_policy;
aa_kernel_interface_load_policy_from_file;
aa_kernel_interface_load_policy_from_fd;
aa_kernel_interface_replace_policy;
aa_kernel_interface_replace_policy_from_file;
aa_kernel_interface_replace_policy_from_fd;
aa_kernel_interface_remove_policy;
aa_kernel_interface_write_policy;
aa_policy_cache_new;
aa_policy_cache_ref;
aa_policy_cache_unref;
aa_policy_cache_remove;
aa_policy_cache_replace_all;
aa_splitcon;
local:
*;
} APPARMOR_2.9;
PRIVATE {
global:
_aa_is_blacklisted;
_aa_autofree;
_aa_autoclose;
_aa_autofclose;
_aa_dirat_for_each;
local:
*;
};

View File

@@ -0,0 +1,277 @@
/*
* Copyright (c) 2014
* 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/apparmor.h>
#include "private.h"
#define CACHE_FEATURES_FILE ".features"
struct aa_policy_cache {
unsigned int ref_count;
aa_features *features;
aa_features *kernel_features;
int dirfd;
};
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
void *data unused)
{
/* remove regular files */
if (S_ISREG(st->st_mode))
return unlinkat(dirfd, path, 0);
/* do nothing with other file types */
return 0;
}
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
{
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
return -1;
if (aa_features_write_to_file(features, policy_cache->dirfd,
CACHE_FEATURES_FILE) == -1)
return -1;
aa_features_unref(policy_cache->features);
policy_cache->features = aa_features_ref(features);
return 0;
}
static int init_cache_features(aa_policy_cache *policy_cache,
aa_features *kernel_features, bool create)
{
bool call_create_cache = false;
if (aa_features_new(&policy_cache->features, policy_cache->dirfd,
CACHE_FEATURES_FILE)) {
policy_cache->features = NULL;
if (!create || errno != ENOENT)
return -1;
/* The cache directory needs to be created */
call_create_cache = true;
} else if (!aa_features_is_equal(policy_cache->features,
kernel_features)) {
if (!create) {
errno = EEXIST;
return -1;
}
/* The cache directory needs to be refreshed */
call_create_cache = true;
}
return call_create_cache ?
create_cache(policy_cache, kernel_features) : 0;
}
struct replace_all_cb_data {
aa_policy_cache *policy_cache;
aa_kernel_interface *kernel_interface;
};
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
void *cb_data)
{
int retval = 0;
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
struct replace_all_cb_data *data;
data = (struct replace_all_cb_data *) cb_data;
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
data->policy_cache->dirfd,
name);
}
return retval;
}
/**
* aa_policy_cache_new - create a new aa_policy_cache object from a path
* @policy_cache: will point to the address of an allocated and initialized
* aa_policy_cache_new object upon success
* @kernel_features: features representing a kernel (may be NULL if you want to
* use the features of the currently running kernel)
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: path to the policy cache
* @max_caches: The maximum number of policy caches, one for each unique set of
* kernel features, before older caches are auto-reaped. 0 means
* that no new caches should be created (existing, valid caches
* will be used) and auto-reaping is disabled. UINT16_MAX means
* that a cache can be created and auto-reaping is disabled.
*
* Returns: 0 on success, -1 on error with errno set and *@policy_cache
* pointing to NULL
*/
int aa_policy_cache_new(aa_policy_cache **policy_cache,
aa_features *kernel_features,
int dirfd, const char *path, uint16_t max_caches)
{
aa_policy_cache *pc;
bool create = max_caches > 0;
*policy_cache = NULL;
if (!path) {
errno = EINVAL;
return -1;
}
if (max_caches > 1) {
errno = ENOTSUP;
return -1;
}
pc = calloc(1, sizeof(*pc));
if (!pc) {
errno = ENOMEM;
return -1;
}
pc->dirfd = -1;
aa_policy_cache_ref(pc);
open:
pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (pc->dirfd < 0) {
int save;
/* does the dir exist? */
if (create && errno == ENOENT) {
if (mkdirat(dirfd, path, 0700) == 0)
goto open;
PERROR("Can't create cache directory '%s': %m\n", path);
} else if (create) {
PERROR("Can't update cache directory '%s': %m\n", path);
} else {
PDEBUG("Cache directory '%s' does not exist\n", path);
}
save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
if (kernel_features) {
aa_features_ref(kernel_features);
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
int save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
pc->kernel_features = kernel_features;
if (init_cache_features(pc, kernel_features, create)) {
int save = errno;
aa_policy_cache_unref(pc);
errno = save;
return -1;
}
*policy_cache = pc;
return 0;
}
/**
* aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
* @policy_cache: the policy_cache
*
* Returns: the policy_cache
*/
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
{
atomic_inc(&policy_cache->ref_count);
return policy_cache;
}
/**
* aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
* @policy_cache: the policy_cache (can be NULL)
*/
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
{
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
aa_features_unref(policy_cache->features);
aa_features_unref(policy_cache->kernel_features);
if (policy_cache->dirfd != -1)
close(policy_cache->dirfd);
free(policy_cache);
}
}
/**
* aa_policy_cache_remove - removes all policy cache files under a path
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
* @path: the path to a policy cache directory
*
* Returns: 0 on success, -1 on error with errno set
*/
int aa_policy_cache_remove(int dirfd, const char *path)
{
return _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb);
}
/**
* aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
* @policy_cache: the policy_cache
* @kernel_interface: the kernel interface to use when doing the replacement
* (may be NULL if the currently running kernel features
* were used when calling aa_policy_cache_new())
*
* Returns: 0 on success, -1 on error with errno set and features pointing to
* NULL
*/
int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
aa_kernel_interface *kernel_interface)
{
struct replace_all_cb_data cb_data;
int retval;
if (kernel_interface) {
aa_kernel_interface_ref(kernel_interface);
} else if (aa_kernel_interface_new(&kernel_interface,
policy_cache->kernel_features,
NULL) == -1) {
kernel_interface = NULL;
return -1;
}
cb_data.policy_cache = policy_cache;
cb_data.kernel_interface = kernel_interface;
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data,
replace_all_cb);
aa_kernel_interface_unref(kernel_interface);
return retval;
}

View File

@@ -0,0 +1,252 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library 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/>.
*/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "private.h"
/**
* Allow libapparmor to build on older systems where secure_getenv() is still
* named __secure_getenv(). This snippet was taken from the glibc wiki
* (https://sourceware.org/glibc/wiki/Tips_and_Tricks/secure_getenv).
*/
#ifndef HAVE_SECURE_GETENV
#ifdef HAVE___SECURE_GETENV
#define secure_getenv __secure_getenv
#else
#error neither secure_getenv nor __secure_getenv is available
#endif
#endif
struct ignored_suffix_t {
const char * text;
int len;
int silent;
};
static struct ignored_suffix_t ignored_suffixes[] = {
/* Debian packging files, which are in flux during install
should be silently ignored. */
{ ".dpkg-new", 9, 1 },
{ ".dpkg-old", 9, 1 },
{ ".dpkg-dist", 10, 1 },
{ ".dpkg-bak", 9, 1 },
/* RPM packaging files have traditionally not been silently
ignored */
{ ".rpmnew", 7, 0 },
{ ".rpmsave", 8, 0 },
/* patch file backups/conflicts */
{ ".orig", 5, 0 },
{ ".rej", 4, 0 },
/* Backup files should be mentioned */
{ "~", 1, 0 },
{ NULL, 0, 0 }
};
#define DEBUG_ENV_VAR "LIBAPPARMOR_DEBUG"
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...)
{
va_list args;
int openlog_options = 0;
if (honor_env_var && secure_getenv(DEBUG_ENV_VAR))
openlog_options |= LOG_PERROR;
openlog(ident, openlog_options, LOG_ERR);
va_start(args, fmt);
vsyslog(LOG_ERR, fmt, args);
va_end(args);
closelog();
}
void print_debug(const char *fmt, ...)
{
va_list args;
if (!secure_getenv(DEBUG_ENV_VAR))
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
void atomic_inc(unsigned int *v)
{
__sync_add_and_fetch(v, 1);
}
bool atomic_dec_and_test(unsigned int *v)
{
return __sync_sub_and_fetch(v, 1) == 0;
}
int _aa_is_blacklisted(const char *name)
{
size_t name_len = strlen(name);
struct ignored_suffix_t *suffix;
/* skip dot files and files with no name */
if (!name_len || *name == '.' || !strcmp(name, "README"))
return 1;
/* skip blacklisted suffixes */
for (suffix = ignored_suffixes; suffix->text; suffix++) {
char *found;
if ( (found = strstr((char *) name, suffix->text)) &&
found - name + suffix->len == name_len ) {
if (!suffix->silent)
return -1;
return 1;
}
}
return 0;
}
/* automaticly free allocated variables tagged with autofree on fn exit */
void _aa_autofree(void *p)
{
void **_p = (void**)p;
free(*_p);
}
void _aa_autoclose(int *fd)
{
if (*fd != -1) {
/* if close was interrupted retry */
while(close(*fd) == -1 && errno == EINTR);
*fd = -1;
}
}
void _aa_autofclose(FILE **f)
{
if (*f) {
fclose(*f);
*f = NULL;
}
}
int _aa_asprintf(char **strp, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vasprintf(strp, fmt, args);
va_end(args);
if (rc == -1)
*strp = NULL;
return rc;
}
static int dot_or_dot_dot_filter(const struct dirent *ent)
{
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
return 0;
return 1;
}
/**
* _aa_dirat_for_each: iterate over a directory calling cb for each entry
* @dirfd: already opened directory
* @name: name of the directory (NOT NULL)
* @data: data pointer to pass to the callback fn (MAY BE NULL)
* @cb: the callback to pass entry too (NOT NULL)
*
* Iterate over the entries in a directory calling cb for each entry.
* The directory to iterate is determined by a combination of @dirfd and
* @name.
*
* See the openat section of the open(2) man page for details on valid @dirfd
* and @name combinations. This function does accept AT_FDCWD as @dirfd if
* @name should be considered relative to the current working directory.
*
* Pass "." for @name if @dirfd is the directory to iterate over.
*
* The cb function is called with the DIR in use and the name of the
* file in that directory. If the file is to be opened it should
* use the openat, fstatat, and related fns.
*
* Returns: 0 on success, else -1 and errno is set to the error code
*/
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
int (* cb)(int, const char *, struct stat *, void *))
{
autofree struct dirent **namelist = NULL;
autoclose int cb_dirfd = -1;
int i, num_dirs, rc;
if (!cb || !name) {
errno = EINVAL;
return -1;
}
cb_dirfd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
if (cb_dirfd == -1) {
PDEBUG("could not open directory '%s': %m\n", name);
return -1;
}
num_dirs = scandirat(cb_dirfd, ".", &namelist,
dot_or_dot_dot_filter, NULL);
if (num_dirs == -1) {
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
return -1;
}
for (rc = 0, i = 0; i < num_dirs; i++) {
/* Must cycle through all dirs so that each one is autofreed */
autofree struct dirent *dir = namelist[i];
struct stat my_stat;
if (rc)
continue;
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
rc = -1;
continue;
}
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
PDEBUG("dir_for_each callback failed for '%s'\n",
dir->d_name);
rc = -1;
continue;
}
}
return rc;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2014 Canonical Ltd.
*
* The libapparmor library is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* This library 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/>.
*/
#ifndef _AA_PRIVATE_H
#define _AA_PRIVATE_H 1
#include <stdbool.h>
#include <sys/apparmor_private.h>
#define autofree __attribute((cleanup(_aa_autofree)))
#define autoclose __attribute((cleanup(_aa_autoclose)))
#define autofclose __attribute((cleanup(_aa_autofclose)))
#define unused __attribute__ ((unused))
#define asprintf _aa_asprintf
#if ENABLE_DEBUG_OUTPUT
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
#define PDEBUG(fmt, args...) print_debug("libapparmor: " fmt, ## args)
#else /* ENABLE_DEBUG_OUTPUT */
#define PERROR(fmt, args...) print_error(false, "libapparmor", fmt, ## args)
#define PDEBUG(fmt, args...) /* do nothing */
#endif /* ENABLE_DEBUG_OUTPUT */
#define MY_TEST(statement, error) \
if (!(statement)) { \
fprintf(stderr, "FAIL: %s\n", error); \
rc = 1; \
}
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...);
void print_debug(const char *fmt, ...);
void atomic_inc(unsigned int *v);
bool atomic_dec_and_test(unsigned int *v);
#endif /* _AA_PRIVATE_H */

View File

@@ -178,7 +178,7 @@ syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(
hhmmss {digit}{2}{colon}{digit}{2}{colon}{digit}{2}
timezone ({plus}|{minus}){digit}{2}{colon}{digit}{2}
syslog_time {hhmmss}({period}{digits})?{timezone}?
syslog_hostname [[:alnum:]_-]+
syslog_hostname [[:alnum:]._-]+
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
%x single_quoted_string
@@ -355,6 +355,7 @@ yy_flex_debug = 0;
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_TIME); }
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
{dmesg_timestamp} { yylval->t_str = strdup(yytext); return(TOK_DMESG_STAMP); }
. { /* ignore any non-matched input */ BEGIN(unknown_message); yyless(0); }

View File

@@ -20,13 +20,7 @@
#include <stdio.h>
#include <aalogparse.h>
#include "parser.h"
#define MY_TEST(statement, error) \
if (!(statement)) { \
fprintf(stderr, "FAIL: %s\n", error); \
rc = 1; \
}
#include "private.h"
int main(void)
{
@@ -40,19 +34,25 @@ int main(void)
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
MY_TEST(retstr, "basic allocation");
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
free(retstr);
retstr = hex_to_string("61");
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
free(retstr);
retstr = hex_to_string("");
MY_TEST(strcmp(retstr, "") == 0, "empty string");
free(retstr);
/* ipproto_to_string() tests */
retstr = ipproto_to_string((unsigned) 99999);
MY_TEST(strcmp(retstr, "unknown(99999)") == 0, "invalid protocol test");
free(retstr);
retstr = ipproto_to_string((unsigned) 6);
MY_TEST(strcmp(retstr, "tcp") == 0, "protocol=tcp");
free(retstr);
return rc;
}

View File

@@ -0,0 +1,247 @@
/*
* 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 <stdio.h>
#include <string.h>
#include "private.h"
#include "features.c"
static int test_tokenize_path_components(void)
{
struct component components[32];
size_t max = sizeof(components) / sizeof(*components);
size_t num;
int rc = 0;
num = tokenize_path_components(NULL, components, max);
MY_TEST(num == 0, "basic NULL test");
num = tokenize_path_components("", components, max);
MY_TEST(num == 0, "basic empty string test");
num = tokenize_path_components("a", components, 0);
MY_TEST(num == 0, "basic empty array test");
num = tokenize_path_components("a", components, 1);
MY_TEST(num == 1, "one component full test (num)");
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
"one component full test (components[0])");
num = tokenize_path_components("a/b", components, 2);
MY_TEST(num == 2, "two component full test (num)");
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
"two component full test (components[0])");
MY_TEST(!strncmp(components[1].str, "b", components[0].len),
"two component full test (components[1])");
num = tokenize_path_components("a/b/c", components, 1);
MY_TEST(num == 1, "not enough components full test (num)");
MY_TEST(!strncmp(components[0].str, "a/b/c", components[0].len),
"not enough components full test (components[0])");
num = tokenize_path_components("/", components, max);
MY_TEST(num == 0, "no valid components #1 (num)");
num = tokenize_path_components("////////", components, max);
MY_TEST(num == 0, "no valid components #2 (num)");
num = tokenize_path_components("////////////foo////", components, max);
MY_TEST(num == 1, "many invalid components (num)");
MY_TEST(!strncmp(components[0].str, "foo", components[0].len),
"many invalid components (components[0])");
num = tokenize_path_components("file", components, max);
MY_TEST(num == 1, "file (num)");
MY_TEST(!strncmp(components[0].str, "file", components[0].len),
"file (components[0])");
num = tokenize_path_components("/policy///versions//v7/", components, max);
MY_TEST(num == 3, "v7 (num)");
MY_TEST(!strncmp(components[0].str, "policy", components[0].len),
"v7 (components[0])");
MY_TEST(!strncmp(components[1].str, "versions", components[1].len),
"v7 (components[1])");
MY_TEST(!strncmp(components[2].str, "v7", components[2].len),
"v7 (components[2])");
num = tokenize_path_components("dbus/mask/send", components, max);
MY_TEST(num == 3, "dbus send (num)");
MY_TEST(!strncmp(components[0].str, "dbus", components[0].len),
"dbus send (components[0])");
MY_TEST(!strncmp(components[1].str, "mask", components[1].len),
"dbus send (components[1])");
MY_TEST(!strncmp(components[2].str, "send", components[2].len),
"dbus send (components[2])");
return rc;
}
static int do_test_walk_one(const char **str, const struct component *component,
bool is_top_level, bool expect_walk, const char *e1,
const char *e2, const char *e3)
{
const char *save = str ? *str : NULL;
bool walked = walk_one(str, component, is_top_level);
int rc = 0;
/* Check if the result of the walk matches the expected result*/
MY_TEST(expect_walk == walked, e1);
if (save) {
/**
* If a walk was expected, @*str should have changed. It
* shouldn't change if a walk was unexpected.
*/
if (expect_walk) {
MY_TEST(*str != save, e2);
} else {
MY_TEST(*str == save, e3);
}
}
return rc;
}
#define MY_WALK_TEST(str, component, is_top_level, expect_walk, error) \
if (do_test_walk_one(str, component, is_top_level, \
expect_walk, \
error " (walk check)", \
error " (str didn't change)", \
error " (str changed)")) { \
rc = 1; \
}
#define MY_GOOD_WALK_TEST(str, component, is_top_level, error) \
MY_WALK_TEST(str, component, is_top_level, true, error)
#define MY_BAD_WALK_TEST(str, component, is_top_level, error) \
MY_WALK_TEST(str, component, is_top_level, false, error)
static int test_walk_one(void)
{
struct component c;
const char *str;
int rc = 0;
MY_BAD_WALK_TEST(NULL, &c, true, "basic NULL str test");
str = NULL;
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL *str test");
str = "test { a b }";
MY_BAD_WALK_TEST(&str, NULL, true, "basic NULL component test");
str = "test { a b }";
c = (struct component) { NULL, 8 };
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL c.str test");
str = "test { a b }";
c = (struct component) { "", 0 };
MY_BAD_WALK_TEST(&str, &c, true, "basic empty c.str test");
str = "test";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component");
str = "testX";
c = (struct component) { "test", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "single component bad str");
str = "test";
c = (struct component) { "testX", 5 };
MY_BAD_WALK_TEST(&str, &c, true, "single component bad c.str");
str = "test { }";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #1");
str = "test {\n\t}";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #2");
str = "test{}";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #3");
str = "test\t{}\n ";
c = (struct component) { "test", 4 };
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #4");
str = "test {}";
c = (struct component) { "test", 4 };
MY_BAD_WALK_TEST(&str, &c, false, "single component bad is_top_level");
str = "front{back";
c = (struct component) { "frontback", 9};
MY_BAD_WALK_TEST(&str, &c, true, "brace in the middle #1");
MY_BAD_WALK_TEST(&str, &c, false, "brace in the middle #2");
str = "ardvark { bear cat { deer } }";
c = (struct component) { "ardvark", 7 };
MY_GOOD_WALK_TEST(&str, &c, true, "animal walk good ardvark");
c = (struct component) { "deer", 4 };
MY_BAD_WALK_TEST(&str, &c, false, "animal walk bad deer");
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad top-level deer");
c = (struct component) { "bear", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad bear");
c = (struct component) { "cat", 3 };
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good cat");
c = (struct component) { "ardvark", 7 };
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad ardvark");
c = (struct component) { "deer", 4 };
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good deer");
str = "dbus {mask {acquire send receive\n}\n}\nsignal {mask {hup int\n}\n}";
c = (struct component) { "hup", 3 };
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad hup #1");
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad hup #2");
c = (struct component) { "signal", 6 };
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad signal");
MY_GOOD_WALK_TEST(&str, &c, true, "dbus/signal good signal");
c = (struct component) { "mask", 4 };
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad mask");
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good mask");
c = (struct component) { "hup", 3 };
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good hup");
str = "policy {set_load {yes\n}\nversions {v7 {yes\n}\nv6 {yes\n}";
c = (struct component) { "policy", 6 };
MY_GOOD_WALK_TEST(&str, &c, true, "policy good");
c = (struct component) { "versions", 8 };
MY_GOOD_WALK_TEST(&str, &c, false, "versions good");
c = (struct component) { "v7", 2 };
MY_GOOD_WALK_TEST(&str, &c, false, "v7 good");
return rc;
}
int main(void)
{
int retval, rc = 0;
retval = test_tokenize_path_components();
if (retval)
rc = retval;
retval = test_walk_one();
if (retval)
rc = retval;
return rc;
}

View File

@@ -0,0 +1,228 @@
/*
* 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 <stdio.h>
#include <string.h>
#include "kernel.c"
static int nullcmp_and_strcmp(const void *s1, const void *s2)
{
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
if (!s1 || !s2)
return s1 != s2;
return strcmp(s1, s2);
}
static int do_test_splitcon(char *con, int size, bool strip_nl, char **mode,
const char *expected_label,
const char *expected_mode, const char *error)
{
char *label;
int rc = 0;
label = splitcon(con, size, strip_nl, mode);
if (nullcmp_and_strcmp(label, expected_label)) {
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
error, label, expected_label);
rc = 1;
}
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
error, *mode, expected_mode);
rc = 1;
}
return rc;
}
static int do_test_aa_splitcon(char *con, char **mode,
const char *expected_label,
const char *expected_mode, const char *error)
{
char *label;
int rc = 0;
label = aa_splitcon(con, mode);
if (nullcmp_and_strcmp(label, expected_label)) {
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
error, label, expected_label);
rc = 1;
}
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
error, *mode, expected_mode);
rc = 1;
}
return rc;
}
#define TEST_SPLITCON(con, size, strip_nl, expected_label, \
expected_mode, error) \
do { \
char c1[] = con; \
char c2[] = con; \
size_t sz = size < 0 ? strlen(con) : size; \
char *mode; \
\
if (do_test_splitcon(c1, sz, strip_nl, &mode, \
expected_label, expected_mode, \
"splitcon: " error)) { \
rc = 1; \
} else if (do_test_splitcon(c2, sz, strip_nl, NULL, \
expected_label, NULL, \
"splitcon: " error " (NULL mode)")) { \
rc = 1; \
} \
} while (0)
#define TEST_AA_SPLITCON(con, expected_label, expected_mode, error) \
do { \
char c1[] = con; \
char c2[] = con; \
char c3[] = con "\n"; \
char *mode; \
\
if (do_test_aa_splitcon(c1, &mode, expected_label, \
expected_mode, "aa_splitcon: " error)) {\
rc = 1; \
} else if (do_test_aa_splitcon(c2, NULL, expected_label,\
NULL, \
"aa_splitcon: " error " (NULL mode)")) {\
rc = 1; \
} else if (do_test_aa_splitcon(c3, &mode, \
expected_label, expected_mode, \
"aa_splitcon: " error " (newline)")) { \
rc = 1; \
} \
} while (0)
static int test_splitcon(void)
{
int rc = 0;
/**
* NOTE: the TEST_SPLITCON() macro automatically generates
* corresponding tests with a NULL mode pointer.
*/
TEST_SPLITCON("", 0, true, NULL, NULL, "empty string test #1");
TEST_SPLITCON("", 0, false, NULL, NULL, "empty string test #2");
TEST_SPLITCON("unconfined", -1, true, "unconfined", NULL,
"unconfined #1");
TEST_SPLITCON("unconfined", -1, false, "unconfined", NULL,
"unconfined #2");
TEST_SPLITCON("unconfined\n", -1, true, "unconfined", NULL,
"unconfined #3");
TEST_SPLITCON("unconfined\n", -1, false, NULL, NULL,
"unconfined #4");
TEST_SPLITCON("label (mode)", -1, true, "label", "mode",
"basic split #1");
TEST_SPLITCON("label (mode)", -1, false, "label", "mode",
"basic split #2");
TEST_SPLITCON("label (mode)\n", -1, true, "label", "mode",
"basic split #3");
TEST_SPLITCON("label (mode)\n", -1, false, NULL, NULL,
"basic split #4");
TEST_SPLITCON("/a/b/c (enforce)", -1, true, "/a/b/c", "enforce",
"path enforce split #1");
TEST_SPLITCON("/a/b/c (enforce)", -1, false, "/a/b/c", "enforce",
"path enforce split #2");
TEST_SPLITCON("/a/b/c (enforce)\n", -1, true, "/a/b/c", "enforce",
"path enforce split #3");
TEST_SPLITCON("/a/b/c (enforce)\n", -1, false, NULL, NULL,
"path enforce split #4");
return rc;
}
static int test_aa_splitcon(void)
{
int rc = 0;
/**
* NOTE: the TEST_AA_SPLITCON() macro automatically generates
* corresponding tests with a NULL mode pointer and contexts with
* trailing newline characters.
*/
TEST_AA_SPLITCON("label (mode)", "label", "mode", "basic split");
TEST_AA_SPLITCON("/a/b/c (enforce)", "/a/b/c", "enforce",
"path enforce split");
TEST_AA_SPLITCON("/a/b/c (complain)", "/a/b/c", "complain",
"path complain split");
TEST_AA_SPLITCON("profile_name (enforce)", "profile_name", "enforce",
"name enforce split");
TEST_AA_SPLITCON("profile_name (complain)", "profile_name", "complain",
"name complain split");
TEST_AA_SPLITCON("unconfined", "unconfined", NULL, "unconfined");
TEST_AA_SPLITCON("(odd) (enforce)", "(odd)", "enforce",
"parenthesized label #1");
TEST_AA_SPLITCON("(odd) (enforce) (enforce)", "(odd) (enforce)",
"enforce", "parenthesized label #2");
TEST_AA_SPLITCON("/usr/bin/😺 (enforce)", "/usr/bin/😺", "enforce",
"non-ASCII path");
TEST_AA_SPLITCON("👍 (enforce)", "👍", "enforce",
"non-ASCII profile name");
/* Negative tests */
TEST_AA_SPLITCON("", NULL, NULL, "empty string test");
TEST_AA_SPLITCON("profile\t(enforce)", NULL, NULL,
"invalid tab separator");
TEST_AA_SPLITCON("profile(enforce)", NULL, NULL,
"invalid missing separator");
return rc;
}
int main(void)
{
int retval, rc = 0;
retval = test_splitcon();
if (retval)
rc = retval;
retval = test_aa_splitcon();
if (retval)
rc = retval;
return rc;
}

View File

@@ -3,12 +3,30 @@
%{
#include <aalogparse.h>
#include <sys/apparmor.h>
#include <sys/apparmor_private.h>
%}
%include "typemaps.i"
%include <aalogparse.h>
/**
* swig doesn't like the macro magic we do in apparmor.h and apparmor_private.h
* so the function prototypes must be manually inserted.
*
* Functions that return a negative int and set errno upon error use a special
* %exception directive and must be listed after the %exception below. All
* other functions go here.
*/
/* apparmor.h */
extern char *aa_splitcon(char *con, char **mode);
/* apparmor_private.h */
extern int _aa_is_blacklisted(const char *name);
#ifdef SWIGPYTHON
%exception {
$action
@@ -19,9 +37,9 @@
}
#endif
/* swig doesn't like the macro magic we do in apparmor.h so the fn prototypes
* are manually inserted here
*/
/* Functions that return a negative int and set errno upon error go here. */
/* apparmor.h */
extern int aa_is_enabled(void);
extern int aa_find_mountpoint(char **mnt);
@@ -33,11 +51,22 @@ extern int aa_change_hat_vargs(unsigned long token, int count, ...);
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode);
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
extern int aa_getcon(char **con, char **mode);
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
extern int aa_getcon(char **label, char **mode);
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
extern int aa_getpeercon(int fd, char **con, char **mode);
extern int aa_getpeercon(int fd, char **label, char **mode);
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
int *audit);
extern int aa_query_file_path_len(uint32_t mask, const char *label,
size_t label_len, const char *path,
size_t path_len, int *allowed, int *audited);
extern int aa_query_file_path(uint32_t mask, const char *label,
const char *path, int *allowed, int *audited);
extern int aa_query_link_path_len(const char *label, size_t label_len,
const char *target, size_t target_len,
const char *link, size_t link_len,
int *allowed, int *audited);
extern int aa_query_link_path(const char *label, const char *target,
const char *link, int *allowed, int *audited);
%exception;

View File

@@ -6,9 +6,8 @@ SUBDIRS = test
libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
$(SWIG) -python -I$(srcdir)/../../include -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
mv LibAppArmor.py __init__.py
MOSTLYCLEANFILES=libapparmor_wrap.c __init__.py
MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
all-local: libapparmor_wrap.c setup.py
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi

View File

@@ -0,0 +1,6 @@
import sys
if sys.version_info[0] >= 3:
from LibAppArmor.LibAppArmor import *
else:
from .LibAppArmor import *

View File

@@ -121,7 +121,7 @@ class AAPythonBindingsTests(unittest.TestCase):
continue
else:
new_record[key] = str(value)
elif record.__getattr__(key):
elif value or value == '':
new_record[key] = str(value)
return new_record

View File

@@ -0,0 +1 @@
[103975.623545] audit: type=1400 audit(1481284511.494:2807): apparmor="DENIED" operation="change_onexec" info="no new privs" error=-1 namespace="root//lxd-tor_<var-lib-lxd>" profile="unconfined" name="system_tor" pid=18593 comm="(tor)" target="system_tor"

View File

@@ -0,0 +1,15 @@
START
File: change_onexec_lp1648143.in
Event type: AA_RECORD_DENIED
Audit ID: 1481284511.494:2807
Operation: change_onexec
Profile: unconfined
Name: system_tor
Command: (tor)
Name2: system_tor
Namespace: root//lxd-tor_<var-lib-lxd>
Info: no new privs
ErrorCode: 1
PID: 18593
Epoch: 1481284511
Audit subid: 2807

View File

@@ -0,0 +1 @@
type=AVC msg=audit(1465133533.431:728): apparmor="DENIED" operation="chown" profile="/usr/sbin/cupsd" name="/run/cups/certs/" pid=8515 comm="cupsd" requested_mask="w" denied_mask="w" fsuid=0 ouid=4

View File

@@ -0,0 +1,15 @@
START
File: file_chown.in
Event type: AA_RECORD_DENIED
Audit ID: 1465133533.431:728
Operation: chown
Mask: w
Denied Mask: w
fsuid: 0
ouid: 4
Profile: /usr/sbin/cupsd
Name: /run/cups/certs/
Command: cupsd
PID: 8515
Epoch: 1465133533
Audit subid: 728

View File

@@ -0,0 +1 @@
Oct 22 15:57:38 NR021AA kernel: [ 69.827705] audit: type=1400 audit(1445522258.769:1054): apparmor="DENIED" operation="file_inherit" profile="/usr/lib/NetworkManager/nm-dhcp-client.action" pid=2407 comm="nm-dhcp-client." lport=10580 family="inet6" sock_type="dgram" protocol=17

View File

@@ -0,0 +1,14 @@
START
File: file_inherit_network_lp1509030.in
Event type: AA_RECORD_DENIED
Audit ID: 1445522258.769:1054
Operation: file_inherit
Profile: /usr/lib/NetworkManager/nm-dhcp-client.action
Command: nm-dhcp-client.
PID: 2407
Network family: inet6
Socket type: dgram
Protocol: udp
Local port: 10580
Epoch: 1445522258
Audit subid: 1054

View File

@@ -0,0 +1 @@
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:192.168.236.159 lport=80 faddr=::ffff:192.168.103.80 fport=61985 family="inet6" sock_type="stream" protocol=6

View File

@@ -0,0 +1,17 @@
START
File: file_perm_network_lp1466812.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1434708055.676:19629
Operation: file_perm
Profile: /usr/sbin/apache2
Command: apache2
PID: 3512
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:192.168.236.159
Foreign addr: ::ffff:192.168.103.80
Local port: 80
Foreign port: 61985
Epoch: 1434708055
Audit subid: 19629

View File

@@ -0,0 +1 @@
type=AVC msg=audit(1463403689.381:267599): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2//www.xxxxxxxxxx.co.uk" pid=13215 comm="apache2" laddr=::ffff:192.168.1.100 lport=80 faddr=::ffff:192.168.1.100 fport=45658 family="inet6" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"

View File

@@ -0,0 +1,19 @@
START
File: file_perm_network_receive_lp1577051.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1463403689.381:267599
Operation: file_perm
Mask: send
Denied Mask: send
Profile: /usr/sbin/apache2//www.xxxxxxxxxx.co.uk
Command: apache2
PID: 13215
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:192.168.1.100
Foreign addr: ::ffff:192.168.1.100
Local port: 80
Foreign port: 45658
Epoch: 1463403689
Audit subid: 267599

View File

@@ -0,0 +1 @@
Apr 30 21:53:05 nova kernel: [24668.960760] audit: type=1400 audit(1462045985.636:2154): apparmor="ALLOWED" operation="file_perm" profile="/usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java" pid=12529 comm="java" laddr=::ffff:127.0.0.1 lport=8080 faddr=::ffff:127.0.0.1 fport=52308 family="inet6" sock_type="stream" protocol=6 requested_mask="receive" denied_mask="receive"

View File

@@ -0,0 +1,19 @@
START
File: file_perm_network_receive_lp1582374.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1462045985.636:2154
Operation: file_perm
Mask: receive
Denied Mask: receive
Profile: /usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java
Command: java
PID: 12529
Network family: inet6
Socket type: stream
Protocol: tcp
Local addr: ::ffff:127.0.0.1
Foreign addr: ::ffff:127.0.0.1
Local port: 8080
Foreign port: 52308
Epoch: 1462045985
Audit subid: 2154

View File

@@ -0,0 +1 @@
Sep 14 18:49:13 mfa-mia-74-app-rabbitmq-1.mia.ix.int kernel: [964718.247816] type=1400 audit(1442256553.643:40143): apparmor="ALLOWED" operation="open" profile="/opt/evoke/venv/bin/gunicorn" name="/opt/evoke/venv/lib/python2.7/warnings.pyc" pid=28943 comm="gunicorn" requested_mask="r" denied_mask="r" fsuid=1000 ouid=110

View File

@@ -0,0 +1,15 @@
START
File: syslog_hostname_with_dot.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1442256553.643:40143
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 110
Profile: /opt/evoke/venv/bin/gunicorn
Name: /opt/evoke/venv/lib/python2.7/warnings.pyc
Command: gunicorn
PID: 28943
Epoch: 1442256553
Audit subid: 40143

View File

@@ -0,0 +1 @@
type=AVC msg=audit(1449442292.901:961): apparmor="ALLOWED" operation="change_hat" profile="/usr/sbin/httpd{,2}-prefork" pid=8527 comm="httpd-prefork" target="/usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT"

View File

@@ -0,0 +1,11 @@
START
File: testcase_changehat_01.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1449442292.901:961
Operation: change_hat
Profile: /usr/sbin/httpd{,2}-prefork
Command: httpd-prefork
Name2: /usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT
PID: 8527
Epoch: 1449442292
Audit subid: 961

View File

@@ -0,0 +1 @@
Sep 9 12:51:36 ubuntu-desktop kernel: [ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"

View File

@@ -0,0 +1,11 @@
START
File: testcase_changeprofile_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1431116353.523:77
Operation: change_profile
Profile: /tests/regression/apparmor/changeprofile
Command: changeprofile
Name2: /tests/regression/apparmor/rename
PID: 3459
Epoch: 1431116353
Audit subid: 77

View File

@@ -0,0 +1 @@
[ 1612.746129] audit: type=1400 audit(1284061910.975:672): apparmor="DENIED" operation="capable" parent=2663 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority" pid=7292 comm="syscall_setprio" capability=23 capname="sys_nice"

View File

@@ -0,0 +1,12 @@
START
File: testcase_dmesg_capability.in
Event type: AA_RECORD_DENIED
Audit ID: 1284061910.975:672
Operation: capable
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority
Name: sys_nice
Command: syscall_setprio
Parent: 2663
PID: 7292
Epoch: 1284061910
Audit subid: 672

View File

@@ -0,0 +1 @@
[ 1597.774866] audit: type=1400 audit(1284061896.005:28): apparmor="DENIED" operation="change_hat" info="unconfined" error=-1 pid=2698 comm="syscall_ptrace"

View File

@@ -0,0 +1,11 @@
START
File: testcase_dmesg_changehat_negative_error.in
Event type: AA_RECORD_DENIED
Audit ID: 1284061896.005:28
Operation: change_hat
Command: syscall_ptrace
Info: unconfined
ErrorCode: 1
PID: 2698
Epoch: 1284061896
Audit subid: 28

View File

@@ -0,0 +1 @@
[ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"

View File

@@ -0,0 +1,11 @@
START
File: testcase_dmesg_changeprofile_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1431116353.523:77
Operation: change_profile
Profile: /tests/regression/apparmor/changeprofile
Command: changeprofile
Name2: /tests/regression/apparmor/rename
PID: 3459
Epoch: 1431116353
Audit subid: 77

View File

@@ -0,0 +1 @@
[ 2010.738449] audit: type=1400 audit(1284062308.965:276251): apparmor="DENIED" operation="link" parent=19088 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/link" name="/tmp/sdtest.19088-12382-HWH57d/linkfile" pid=19142 comm="link" requested_mask="l" denied_mask="l" fsuid=0 ouid=0 target="/tmp/sdtest.19088-12382-HWH57d/target"

View File

@@ -0,0 +1,17 @@
START
File: testcase_dmesg_link_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1284062308.965:276251
Operation: link
Mask: l
Denied Mask: l
fsuid: 0
ouid: 0
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/link
Name: /tmp/sdtest.19088-12382-HWH57d/linkfile
Command: link
Name2: /tmp/sdtest.19088-12382-HWH57d/target
Parent: 19088
PID: 19142
Epoch: 1284062308
Audit subid: 276251

View File

@@ -0,0 +1 @@
[45334.755142] audit: type=1503 audit(1282671283.411:2199): operation="mkdir" pid=4786 parent=4708 profile="/usr/sbin/sshd//ubuntu" requested_mask="c::" denied_mask="c::" fsuid=1000 ouid=1000 name="/tmp/ssh-gRozJw4786/"

View File

@@ -0,0 +1,15 @@
START
File: testcase_dmesg_mkdir.in
Event type: AA_RECORD_DENIED
Audit ID: 1282671283.411:2199
Operation: mkdir
Mask: c::
Denied Mask: c::
fsuid: 1000
ouid: 1000
Profile: /usr/sbin/sshd//ubuntu
Name: /tmp/ssh-gRozJw4786/
Parent: 4708
PID: 4786
Epoch: 1282671283
Audit subid: 2199

View File

@@ -0,0 +1 @@
[ 878.663418] audit: type=1502 audit(1282626827.320:413): operation="rename_dest" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="wc::" denied_mask="wc::" fsuid=0 ouid=0 name="/var/run/motd"

View File

@@ -0,0 +1,15 @@
START
File: testcase_dmesg_rename_dest.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1282626827.320:413
Operation: rename_dest
Mask: wc::
Denied Mask: wc::
fsuid: 0
ouid: 0
Profile: /usr/sbin/sshd
Name: /var/run/motd
Parent: 650
PID: 1881
Epoch: 1282626827
Audit subid: 413

View File

@@ -0,0 +1 @@
[ 878.663410] audit: type=1502 audit(1282626827.320:412): operation="rename_src" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="r::" denied_mask="r::" fsuid=0 ouid=0 name="/var/run/motd.new"

View File

@@ -0,0 +1,15 @@
START
File: testcase_dmesg_rename_src.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1282626827.320:412
Operation: rename_src
Mask: r::
Denied Mask: r::
fsuid: 0
ouid: 0
Profile: /usr/sbin/sshd
Name: /var/run/motd.new
Parent: 650
PID: 1881
Epoch: 1282626827
Audit subid: 412

View File

@@ -0,0 +1 @@
[ 2143.902340] audit: type=1400 audit(1283989336.064:272335): apparmor="STATUS" info="failed to unpack profile" error=-71 pid=4958 comm="apparmor_parser" name="/home/jj/master/tests/regression/apparmor/net_raw" offset=159

View File

@@ -0,0 +1,11 @@
START
File: testcase_dmesg_status_offset.in
Event type: AA_RECORD_STATUS
Audit ID: 1283989336.064:272335
Name: /home/jj/master/tests/regression/apparmor/net_raw
Command: apparmor_parser
Info: failed to unpack profile
ErrorCode: 71
PID: 4958
Epoch: 1283989336
Audit subid: 272335

View File

@@ -0,0 +1 @@
[ 878.662172] audit: type=1503 audit(1282626827.320:411): operation="truncate" pid=1957 parent=1 profile="/etc/update-motd.d/91-release-upgrade" requested_mask="w::" denied_mask="w::" fsuid=0 ouid=0 name="/var/lib/update-notifier/release-upgrade-available"

View File

@@ -0,0 +1,15 @@
START
File: testcase_dmesg_truncate.in
Event type: AA_RECORD_DENIED
Audit ID: 1282626827.320:411
Operation: truncate
Mask: w::
Denied Mask: w::
fsuid: 0
ouid: 0
Profile: /etc/update-motd.d/91-release-upgrade
Name: /var/lib/update-notifier/release-upgrade-available
Parent: 1
PID: 1957
Epoch: 1282626827
Audit subid: 411

View File

@@ -0,0 +1 @@
Jul 29 11:42:05 files kernel: [483212.877816] audit: type=1400 audit(1469785325.122:21021): apparmor="ALLOWED" operation="file_inherit" profile="/usr/bin/nginx-amplify-agent.py//null-/bin/dash" pid=18239 comm="sh" laddr=192.168.10.3 lport=50758 faddr=54.153.70.241 fport=443 family="inet" sock_type="stream" protocol=6 requested_mask="send receive" denied_mask="send receive"

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