2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 06:16:03 +00:00

Compare commits

...

139 Commits

Author SHA1 Message Date
Steve Beattie
4be3c82fa5 git conversion: move .bzrignore to .gitignore
Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
2017-10-27 22:46:04 -07:00
John Johansen
323aee990b Bump release version to 2.8.5 2017-10-18 19:44:47 -07:00
Christian Boltz
6e4fa53b79 backport nscd profile additions from 2.9 branch
The most important change is /proc/[0-9]*/cmdline to allow paranoid mode.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-04-15 23:05:27 +02:00
Christian Boltz
d8a6681b2e Backport profile additions from the 2.9 branch
This patch backports most profile additions from the latest 2.9 branch
r3004, with the exception of new rule types (2.8 doesn't support dbus,
ptrace etc.) and some noisy cleanups (like /proc/*/ -> @{PROC}/@{pid}/).


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-04-15 22:20:54 +02:00
Steve Beattie
6a8a099968 libapparmor: fix parsing for yet another format
Backport from trunk revision 2830

This patch fixes the libapparmor log parsing library to take into
account yet another log format style, as well as incorporating a
testcase for it.

Bugs:
  https://bugs.launchpad.net/apparmor/+bug/1399027
  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771400
  https://bugzilla.opensuse.org/show_bug.cgi?id=905368

Nominated-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>

Bug: https://launchpad.net/bugs/1399027
2014-12-12 17:07:42 -08:00
Steve Beattie
b0273a9289 libaalogparse: fix for new kernel dmesg format
Merge from trunk revision 2647

The upstream kernel at some point between the 3.13 and 3.16 kernel
adjusted the output of audit messages to include an additional "audit:"
keyword. e.g. a 3.13 message would look like:

  kernel: [182243.243324] type=1400 audit(1409684003.960:273342): [SNIP]

whereas in 3.16, it looks like:

  kernel: [182243.243324] audit: type=1400 audit(1409684003.960:273342): [SNIP]
                          ^^^^^^

This patch adjust the libapparmor aalogparse grammar and lexer to
compensate for this change.

Nominated-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-12-12 17:03:07 -08:00
Christian Boltz
a21d7df05b fix filename for .../nscd/hosts (which was accidently changed to "host" 3 years ago)
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-11-18 00:28:51 +01:00
Steve Beattie
2c6dd0aa98 toplevel Makefile: use https URI by default for vcs export
Merge from trunk commit 2261.

Since --per-file-timestamps is broken over the SSH transport (see
https://bugs.launchpad.net/bzr/+bug/1257078), make the default use
a HTTPS URI instead.
2014-10-09 14:40:50 -07:00
Steve Beattie
6a347df2fb Prepare for apparmor 2.8.4 release. 2014-10-09 14:29:47 -07:00
Steve Beattie
ed2b8b3111 mod_apparmor: revert apache 2.4 api fix from commit 2131
This patch reverts commit 2131 which added support for the newer apache
2.4 ap_hook_check_access_ex() api, based on a report from Christian that
it broke apache's simple authentication.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-10-09 12:49:38 -07:00
Christian Boltz
5efe6e2cec ntpd on openSUSE Factory needs another location for the pid file.
References: https://bugzilla.novell.com/show_bug.cgi?id=899746
  

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-10-06 19:58:49 +02:00
Seth Arnold
766485972a Merge changes from trunk -- almost entirely additions to abstractions, a
perl multiarch change to logprof.conf and new perl severity entries.

  intrigeri@boum.org 2014-09-10 Cherry-pick r2671 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2387 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2610 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2506 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2592 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2353 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2294 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2593 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2590 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2522 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2369 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2246 from master.
2014-09-12 16:13:45 -07:00
Seth Arnold
029875ef72 Remove <sys/sysctl.h> from parser_main.c to fix FTBFS on x32 platform.
As originally applied to trunk in 2667:

  The AppArmor parser failed to build on the x32 architecture due to a
  missing <sys/sysctl.h> header. This header is included by accident, a
  vestige of earlier days, and wasn't removed when the sysctls were
  removed. (Think Linux 2.0 or Linux 2.2 days.)

  See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=760378

  Thanks to Thorsten Glaser for the discovery and initial fix.
2014-09-10 18:36:10 -07:00
intrigeri
770746a320 Cherry-pick r2671 from master. 2014-09-10 17:41:44 -07:00
intrigeri
90bcee0f23 Cherry-pick r2387 from master. 2014-09-10 17:40:14 -07:00
intrigeri
2ace7d9dfa Cherry-pick r2610 from master. 2014-09-10 17:37:53 -07:00
intrigeri
95368e8fd0 Cherry-pick r2506 from master. 2014-09-10 17:37:27 -07:00
intrigeri
53fce179d9 Cherry-pick r2592 from master. 2014-09-10 17:37:02 -07:00
intrigeri
7566f992dd Cherry-pick r2353 from master. 2014-09-10 17:34:21 -07:00
intrigeri
3b1b013fc8 Cherry-pick r2294 from master. 2014-09-10 17:33:36 -07:00
intrigeri
e579d939ce Cherry-pick r2593 from master. 2014-09-10 17:32:57 -07:00
intrigeri
a591cf73b1 Cherry-pick r2590 from master. 2014-09-10 17:32:03 -07:00
intrigeri
97f6d4f52e Cherry-pick r2522 from master. 2014-09-10 17:24:07 -07:00
intrigeri
793013c3ce Cherry-pick r2369 from master. 2014-09-10 17:21:54 -07:00
intrigeri
fc03b984bd Cherry-pick r2246 from master. 2014-09-10 17:21:31 -07:00
Christian Boltz
e1092cfc72 add missing --display to aa-notify.pod
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-08 20:41:07 +02:00
Christian Boltz
90fe8b8d09 Fix for commit 2.8 branch r2140:
> Allow dnsmasq read access to IPv6 config

The commit did not match this part of the commit message  
> slightly modified (../conf/**/mtu -> ../conf/*/mtu)
which I'm fixing now.
2014-09-08 20:39:12 +02:00
Christian Boltz
6f6bce01a1 Allow dnsmasq read access to IPv6 config
The IPv6 Neighbor Discovery protocol (RFC 2461) suggests
implementations provide MTU in Router Advertisement (RA)
messages.  From section 4.2

MTU    SHOULD be sent on links that have a variable MTU
       (as specified in the document that describes how to
       run IP over the particular link type).  MAY be sent
       on other links.

dnsmasq supports this option and should have read access
to an interface's MTU.

Patch by James Fehlig <jfehlig@suse.com>


slightly modified (../conf/**/mtu -> ../conf/*/mtu)


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-06 23:09:18 +02:00
Arthur Marble
c72c406357 parser: fix FTBFS when building with clang
Fix undefined reference error in parser/parser_interface.c.
http://clang.llvm.org/compatibility.html#inline has more details.

Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=756807

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-29 12:26:59 -07:00
Christian Boltz
038c37c551 smbd: changed cachedir in openSUSE
openSUSE now compiles samba --with-cachedir=/var/lib/samba (instead of 
the default /var/cache/samba). This patch updates the smbd profile to 
match this change.

References: https://bugzilla.novell.com/show_bug.cgi?id=869787


Acked by: Seth Arnold <seth.arnold@canonical.com>
2014-08-11 23:24:23 +02:00
Christian Boltz
dedfb6d17a From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Properly handle bare 'file' keyword
References: bnc#889652

The bare file keyword is a shortcut for /{**,}. There are also implied
permissions that go with it.

This patch accepts the file keyword as well as allowing for missing mode
specifiers.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:49:15 +02:00
Christian Boltz
08fcbcc8ec From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Handle bare 'capability' keyword
References: bnc#889651

Specifying 'capability' implies all capabilities, but the perl code didn't
recognize it.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:48:30 +02:00
Christian Boltz
ff267dc1fc From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Fix bare 'network' keyword handling
References: bnc#889650

The 'network' bare keyword was being printed as "audit network all" due to
two different bugs:

1) {audit}{all} was always being set to 1, regardless of whether the audit
   keyword was used
2) {rule} eq 'all' is the wrong test - it should be {rule}{all}

With these fixed, 'network' is properly handled.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:47:39 +02:00
Steve Beattie
47df23aca5 parser: remove leaked in C++ish bool
In commit rev 2127, backported from trunk, a bit of C++ish style code
leaked in, the use of a bool variable. This is problematic for pure C
code. This commit converts the bool to an int and adjusts the true and
false keywords to their corresponding macros as defined in parser.h.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-07-30 03:49:49 -07:00
Steve Beattie
090c912431 utils: add CAP_AUDIT_READ to severity.db
Merge from trunk rev 2564.

This patch adds the new capability CAP_AUDIT_READ, added in the 3.16
kernel, to the utils severity.db. I set the severity level at 7,
since it seemed to offer less exposure than CAP_AUDIT_CONTROL and
CAP_AUDIT_WRITE, which are both considered severity 8.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-21 22:56:11 -07:00
Steve Beattie
59ed7057b3 libapparmor: fix log parsing memory leaks
This patch fixes some memory leaks in the libapparmor log parsing
functions, specifically around handling records obtained from syslog
and records containing network addresses.

Bug: https://bugs.launchpad.net/bugs/1340927
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-12 07:48:12 -07:00
Steve Beattie
b01c8f2a7a mod_apparmor: for apache 2.4, use new access control hook
Use ap_hook_check_access_ex() instead of
ap_hook_access_checker() for apache 2.4; see
http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html#http_request

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-10 10:09:48 -07:00
Steve Beattie
afe682c65c mod_apparmor: try uri hat after AADefaultHatName, not before
Bug: https://bugs.launchpad.net/bugs/1322778

Between the apparmor 2.8.2 and 2.8.3, a bug was fixed in mod_apparmor
(in 2.8 revno 2120) that corrected the storage location for
AADefaultHatName.  The incorrect storage caused the hat specified by
the AADefaultHatName keyword to be the default value for AAHatName,
and meant that if both an AAHatName and an AADefaultHatName entry
were given in a vhost, mod_apparmor would not fall back to trying
AADefaultHatName if the hat specified in AAHatName did not exist in
the apache apparmor profile.

However, because the value specified in AADefaultHatName was the
default, if no AAHatName was specified, it would be attempted first,
before a hat based on the passed URI, rather than after as the
documentation stated and the code intended. By fixing the storage bug,
the attempted hat ordering now matched the documentation. But a number
of users came to rely on AADefaultHatName being attempted before the
URI. Additionally, because the 2.8 mod_apparmor attempts each hat
individually (rather than use the aa_change_hatv like trunk's
mod_apparmor), each attempt with the URI-based hatname is logged by the
kernel portion of apparmor, making system logs particularly noisy those
same users.

This patch re-adjusts the ordering so that the URI-based hat is
attempted after the hat specified by AADefaultHatName is attempted,
thus maintaining the actual behavior before the bug addressed in
revno 2120 was fixed.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

Bug: https://launchpad.net/bugs/1322778
2014-07-10 10:08:24 -07:00
Christian Boltz
979b1d9f22 abstractions/nameservice should allow /run/nscd/passwd etc. in addition
to /var/run/nscd/passwd.

References: https://bugzilla.novell.com/show_bug.cgi?id=886225


Acked-by: Seth Arnold <seth.arnold@canonical.com> for both trunk and 2.8.
2014-07-09 10:18:54 +02:00
Jamie Strandboge
2c21b2d732 Description: update nvidia abstraction for additional /proc and ~/.nv/GLCache
access
Bug-Ubuntu: https://launchpad.net/bugs/1325050

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-06-06 13:52:24 -05:00
John Johansen
409e8703cf Fix profile loads from cache files that contain multiple profiles
backport of dev commit 2510

v3: fix freeing of filename when undefined
v2: address tyhicks feedback
    refactor to have a common write routine
    fix issue with set profile load being done even if !kernel_load

Profile loads from cache files that contain multiple profiles can
result in multiple reloads of the same profile or error messages about
failure to load profiles if the --add option is used. eg.

  apparmor="STATUS" operation="profile_load"
  name="/usr/lib/apache2/mpm-prefork/apache2" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058388] type=1400 audit(1395415826.937:616):
  apparmor="STATUS" operation="profile_load" name="DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058391] type=1400 audit(1395415826.937:617):
  apparmor="STATUS" operation="profile_load"
  name="HANDLING_UNTRUSTED_INPUT" pid=8631 comm="apparmor_parser"
  <sth0R> [82932.058394] type=1400 audit(1395415826.937:618):
  apparmor="STATUS" operation="profile_load" name="phpsysinfo" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059058] type=1400 audit(1395415826.937:619):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059574] type=1400 audit(1395415826.937:620):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//HANDLING_UNTRUSTED_INPUT"
  pid=8631 comm="apparmor_parser"


The reason this happens is that the cache file is a container that
can contain multiple profiles in sequential order
  profile1
  profile2
  profile3

The parser loads the entire cache file to memory and the writes the
whole file to the kernel interface. It then skips foward in the file
to the next profile and reloads the file from that profile into
the kernel.
  eg. First load
    profile1
    profile2
    profile3

  advance to profile2, do second load
    profile2
    profile3

  advance to profile3, do third load
    profile3


With older kernels the interface would stop after the first profile and
return that it had processed the whole file, thus while wasting compute
resources copying extra data no errors occurred. However newer kernels
now support atomic loading of multipe profiles, so that all the profiles
passed in to the interface get processed.

This means on newer kernels the current parser load behavior results
in multiple loads/replacements when a cache file contains more than
one profile (note: loads from a compile do not have this problem).

To fix this, detect if the kernel supports atomic set loads, and load
the cache file once. If it doesn't only load one profile section
from a cache file at a time.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-05-08 09:37:01 -07:00
Steve Beattie
933658d8a6 Add dconf abstraction for querying dconf settings
Merge from trunk revno: 2209

An abstraction to grant the ability to query dconf settings. It does
not grant the ability to update or add settings, due to our current
inability to restrict where within the dconf hierarchy updates
can occur.

Nominated for 2.8 by intrigeri <intrigeri@boum.org>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-03-10 10:25:55 -07:00
Seth Arnold
3df7f56154 Cherrypick revision 2412 from trunk, store magic token in unsigned int
Original log:
Store the aa_change_hat magic token in an unsigned long in the test suite

The magic token used in the test suite is incorrectly stored
as an int rather than unsigned long leading to failure like this:

running changehat_misc
/tmp/testlibCTcwOe/source/trusty/apparmor-2.8.95~2411/tests/regression/apparmor/prologue.inc: line 176: 20184
Killed                  $testexec "$@" > $outfile 2>&1
Error: changehat_twice failed. Test 'CHANGEHAT (subprofile->subprofile)' was expected to 'pass'. Reason for
failure 'killed by signal 9'

Signed-off-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-03-04 10:57:23 -08:00
Jamie Strandboge
155bdd07af Add /var/www/html to abstractions/web-data, which is the path used on Debian
and its derivatives
Bug-Ubuntu: https://launchpad.net/bugs/1285653

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-27 14:51:31 -06:00
Christian Boltz
96c2ee3e08 dnsmasq profile - NetworkManager integration
This is an updated version of the previous dnsmasq profile patch, again 
from develop7 [at] develop7.info


Acked-by: John Johansen <john.johansen@canonical.com>
2014-02-17 22:57:14 +01:00
Seth Arnold
1d07373407 bump versions in preparation for release 2014-02-16 21:01:10 -08:00
Steve Beattie
255954f240 mod_apparmor: include errno in log messages for failures
Merged from trunk revno: 2340

This patch includes the errno in the log messages generated by two
different failed aa_change_hat() calls and the failure to open
/dev/urandom to get the random token, to further ease failure
diagnosis.

2.8 Note: did not apply cleanly, required manual adjustment.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:51:11 -08:00
Steve Beattie
1c03c6249f mod_apparmor: fix AADefaultHatName storage
Merge from trunk revno: 2335

When defining an AADefaultHatName entry, it was being stored in the
passed mconfig location, which is not the module specific server
config, but instead the top level (i.e. no path defined) default
directory/location config. This would be superceded by a more specific
directory config if it applied to the request. Thus, if an AAHatName was
defined that applied, but the named hat was not defined in the apparmor
policy, mod_apparmor would not attempt to fall back to the defined
AADefaultHatName, but instead jump directly to trying the DEFAULT_URI
hat.

This patch fixes it by storing the defined AADefaultHatName correctly in
the module specific storage in the related server data structure. It
also adds a bit of developer debugging statements.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:43:37 -08:00
Steve Beattie
b0e00b01f2 mod_apparmor: improve initial and exit aa_change_hat call log message
Merge from trunk revno: 2334

This patch adds the name of the hat to the log message about the
initial aa_change_hat call, just to be explicit about what's happening
when debugging and changes the formatting slightly of the exiting
change_hat log message.

Patch history:
  v1: initial version
  v2: tweak output of exit trace message

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:42:12 -08:00
Steve Beattie
a20f467bf0 mod_apparmor: convert change_hat to aa_change_hat()
Merge from trunk revno: 2333

mod_apparmor never got converted to use the renamed aa_change_hat()
call (there's a compatibility macro in sys/apparmor.h); this patch does
that as well as converting the type of the magic_token to long from int.

(This patch is somewhat mooted by a later patch in the series to
convert to using aa_change_hatv(), but would be a safer candidate
for e.g. the 2.8 branch.)

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:40:57 -08:00
Steve Beattie
ba1e5a5b7c mod_apparmor: convert debug_dump_uri to use trace loglevel
Merge from trunk revno: 2332

This patch converts the debug_dump_uri() function to use the trace
loglevels and enable it all the time, rather than just when DEBUG is
defined at compile time.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:39:21 -08:00
Steve Beattie
11288e5b8d mod_apparmor: use trace1 loglevel for developer-oriented debug messages
Merged from trunk revno: 2331

Apache 2.4 added addition logging levels. This patch converts some of
the log messages that are more intended for mod_apparmor development
and debugging than for sysadmins configuring mod_apparmor to use trace1
(APLOG_TRACE1) level instead. Since apache 2.2. does not contain this
level (or define), we define it back to APLOG_DEBUG.

Patch history:
  v1: initial version
  v2: mark a couple of additional log messages as trace1 level

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:38:04 -08:00
Steve Beattie
bea5043bb8 mod_apparmor: fix logging
Merge from trunk revno: 2330

The apache2 mod_apparmor module was failing to log debugging messages
when the apache loglevel was set to debug or lower (i.e. traceN). This
patch fixes it by using ap_log_rerror() (for request specific messages,
with the request passed for context) and ap_log_error() (more general
messages outside of a request context).

Also, the APLOG_USE_MODULE macro is called, to mark the log messages
as belonging to the apparmor module, so that the apache 2.4 feature
of enabling debug logging for just the apparmor module will work,
with an apache configuration entry like:

  LogLevel apparmor:debug

See

  http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__LOG.html

for specific about the ap_log_*error() and APLOG_USE_MODULE functions
and macros, and

  http://httpd.apache.org/docs/2.4/mod/core.html.en#loglevel

for the bits about module specific logging.

Patch history:
  v1: initial version
  v2: - revert to using ap_log_error with (the 2.4 specific)
        ap_server_conf outside of a request specific context, as the
        pool specific ap_log_perror messages weren't being reported.
      - add compatibility workaround for apache 2.2
  v3: keep commented out merge function's log call consistent with the
      others

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de> (on IRC)
2014-02-14 16:35:21 -08:00
Seth Arnold
692e1b29e6 Fix --create-cache-dire typo in apparmor_parser --help output.
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2014-02-14 15:28:46 -08:00
Christian Boltz
3c7f5f5feb update abstractions/winbind
- some *.dat files live in a different directory nowadays (at least in 
  openSUSE)
- the openSUSE smb.conf includes the (autogenerated) dhcp.conf, so this
  file also needs to be readable.

References: https://bugzilla.novell.com/show_bug.cgi?id=863226

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-02-14 23:38:10 +01:00
Christian Boltz
b7e854695b apparmor.vim says "attach_disconnect" is correct, but the parser only
likes "attach_disconnected".

Acked-By: Jamie Strandboge <jamie@canonical.com>
2014-01-29 23:18:52 +01:00
Steve Beattie
2b51489cef Subject: libapparmor: fix aa_change_hat token format string
Merge from trunk commit rev 2329.

This patch fixes the format string for the magic token in aa_change_hat
to match the type of the magic token (long). Without this, on 64
bit platforms, only the bottom 32 bits of the token would be used.
aa_change_hatv() has the correct format string, so an aa_change_hatv()
call followed by an exiting aa_change_hat() call would result in the
latter having a different token, which would cause the process to be
killed by apparmor.

(Hat tip to John Johansen for spotting the actual bug.)

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-23 13:18:25 -08:00
Christian Boltz
78cbf37db0 allow dnsmasq read config created by recent NetworkManager
(see  http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=d82669d3fdaa7ec70ef1b64941c101ac810c394b 
for details)

Patch by develop7 [at] develop7.info

Acked-by: Jamie Strandboge <jamie@canonical.com>
2014-01-17 20:59:22 +01:00
Steve Beattie
9040d46cc4 parser: fix compilation failure on 32 bit systems
Merge from trunk revision 2308.

std::max in C++ requires that both arguments be the same type. The
previous fix added std::max comparisons between unsigned long numeric
constants and size_t, this fix casts the numeric constants to size_t.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-10 11:08:38 -08:00
John Johansen
ac7ab1c089 Fix policy generation for small dfas
cherry-pick of r2303 from trunk

So there are multiple bugs in policy generation for small dfas.
- A bug where dfas reduced to only have a none accepting state
  drop the start state for accept tables in the chfa encoding

  eg. deny audit dbus,

  the accept and accept2 tables are resized to 1 but the cfha format
  requires at least 2. 1 for the none accepting state and 1 for the
  start state.
  the kernel check that the accept tables == other state table sizes
  caught this and rejected it.

- the next/check table needs to be padded to the largest base position
  used + 256 so no input can ever overflow the next/check table
  (next/check[base+c]).

  This is normally handled by inserting a transition which resizes
  the table. However in this case there where no transitions being
  inserted into the dfa. Resulting in a next/check table size of
  2, with a base pos of 0. Meaning the table needed to be padded
  to 256.

- there is an alignment bug for dfas within the container (see below)
  what follows is a hexdump of the generated policy. With the
  different parts broken out. There are 2 dfas (policy and older file) and
  it is the second dfa that is out of alignment.

  The aadfa blob wrapper should be making sure that the start of the actual
  dfa is in alignment but this is not happening. In this example


00000000  04 08 00 76 65 72 73 69  6f 6e 00 02 05 00 00 00  |...version......|
00000010  04 08 00 70 72 6f 66 69  6c 65 00 07 05 40 00 2f  |...profile...@./|
00000020  68 6f 6d 65 2f 75 62 75  6e 74 75 2f 62 7a 72 2f  |home/ubuntu/bzr/|
00000030  61 70 70 61 72 6d 6f 72  2f 74 65 73 74 73 2f 72  |apparmor/tests/r|
00000040  65 67 72 65 73 73 69 6f  6e 2f 61 70 70 61 72 6d  |egression/apparm|
00000050  6f 72 2f 71 75 65 72 79  5f 6c 61 62 65 6c 00 04  |or/query_label..|
00000060  06 00 66 6c 61 67 73 00  07 02 00 00 00 00 02 00  |..flags.........|
00000070  00 00 00 02 00 00 00 00  08 02 00 00 00 00 02 00  |................|
00000080  00 00 00 02 00 00 00 00  02 00 00 00 00 04 07 00  |................|
00000090  63 61 70 73 36 34 00 07  02 00 00 00 00 02 00 00  |caps64..........|
000000a0  00 00 02 00 00 00 00 02  00 00 00 00 08 04 09 00  |................|
000000b0  70 6f 6c 69 63 79 64 62  00 07

begin of policy dfa blob wrapper
000000b0                                 04 06 00 61 61 64  |policydb.....aad|
000000c0  66 61 00 06

size of the following blob (in little endian) so 0x80
000000c0              80 00 00 00  

begin of actual policy dfa, notice alignment on 8 byte boundry
000000c0                           1b 5e 78 3d 00 00 00 18  |fa.......^x=....|
000000d0  00 00 00 80 00 00 6e 6f  74 66 6c 65 78 00 00 00  |......notflex...|
000000e0  00 01 00 04 00 00 00 00  00 00 00 01 00 00 00 00  |................|
000000f0  00 07 00 04 00 00 00 00  00 00 00 01 00 00 00 00  |................|
00000100  00 02 00 04 00 00 00 00  00 00 00 02 00 00 00 00  |................|
00000110  00 00 00 00 00 00 00 00  00 04 00 02 00 00 00 00  |................|
00000120  00 00 00 02 00 00 00 00  00 08 00 02 00 00 00 00  |................|
00000130  00 00 00 02 00 00 00 00  00 03 00 02 00 00 00 00  |................|
00000140  00 00 00 02 00 00 00 00  08

dfa blob wrapper
00000140                              04 06 00 61 61 64 66  |............aadf|
00000150  61 00 06

size of the following blob (in little endian) so 0x4c8
00000150          c8 04 00 00

begin of file dfa, notice alignment. NOT on 8 byte boundry
                               1b  5e 78 3d 00 00 00 18 00  |a.......^x=.....|
00000160  00 04 c8 00 00 6e 6f 74  66 6c 65 78 00 00 00 00  |.....notflex....|
00000170  01 00 04 00 00 00 00 00  00 00 06 00 00 00 00 00  |................|
00000180  00 00 00 00 9f c2 7f 00  00 00 00 00 00 00 00 00  |................|
00000190  04 00 30 00 00 00 00 00  07 00 04 00 00 00 00 00  |..0.............|
000001a0  00 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001c0  02 00 04 00 00 00 00 00  00 00 06 00 00 00 00 00  |................|
000001d0  00 00 00 00 00 00 01 00  00 00 01 00 00 00 02 00  |................|
000001e0  00 00 00 00 00 00 00 00  04 00 02 00 00 00 00 00  |................|
000001f0  00 00 06 00 00 00 00 00  02 00 00 00 05 00 05 00  |................|
00000200  08 00 02 00 00 00 00 00  00 01 02 00 00 00 03 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000260  00 00 00 00 00 00 00 00  00 00 02 00 04 00 00 00  |................|
00000270  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000410  03 00 02 00 00 00 00 00  00 01 02 00 00 00 02 00  |................|
00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000470  00 00 00 00 00 00 00 00  00 00 01 00 03 00 04 00  |................|
00000480  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000610  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00

end of container
00000610                                                08  |................|
00000620

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-01-09 17:43:59 -08:00
Steve Beattie
5ed40d9399 libapparmor: require libtoolize instead of libtool
Merge from trunk revision 2295:

libtoolize is the standard mechanism for incorporating libtool support
into a library; however, libapparmor's autogen.sh script specifically
looks for the existence of the libtool binary rather than libtoolize.
The libtoolize tool automatically generates a libtool script and does
not require the existence of the libtool binary, so we no longer need
to check for it.

The autogen.sh script aborting because it can't find the libtool
binary causes a spurious build failure in Ubuntu 14.04, due to the
libtool binary being separated out into its own package, and which
is not a strict dependency for libtool.

(I also added setting the package variable so that the error message
emitted will indicate that the failure is in building libapparmor.)

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-03 21:53:14 -08:00
Christian Boltz
6b18bb00ff samba (nmbd and smbd) need to create /var/run/samba and /var/cache/samba
at startup (at least on systems where /var/run is on a tmpfs)

References: https://bugzilla.novell.com/show_bug.cgi?id=856651

Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.8. Thanks!
2013-12-23 22:16:59 +01:00
Christian Boltz
c184f1ac39 add /var/lib/ca-certificates/ to abstractions/ssl_certs.
update-ca-certificates (from ca-certificates-1_201310161709-1.1.noarch) 
stores certs in this directory now.

References: https://bugzilla.novell.com/show_bug.cgi?id=852018

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-26 00:42:19 +01:00
Christian Boltz
d8793a07e8 Update samba profiles for samba 4.x
The patch includes changes needed for Samba 4.x, which also includes 
some small abstraction updates.

References: https://bugzilla.novell.com/show_bug.cgi?id=845867
References: https://bugzilla.novell.com/show_bug.cgi?id=846054

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-20 01:11:01 +01:00
Christian Boltz
1a8423937e ntpd needs access to /var/lib/ntp/drift/driftfile and
/var/lib/ntp/drift/driftfile.TEMP

References: https://bugzilla.novell.com/show_bug.cgi?id=850374

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-14 21:51:29 +01:00
John Johansen
01b23e02fa The apparmor parser build fails when bison 3 is used. The following
patch is needed to fix the build.

patch from: Jan Rękorajski <baggins@pld-linux.org>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-11-05 14:46:54 -08:00
Christian Boltz
6417e87d59 dnsmasq profile - update for libvirt files
dnsmasq needs read access to more files in /var/lib/libvirt/dnsmasq/
(at least *.conf and *.addnhosts)

Since this directory contains only files that are intended for dnsmasq 
(also confirmed by Jim Fehlig, the SUSE libvirt maintainer), the best 
way is to just allow "/var/lib/libvirt/dnsmasq/* r,"

References: https://bugzilla.novell.com/show_bug.cgi?id=848215


+1'd for trunk and 2.8 by Jamie Strandboge <jamie@canonical.com>
2013-10-30 21:43:45 +01:00
John Johansen
68f86b7cfd On Ubuntu saucy fontconfig reads user configs from
$HOME/.config/fontconfig/conf.d/* and
$HOME/.config/fontconfig/fonts.conf

/etc/fonts/conf.d/50-user.conf:
        <!--
            Load per-user customization files where stored on XDG Base Directory
            specification compliant places. it should be usually:
              $HOME/.config/fontconfig/conf.d
              $HOME/.config/fontconfig/fonts.conf
        -->
        <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
        <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>


abstractions/fonts should allow read access to those files:

From: Felix Geyer debfx@ubuntu.com
Acked-by: John Johansen <john.johansen@canonical.com>
2013-10-14 16:31:38 -07:00
John Johansen
19a1f0aa8c Rev 2203 (rev 2097 on the 2.8 branch) created a regression such that
cache files will be written out even if the '--skip-bad-cache' option
is given and the cached features file differs from the features of
the currently running kernel. The patch below fixes the regression.

From: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-10-14 01:51:21 -07:00
John Johansen
3d8c3806e2 Add an option to create the cache directory if it is missing
Signed-off-by: John Johansen john.johansen@canonical.com
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2013-09-29 01:39:22 -07:00
John Johansen
fefb397c56 Moves the cache clearing logic into the create cache routine, because if
we are writing a new cache .features file the cache dir should be cleared
out.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2013-09-29 01:13:55 -07:00
John Johansen
f6a0a3c502 The parser is not correctly clearing cache files if cache-loc is specified.
Fix this and unify creation and use of cacheloc so that we can hopefully
avoid these bugs.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2013-09-23 15:26:51 -07:00
John Johansen
01bdac1444 The feature file is not being written to the proper location if the parameter
--cache-loc= is specified. This results in using the .features file from
/etc/apparmor.d/cache or always recompiling policy.

The former case is particularly bad as the .features file in
/etc/apparmor.d/cache/ may not correspond to the file in the specified
cache location.

bug: launchpad.net/bugs/1229393

Signed-off-by: John Johansen <john.johansen@canonical.com>
2013-09-23 14:56:16 -07:00
Christian Boltz
204a96ed58 aa-unconfined displays less unconfined processes in some languages (for
example with LANG=pt_BR) because a regex relies on netstat output.

Enforce LANG=C to make sure aa-unconfined always sees the expected output.

Acked-by: Steve Beattie <steve@nxnw.org>
2013-09-20 13:23:47 +02:00
Christian Boltz
c854a5b81e fix broken URLs in various utils/*.pod files.
(The broken URLs were introduced in r1582.)

for utils/*.pod:
  Acked-by: Steve Beattie <steve@nxnw.org> 

for the other directories:
  Patch by Steve Beattie
  Acked-by: Christian Boltz <apparmor@cboltz.de>
2013-09-19 21:21:43 +02:00
Christian Boltz
dcde62755e ntpd needs read access to openssl.cnf
Patch-Author: Stefan Seyfried <seife+obs@b1-systems.com>

After this change in ntp:

* Mo Aug 19 2013 crrodriguez@opensuse.org
- Build with -DOPENSSL_LOAD_CONF , ntp must respect and use
  the system's openssl configuration.

we need to read openssl.cnf or starting of ntpd will fail silently(!)


Patch v2 by Christian Boltz: use abstractions/openssl instead of
allowing /etc/ssl/openssl.cnf directly

Acked-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-09-17 00:25:59 +02:00
Christian Boltz
8d597e7b07 fix some (mis)translations in utils/po/de.po
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-09-14 00:39:03 +02:00
Jamie Strandboge
b1f45986d8 p11-kit needs access to /usr/share/p11-kit/modules
Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org> (for trunk and 2.8)
2013-09-12 09:25:56 -05:00
Steve Beattie
fc3c98532b profiles - Allow reading /etc/machine-id in the dbus-session abstraction.
Merge from trunk commit rev 2181
From: intrigeri <intrigeri@boum.org>

D-Bus now uses /etc/machine-id in some cases:
https://bugs.freedesktop.org/show_bug.cgi?id=35228

Acked-by: Steve Beattie <steve@nxnw.org>
2013-09-11 16:05:13 -07:00
Christian Boltz
d2d79c0777 use grep instead of ~~ (smartmatch)
Patch by Kshitij Gupta <kgupta8592@gmail.com>

A previous bugreport [1] was fixed using the smartmatch operator,
which raised the minimum Perl version requirement to >=5.10.1 .
However in Perl5.18 the smartmatch operator has again become
"experimental" [2] so the following patch replace smartmatch operator
with grep and thereby avoiding the requirement hike and avoiding
warnings.

[1] https://bugs.launchpad.net/apparmor/+bug/1180230

[2] http://blogs.perl.org/users/mike_b/2013/06/a-little-nicer-way-to-use-smartmatch-on-perl-518.html

ACKed-by: Christian Boltz <apparmor@cboltz.de>
2013-08-23 22:04:45 +02:00
Seth Arnold
3b47558827 Bump libapparmor's AA_LIB_REVISION in preparation for 2.8.2 release.
Bump common/Version in preparation for 2.8.2 release.
2013-08-15 16:14:58 -07:00
Steve Beattie
2fec3758ed Subject: [patch] fix apparmor cache tempfile location to use passed arg v2
Merge from trunk revision 2142

This patch fixes problems in the handling of both the final cache
name location and the temporary cache file when an alternate location
is specified.

The first issue is that if the alternate cache directory location was
specified, the alternate directory name would be used as the final
location for the cache file, rather than the alternate directory +
the basename of the profile.

The second issue is that it would generate the temporary file that it
stores the cache file in [basedir]/cache even if an alternate cache
location was specified on the command line. This causes a problem
if [basedir]/cache is on a separate device than the alternate cache
location, because the rename() of the tempfile into the final location
would fail (which the parser would not check the return code of).

This patch fixes the above by incorporating the basename into the cache
file name if the alternate cache location has been specified, bases the
temporary cache file name on the destination cache name (such that they
end up in the same directory), and finally detects if the rename fails
and unlinks the temporary file if that happens (rather than leave it
around). It also has been updated to add a couple of testcases to verify
that writing and reading from an alternate cache location work.

Patch history:
  v1: first draft of patch
  v2: add testcases, convert PERROR() to pwarn() if rename() fails for
      placing cachefile into place.

For 2.8 branch:

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-07-29 09:52:18 -07:00
Seth Arnold
09c2da3a69 Fix $options -> @options in previous patch. Fix tabs -> spaces.
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-07-09 16:03:09 -07:00
Seth Arnold
9d5269b601 Merge intrigeri's abstractions/fonts improvements 2013-07-08 17:45:20 -07:00
Seth Arnold
28a97bf3c5 Kshitij Gupta fixed a display bug in aa-logprof, aa-genprof, with the Glob
and Glob with Ext putting duplicate entries in the list.

The fix introduced a Perl 5.10.1 or higher dependency, so start documenting
minimum required versions of packages.

Acked-By: Christian Boltz <apparmor@cboltz.de>
2013-07-07 18:33:48 -07:00
Seth Arnold
b77a05aa52 Fix potential NULL-write in aa_getprocattr() error path
https://bugs.launchpad.net/apparmor/+bug/1196880

Patch by Gernot Vormayr <gvormayr@gmail.com>

Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-07-02 11:53:31 -07:00
Steve Beattie
2c6e1b6e0f Subject: libapparmor - use python-config if it exists when configuring
Merge from trunk commit 2108

Author: Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com>
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

Modifiy the libapparmor macro for python to use python-config if it
exists to determine what CPPFLAGS and LDFLAGS to use when building
the python swig libraries. Without this addition, python detection
fails on ubuntu 13.04. I've confirmed that with this patch applied,
the python libraries still build successfully on older releases as well
(as far back as ubuntu 11.10).
2013-07-02 10:35:36 -07:00
Christian Boltz
b0fd46af26 add Dolphin (default Kubuntu file manager) to the list of file managers in
abstractions/ubuntu-browsers.d/ubuntu-integration.

Patch by Felix Geyer <debfx@ubuntu.com>

Acked-by: Seth Arnold <seth.arnold at canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de> 

(backport of trunk r2133)
2013-07-01 17:51:11 +02:00
Christian Boltz
9687641741 merge https://code.launchpad.net/~kensington/apparmor/apparmor/+merge/169010
Michael Palimaka 2013-06-13 Add missing key shortcuts for hu linguas.

(backport of trunk r2132)
2013-07-01 17:45:50 +02:00
Seth Arnold
6e67ef7cc3 Move poppler's cMaps from gnome to fonts; gnome includes fonts
Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-05-30 14:46:31 -07:00
Jamie Strandboge
76e23529af cherrypick r2119 from trunk:
deny writes to upstart user sessions jobs in abstractions/private-files

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-13 14:58:28 -05:00
Jamie Strandboge
d345d4a93a cherrypick r2118 from trunk:
add @{HOME}/.gnome2/keyrings/** to abstractions/private-files-strict

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-13 14:57:35 -05:00
Christian Boltz
bd09ea910b Backport the python3 compability changes from trunk r2052 to
the 2.8 branch.

Original commit message:
    committer: Jamie Strandboge <jamie@canonical.com>
    Initial port to python3 for utilities. Thanks to Dmitrijs Ledkovs
    Acked-By: Jamie Strandboge <jamie@canonical.com>

Most of trunk r2052 also applies to the 2.8 branch. The only difference
is the last section of changes in utils/vim/create-apparmor.vim.py

Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
Skimmed-by: Seth Arnold <seth.arnold@canonical.com>
2013-05-07 22:38:18 +02:00
John Johansen
18d66a09f6 This is a minimal fix to apparmor 2.8 for cache failures when the feature
file is larger than the feature buffer used for cache version comparison.

Ideally this would be dynamically allocated but for 2.8 just bumping the
buffer size is the quick fix.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-02 11:30:19 -07:00
Jamie Strandboge
5d439f2fcc cherrypick 2111 from trunk:
add read access to @{PROC}/sys/vm/overcommit_memory as used by glibc. See
  http://sourceware.org/git/?p=glibc.git;a=commit;h=9fab36eb583c0e585e83a01253299afed9ea9a11

Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2013-04-09 08:18:40 -05:00
Jamie Strandboge
e9353b757c cherrypick r2110 from trunk:
update pulseaudio directory and cookie file paths

Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2013-04-09 08:17:39 -05:00
Christian Boltz
8029059d73 Add missing permissions to the nscd profile.
Also deny capability block_suspend because nobody can imagine why it 
would be needed.

References: https://bugzilla.novell.com/show_bug.cgi?id=807104

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

(backport of trunk r2109)
2013-03-05 22:12:37 +01:00
Christian Boltz
05251eef06 abstractions/mysql: changed paths and MariaDB support
abstractions/mysql  contains
   /var/lib/mysql/mysql.sock rw,
   /usr/share/mysql/charsets/ r,
   /usr/share/mysql/charsets/*.xml r,

but the files moved (at least on openSUSE) to
    /usr/share/mysql-community-server/charsets/*.xml
    /var/run/mysql/mysql.sock
This causes denials for all applications using MySQL on 12.2 and 
Factory.

MariaDB has the *.xml files in
    /usr/share/mariadb/charsets/*.xml
and also seems to use /var/run/mysql/ for the socket.

Since MariaDB is basically a drop-in replacement for MySQL, it makes
sense to allow access to it via abstractions/mysql.

References: https://bugzilla.novell.com/show_bug.cgi?id=798183

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-01-13 14:41:56 +01:00
Steve Beattie
3158465820 Bump libapparmor's AA_LIB_REVISION in preparation for 2.8.1 release. 2013-01-09 16:23:51 -08:00
Steve Beattie
a27cd136b6 prepare for 2.8.1 release 2013-01-09 15:36:12 -08:00
Steve Beattie
e7e6aa9ed2 Subject: profiles - adjust pulseaudio in abstraction
Merge from trunk commit 2102

Original message:
  I was testing out a profile for pulseaudio and hit an issue where my
  pulseaudio process was getting the firefox profile applied to it. This
  is because in abstractions/ubuntu-browsers.d/multimedia the rule for
  pulseaudio is /usr/bin/pulseaudio ixr; attached is a patch to change it
  to Pixr, so as to use a global pulseaudio policy if it exists.

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-09 15:15:59 -08:00
John Johansen
e478b9b37d The following patch extends the libraries log parsing to support more date
time formats. As this is causing failures on some systems

currently the only supported format is
  <Month> ## hh:mm:ss

extend this to
  <Month> ## hh:mm:ss(.ms)?((+|-)timezone)?

  yyyy-mm-dd hh:mm:ss(.ms)?((+|-)timezone)?

  yyyy-mm-ddThh:mm:ss(.ms)?((+|-)timezone)?
2013-01-08 12:51:07 -08:00
Steve Beattie
98a1594e88 Subject: aa-decode test script
Merge from trunk commit 2077

Original message:
  Subject: aa-decode test script v3
  
  This patch adds a test script/driver for the aa-decode utility. The only
  change from the previous versions is to support overriding the location
  of the aa-decode to test via the APPARMOR_DECODE environment variable
  and documenting the utils/ tests in the top level README.
  
  The aa-decode test can be run directly from the commandline in the utils
  directory like so:
  
    test/test-aa-decode.py -v
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Christian Boltz <apparmor@cboltz.de>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Christian Boltz <apparmor@cboltz.de>
2013-01-04 15:06:47 -08:00
Steve Beattie
e6614df4a5 Backported merge of various fixes from trunk in preparation of the 2.8.1
release. In this merge are the following trunk commits:

2050 - parser - network rules debugging statements
2057 - update ubuntu-browsers.d/java for IcedTea 7
2058 - let sanitized-helper also allow access to /usr/local
2059 - ubuntu-integration does not work properly with exo-open
2062 - support alternate ping install location in /usr
2064 - parser - update apparmor_parser man page
2065 - parser - correct apparmor_parser -N command privilege
2066 - parser - *just* the updated caching test message from this commit
2065.1.1 - profiles update fonts abstraction for new fontconfig paths
2065.1.{3,4} - profiles - Gnome applications are now quite interested
       in reading /usr/share/poppler/cMap/**
2069 - profiles - update extras README with mail list info
2074 - tests - fix clone test on arm
2076 - parser tests - fix test driver for exec() failure
2079 - libapparmor - add pkgconfig support
2083 - parser tests - fix fine grained timestamp detection in caching tests
2090 - nvidia abstractions cleanups
2092 - update skype profile
2093 - add XCompose to abstractions/X
2096 - dnsmasq network-manager integration
2013-01-04 10:11:00 -08:00
Steve Beattie
701537325e Subject: dnsmasq network-manager integration
Merge from trunk commit 2096

Original message:
  Subject: profiles - dnsmasq: allow writes to
   /{,var/}run/sendsigs.omit.d/*dnsmasq.pid for network manager
   integration
  
  Author: Jamie Strandboge <jamie@canonical.com>
  Description: allow writes to /{,var/}run/sendsigs.omit.d/*dnsmasq.pid
   for network manager integration
  Bug-Ubuntu: https://launchpad.net/bugs/941808
  
  Acked-by: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:46:39 -08:00
Steve Beattie
dca6359ad5 Subject: add XCompose to abstractions/X
Merge from trunk commit 2093

Original message:
  Subject: profiles - add user's XCompose file to X abstraction
  
  In testing the skype profile, I found access to my @{HOME}/.XCompose
  was being rejected. This patch updates the X abstraction to take a
  user's defined XCompose key shortcuts into account.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:45:19 -08:00
Steve Beattie
6e02694f6f Subject: update skype profile
Merge from trunk commit 2092 (w/ dropping the last modified timestamp
entirely)

Original message:
  Subject: profiles - update skype profile
  
  Author: Jamie Strandboge <jamie@canonical.com>
  Bug-Ubuntu: https://launchpad.net/bugs/933440 Forwarded: yes
  
  This is a very slightly updated version of the skype profile
  update that Jamie Strandboge submitted, but did not get a review.
  The only addition over the previously submitted version is rw access
  to @{HOME}/.config/Skype/Skype.conf.
  
  (This commit incorporates the additional @{HOME}/.kde4 change proposed
  by Christian Boltz <apparmor@cboltz.de>)
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:38:29 -08:00
Steve Beattie
fc6889ae8e Subject: nvidia abstractions cleanups
Merge from trunk commit 2090

Original message:
  Subject: profiles - nvidia abstraction cleanups
  
  This patch modifies the nvidia abstraction to add the livdpau wrapper
  config file for nvidia workarounds. It also converts the /proc/
  rules to use the @{PROC} tunable. And finally, it converts the
  ubuntu-browsers.d/multimedia abstraction to use the nvidia abstraction.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:34:43 -08:00
Steve Beattie
0a97828f30 Subject: parser tests - fix fine grained timestamp detection in
caching tests

Merge from trunk commit 2083

Original message:
  This patch modifies the parser's caching test to more accurately detect
  whether or not the filesystem has a fine enough timestamp resolution.
  Occasionally even on filesystems like ext3, the two files' creation
  dates would differ when created less than a second apart, which would
  typically cause the 'Cache is used when cache is newer' test to fail
  because the cached file would have the same timestamp as the profile.
  
  The fix creates 10 files 0.1 seconds apart and ensures that all ten
  have distinct timestamps.
  
  (The occasional failure was caught in testing runs like
   https://bugs.launchpad.net/qa-regression-testing/+bug/1087061/ )
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-by: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:28:44 -08:00
Steve Beattie
84e7cdb5ee Subject: libapparmor - add pkgconfig support
Merge from trunk commit 2079

Original message:
  Given that we want to do more apparmor things in user space (dbus
  mediation, file picker, etc.), making it easier for other source bases
  to detect the presence of libapparmor would be beneficial. This patch
  adds pkg-config support to the build infrastructure for libapparmor.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-by: Kees Cook <kees@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:26:27 -08:00
Steve Beattie
6654dfe251 Subject: parser tests - fix test driver for exec() failure
Merge from trunk commit 2076

Original message:
  Subject: two fixes to the parser's simple test driver
  
  This patch fixes two issue with the simple test driver. The first is
  that child exec that actually ran the parser was located inside the
  eval statement. This meant that if the exec failed for some reason
  (like the parser didn't exist), the child wouldn't actually die,
  but would pop out of the eval and continue running through the loop
  of test profiles (while the parent process does the same). This meant
  that if the script ran on the full testsuite with a misconfiguration,
  it would explode creating O(n^2) processes, where n is the number of
  testcase files -- with over 25k testcases, that's a lot. The fis is to
  lift the child exec outside the eval{}, then an exec() failure causes
  the child process to die correctly.
  
  The second fix is that several of the testcases were added with the
  DESCRIPTION field added in lower case (i.e. #=Description blah blah).
  This fix makes the regex that pulls out the description not be
  case-sensitive.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:22:00 -08:00
Steve Beattie
a99e93c412 Subject: tests - fix clone test on arm
Merge from trunk commit 2074.

Original message:
  apparmor: Fix clone test on quantal arm omap-4
  
  It turns out that PAGE_SIZE isn't defined on all architectures.
  
  This fixes a regression test failure happening on Ubuntu quantal
  on the arm ti-omap4 architecture.
  
  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:47:10 -08:00
Steve Beattie
ae12cc8e42 Subject: update mailing list address in extras README
Merge mailing list update from profiles/apparmor/profiles/extras/README
in trunk commit 2069.

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:43:41 -08:00
Steve Beattie
590a39e194 Subject: update gnome abstraction to allow reading
/usr/share/poppler/cMap/**

Merge from trunk commit 2065.1.3

Original message:
  Gnome applications are now quite interested in reading
  /usr/share/poppler/cMap/**. These files are included in the poppler-data
  package on Ubuntu, and their 'r' denials create quite a bit of noise.
  Apparently they are needed to display PDF documents containing CJK
  characters with libpoppler. I added it to the gnome abstraction because
  several applications not linked against poppler are consulting this
  data.
  
  Acked-By: Jamie Strandboge <jamie@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:34:57 -08:00
Steve Beattie
0da19a9474 Subject: update fonts abstraction for new fontconfig paths
Merge from trunk commit 2065.1.1.

Original message:
  update fonts abstraction for new fontconfig paths
  
  Acked-By: Jamie Strandboge <jamie@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:27:15 -08:00
Steve Beattie
06aa9b0a54 Subject: update caching test message
Merge from just the parser/tst/caching.sh portion of trunk commit 2066.

Original message:
  apparmor: abstract out the directory walking routine
  
  The apparmor_parser has 3 different directory walking routines.
Abstract
  them out and use a single common routine.
  
  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>
 
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:20:14 -08:00
Steve Beattie
76925a236c Merge from trunk commit 2065:
Original message:
  apparmor: correct apparmor_parser -N command privilege

  Fix the apparmor_parsers -N command (which dumps the list of profile
  names found in a policy file) to be available without privilege and
  also make it be recognized as a command instead of an option so that
  it can conflict with -a -r -R -S and -o.

  Currently it can be specified with these commands but will cause the
  parser to short circuit just dumping the names and not doing the actual
  profile compile or load.

  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:12:20 -08:00
Steve Beattie
626b9a9d36 Merge from trunk commit 2064:
Original message:
  apparmor: update apparmor_parser man page

  Rework and update the apparmor_parser man page. It reworks some of the
  text but mostly just reorganizes the commands and options into logical
  grouping to make it easier to sort out how the various commands and
  options work.

  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:58:28 -08:00
Steve Beattie
4fdb2dd24e Merge from trunk commit 2062:
Original message:
  /bin/ping moved to /usr/bin/ping on openSUSE (usrMerge)
  Update the profile to make sure it's still used.

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

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:55:57 -08:00
Steve Beattie
6e0996981b Merge from trunk commit 2059:
Original message:
  Author: Mark Ramsell <mramsell@qazonline.net>
  Description: ubuntu-integration does not work properly with exo-open
  Bug-Ubuntu: https://launchpad.net/bugs/987578

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:54:16 -08:00
Steve Beattie
8e33b4a173 Merge from trunk commit 2058:
Original message:
  Description: let sanitized-helper also allow access to /usr/local.
    Patch based on work by Reuben Thomas
  Bug-Ubuntu: https://launchpad.net/bugs/1013887

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:44:14 -08:00
Steve Beattie
3e18698c78 Merge from trunk commit 2057:
Original message:
  Description: update ubuntu-browsers.d/java for IcedTea 7
  Bug-Ubuntu: https://launchpad.net/bugs/1003856

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:37:41 -08:00
Steve Beattie
0fc26d7c47 Merge from trunk commit 2050:
Original Message:
  While integrating 3.4-rc1, I ran into a problem where network rules
  weren't being processed. It ultimately boiled down to a kernel
  issue but I found it useful to see what the parser thought it was
  working with. Since the parser already has a debugging mode that
  will show things like capabilities, it was an obvious extension to
  add network rules.

  Signed-off-by: Jeff Mahoney <jeffm@suse.com>
  Acked-by: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 14:38:38 -08:00
Christian Boltz
78cd88c56d fix aa-decode by backporting all changes from trunk to 2.8 branch
Acked-By: John Johansen (up to r2072)
Acked-by: Steve Beattie <sbeattie@ubuntu.com> (including r2088)


In detail, the changes are (bzr log from trunk):
------------------------------------------------------------
revno: 2088
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Tue 2013-01-01 20:15:04 +0100
message:
  speed up aa-decode by using a bash regex matching instead of calling egrep for each line.

  Acked-by: Steve Beattie <sbeattie@ubuntu.com>

  (Patch sent 2012-11-01, Acked-by from 2013-01-01)
------------------------------------------------------------
revno: 2072
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Tue 2012-10-16 00:19:49 +0200
message:
  Fix aa-decode handling of stdin

  Handling stdin was totally broken (= no output) with the current log
  format because aa-decode expected name= to be the last entry in the
  log line.

  This patch for stdin handling
  - fixes the pattern to match the current log format (name= is NOT the
    last part in the log entry)
  - uses bash replacement to avoid some sed calls (which also means the
    script now needs an explicit "#!/bin/bash")
  - prints decoded filenames in double instead of single quotes to be
    consistent with filenames that were not encoded
  - also prints lines that do not contain an encoded filename (instead of
    grepping them away)
  - replace tr calls by perl's uc() (also for non-stdin mode)
  - also handle encoded profile names (introduced by Steve)
  - don't fail if a file or profile name contains a '

  In other words: you can pipe your audit.log through aa-decode, and the
  only difference to the raw audit.log is that filenames are decoded.


  Acked-By: Steve Beattie <sbeattie@ubuntu.com>
------------------------------------------------------------
revno: 2068
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Mon 2012-09-17 23:55:28 +0200
message:
  fix error handling in aa-decode

  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

  Looks-Good-By: ;-)  Seth Arnold <seth.arnold@gmail.com>
------------------------------------------------------------
2013-01-01 20:26:19 +01:00
John Johansen
c48e4a76d3 Add a small sleep call to the onexec test to give the forked process a
chance to run before verifying it's current and future confinement
state. In testing the combined sleeps added roughly a second to
onexec.sh's total time on relatively reasonable hardware.

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com> (via IRC)
2012-12-19 05:38:49 -08:00
Christian Boltz
bbaa1fa6d1 add CAP_BLOCK_SUSPEND to severity.db
(backported from trunk)

Acked-by: John Johansen <john.johansen@canonical.com>
2012-12-17 13:34:41 +01:00
Steve Beattie
ecd14e46b9 Add a testcase for the issue fixed in commit 2059.
Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2012-12-10 17:01:24 -08:00
John Johansen
e0c94c9039 fix a nasty little bug that can surface in apparmor 2.8 when
Hats/children profiles are used.

the matchflags in the dfa backend are not getting properly reset, which
results in a previously processed profiles match flags being used. This is
not a problem for most permissions but can result in x conflict errors.

Note: this should not result in profiles with the wrong x transitions loaded
as it causes compilation to file with an x conflict.

This is a minimal patch targeted at the 2.8 release. As such I have just
updated the delete_ruleset routine to clear the flags as it is already
being properly called for every rule set.

Apparmor 2.9/3.0 will have a different approach where it is not possible
to reuse the flags.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2012-12-10 15:12:22 -08:00
John Johansen
b5c6e11aca Add kernel patches for 3.5 and 3.6 kernels 2012-11-20 17:00:59 -08:00
John Johansen
fd6a33f89e Update documentation of change_hat and change_profile apis
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@gmail.com>
2012-11-20 16:52:43 -08:00
John Johansen
276ef3facf So the library version has not been being correctly bumped.
Make this a little bit easier to follow

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2012-10-12 11:41:51 -07:00
John Johansen
4a42d74351 The apparmor coredump regression test was broken.
- It failed to remove coredump files named "core"
- It failed to properly detect "core.<pid>" files
- And it would fail if the coredump_pattern had been modified to
  a different location.

This lead one of the tests to report it was passing when it
wasn't because it was detecting the previous tests core file.

- Fix the test to set the coredump_pattern, to dump into the
  tmpdir used for the test.
- Make it so it will only detect the core file for the pid of
  the last test run.
- And extend the test to have a couple of extra test cases.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
2012-10-01 10:57:11 -07:00
John Johansen
00bf73f7c2 apparmor: add clearing the profile cache when inconsistent
Add the ability to clear out the binary profile cache. This removes the
need to have a separate script to handle the logic of checking and
removing the cache if it is out of date.

The parser already does all the checking to determine cache validity
so it makes sense to allow the parser to clear out inconsistent cache
when it has been instructed to update the cache.

Signed-off-by: John Johnansen <john.johansen@canonical.com>
2012-08-09 00:37:25 -07:00
Christian Boltz
b0a05c5b3d ls moved from /bin/ to /usr/bin/ on openSUSE (usrMove)
Acked-by: John Johansen <john.johansen@canonical.com>
2012-08-06 13:57:22 +02:00
John Johansen
563a49adc4 The previous patch to fix policy compilation around the network flag had a
serious flaw. The test for the network flag was being applied against both
the kernel flags and the cache flags. This means that if either the kernel
or the cache did not have the flag set then network mediation would be
turned off.

Thus if a kernel was booted without the flag, and a cache was generated
based on that kernel and then the system was rebooted into a kernel with
the network flag present, the parser on generating the new policy would
detect the old cache did not support network and turn it off for the
new policy as well.

This can be fixed by either removing the old cache first or regenerating
the cache twice. As the first generation will write that networking is
supported in the cache (even though the policy will have it disabled), and
the second generation will generate the correct policy.

The following patch moves the test so that it is only applied to the kernel
flags set.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-07-17 16:00:53 -07:00
John Johansen
107b5113bd Fix the parser so it checks for the presence of the network feature in the
compatibility interface. Previously it was assuming that if the compatibility
interface was present that network rules where also present, this is not
necessarily true and causes apparmor to break when only the compatibility
patch is applied.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
2012-07-01 01:35:05 -07:00
John Johansen
c1c1b229c1 Have build check for presence of awk and fail with a sensible error message
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2012-06-29 16:42:39 -07:00
John Johansen
9fbfa4c7e0 Original Author: mancha@mancha.user.oftc.net
create-apparmor.vim.py was failing on systems with python 2.5, fix that
    
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2012-06-08 14:27:05 -07:00
Steve Beattie
77de4e26cd update REPO_URL for 2.8 branch 2012-05-31 11:32:33 -07:00
186 changed files with 6002 additions and 440 deletions

View File

View File

@@ -12,7 +12,9 @@ DIRS=parser \
changehat/pam_apparmor \
tests
REPO_URL?=lp:apparmor
#REPO_URL?=lp:apparmor/2.8
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.8
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"

32
README
View File

@@ -146,6 +146,20 @@ For details on structure and adding tests, see libraries/libapparmor/README.
$ cd libraries/libapparmor
$ make check
Utils
-----
There are some simple tests available, including basic perl syntax
checks for the perl modules and executables. There are also minimal
checks on the python utilities and python-based tests in the test/
subdirectory.
$ cd utils
$ make check
The aa-decode utility to be tested can be overridden by
setting up environment variable APPARMOR_DECODE; e.g.:
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
Profile checks
--------------
A basic consistency check to ensure that the parser and aa-logprof parse
@@ -184,3 +198,21 @@ Building and Installing AppArmor Kernel Patches
TODO
-----------------
Required versions
-----------------
The AppArmor userspace utilities are written with some assumptions about
installed and available versions of other tools. This is a (possibly
incomplete) list of known version dependencies:
AppArmor.pm (used by aa-audit, aa-autodep, aa-complain, aa-disable,
aa-enforce, aa-genprof, aa-logprof, aa-unconfined) requires minimum
Perl 5.10.1.
Python scripts require minimum Python 2.7. Some utilities may require
Python 3.3. Python 3.0, 3.1, 3.2 are largely untested.
Most shell scripts are written for POSIX-compatible sh. aa-decode expects
bash, probably version 3.2 and higher.

View File

@@ -17,6 +17,7 @@
#include "http_config.h"
#include "http_request.h"
#include "http_log.h"
#include "http_main.h"
#include "http_protocol.h"
#include "util_filter.h"
#include "apr.h"
@@ -35,9 +36,18 @@
#define DEFAULT_HAT "HANDLING_UNTRUSTED_INPUT"
#define DEFAULT_URI_HAT "DEFAULT_URI"
/* Compatibility with apache 2.2 */
#if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3
#define APLOG_TRACE1 APLOG_DEBUG
server_rec *ap_server_conf = NULL;
#endif
#ifdef APLOG_USE_MODULE
APLOG_USE_MODULE(apparmor);
#endif
module AP_MODULE_DECLARE_DATA apparmor_module;
static unsigned int magic_token = 0;
static unsigned long magic_token = 0;
static int inside_default_hat = 0;
typedef struct {
@@ -68,9 +78,10 @@ immunix_init (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
apr_file_read (file, (void *) &magic_token, &size);
apr_file_close (file);
} else {
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to open /dev/urandom");
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
"Failed to open /dev/urandom");
}
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "Opened /dev/urandom successfully");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "Opened /dev/urandom successfully");
return OK;
}
@@ -83,35 +94,32 @@ immunix_child_init (apr_pool_t *p, server_rec *s)
{
int ret;
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "init: calling change_hat");
ret = change_hat (DEFAULT_HAT, magic_token);
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
"init: calling change_hat with '%s'", DEFAULT_HAT);
ret = aa_change_hat(DEFAULT_HAT, magic_token);
if (ret < 0) {
change_hat (NULL, magic_token);
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to change_hat to '%s'",
DEFAULT_HAT);
aa_change_hat(NULL, magic_token);
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
"Failed to change_hat to '%s'", DEFAULT_HAT);
} else {
inside_default_hat = 1;
}
}
#ifdef DEBUG
static void
debug_dump_uri (apr_uri_t * uri)
debug_dump_uri(request_rec *r)
{
if (uri)
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Dumping uri info "
apr_uri_t *uri = &r->parsed_uri;
if (uri)
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
uri->scheme, uri->hostname, uri->path, uri->query,
uri->fragment);
else
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Asked to dump NULL uri");
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
}
#else
static void
debug_dump_uri (apr_uri_t * __unused uri) { }
#endif
/*
immunix_enter_hat will attempt to change_hat in the following order:
(1) to a hatname in a location directive
@@ -129,8 +137,8 @@ immunix_enter_hat (request_rec *r)
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config (r->server->module_config, &apparmor_module);
debug_dump_uri (&r->parsed_uri);
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
debug_dump_uri(r);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "in immunix_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
(unsigned long) r->main);
@@ -139,41 +147,48 @@ immunix_enter_hat (request_rec *r)
return OK;
if (inside_default_hat) {
change_hat (NULL, magic_token);
aa_change_hat(NULL, magic_token);
inside_default_hat = 0;
}
if (dcfg != NULL && dcfg->hat_name != NULL) {
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [dcfg] %s", dcfg->hat_name);
sd_ret = change_hat (dcfg->hat_name, magic_token);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [dcfg] %s", dcfg->hat_name);
sd_ret = aa_change_hat(dcfg->hat_name, magic_token);
if (sd_ret < 0) {
change_hat (NULL, magic_token);
aa_change_hat(NULL, magic_token);
} else {
return OK;
}
}
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [uri] %s", r->uri);
sd_ret = change_hat (r->uri, magic_token);
if (scfg) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
"scfg='0x%lx' scfg->hat_name='%s'",
(unsigned long) scfg, scfg->hat_name);
} else {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
}
if (scfg != NULL && scfg->hat_name != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [scfg] %s", scfg->hat_name);
sd_ret = aa_change_hat(scfg->hat_name, magic_token);
if (sd_ret < 0) {
aa_change_hat(NULL, magic_token);
} else {
return OK;
}
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [uri] %s", r->uri);
sd_ret = aa_change_hat(r->uri, magic_token);
if (sd_ret < 0) {
change_hat (NULL, magic_token);
aa_change_hat(NULL, magic_token);
} else {
return OK;
}
if (scfg != NULL && scfg->hat_name != NULL) {
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [scfg] %s", scfg->hat_name);
sd_ret = change_hat (scfg->hat_name, magic_token);
if (sd_ret < 0) {
change_hat (NULL, magic_token);
} else {
return OK;
}
}
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat DEFAULT_URI");
sd_ret = change_hat (DEFAULT_URI_HAT, magic_token);
if (sd_ret < 0) change_hat (NULL, magic_token);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat DEFAULT_URI");
sd_ret = aa_change_hat(DEFAULT_URI_HAT, magic_token);
if (sd_ret < 0) aa_change_hat(NULL, magic_token);
return OK;
}
@@ -186,14 +201,15 @@ immunix_exit_hat (request_rec *r)
ap_get_module_config (r->per_dir_config, &apparmor_module);
/* immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config (r->server->module_config, &apparmor_module); */
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "exiting change_hat - dir hat %s path %s", dcfg->hat_name, dcfg->path);
change_hat (NULL, magic_token);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "exiting change_hat: dir hat %s dir path %s",
dcfg->hat_name, dcfg->path);
aa_change_hat(NULL, magic_token);
sd_ret = change_hat (DEFAULT_HAT, magic_token);
sd_ret = aa_change_hat(DEFAULT_HAT, magic_token);
if (sd_ret < 0) {
change_hat (NULL, magic_token);
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to change_hat to '%s'",
DEFAULT_HAT);
aa_change_hat(NULL, magic_token);
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
"Failed to change_hat to '%s'", DEFAULT_HAT);
} else {
inside_default_hat = 1;
}
@@ -204,7 +220,7 @@ immunix_exit_hat (request_rec *r)
static const char *
aa_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "config change hat %s",
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "directory config change hat %s",
parm1 ? parm1 : "DEFAULT");
immunix_dir_cfg * dcfg = mconfig;
if (parm1 != NULL) {
@@ -221,7 +237,7 @@ static const char *
immunix_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
{
if (path_warn_once == 0) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "ImmHatName is "
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmHatName is "
"deprecated, please use AAHatName instead");
path_warn_once = 1;
}
@@ -231,9 +247,10 @@ immunix_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
static const char *
aa_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "config change hat %s",
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "server config change hat %s",
parm1 ? parm1 : "DEFAULT");
immunix_srv_cfg * scfg = mconfig;
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config(cmd->server->module_config, &apparmor_module);
if (parm1 != NULL) {
scfg->hat_name = parm1;
} else {
@@ -248,7 +265,7 @@ static const char *
immunix_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
{
if (srv_warn_once == 0) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "ImmDefaultHatName is "
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmDefaultHatName is "
"deprecated, please use AADefaultHatName instead");
srv_warn_once = 1;
}
@@ -260,9 +277,9 @@ immunix_create_dir_config (apr_pool_t * p, char * path)
{
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_create_dir (%s)", path ? path : ":no path:");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_create_dir (%s)", path ? path : ":no path:");
if (newcfg == NULL) {
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "immunix_create_dir: couldn't alloc dir config");
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "immunix_create_dir: couldn't alloc dir config");
return NULL;
}
newcfg->path = apr_pstrdup (p, path ? path : ":no path:");
@@ -277,7 +294,7 @@ immunix_merge_dir_config (apr_pool_t * p, void * parent, void * child)
{
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_merge_dir ()");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_merge_dir ()");
if (newcfg == NULL)
return NULL;
@@ -290,9 +307,9 @@ immunix_create_srv_config (apr_pool_t * p, server_rec * srv)
{
immunix_srv_cfg * newcfg = (immunix_srv_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_create_srv");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_create_srv");
if (newcfg == NULL) {
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "immunix_create_srv: couldn't alloc srv config");
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "immunix_create_srv: couldn't alloc srv config");
return NULL;
}

View File

@@ -72,11 +72,10 @@ behavior described above.
AADefaultHatName allows you to specify a default hat to be used for
virtual hosts and other Apache server directives, so that you can have
different defaults for different virtual hosts. This can be overridden by
the AAHatName directive and is checked for only if there isn't a matching
AAHatName or hat named by the URI. If the AADefaultHatName hat does not
exist, it falls back to the DEFAULT_URI hat if it exists (as described
above).
different defaults for different virtual hosts. This can be overridden
by the AAHatName directive and is checked for only if there isn't
a matching AAHatName. If the AADefaultHatName hat does not exist,
then it falls back to the behavior described above.
=back
@@ -96,11 +95,11 @@ will:
1. try to aa_change_hat(2) into a matching AAHatName hat if it exists and
applies, otherwise it will
2. try to aa_change_hat(2) into the URI itself, otherwise it will
3. try to aa_change_hat(2) into an AADefaultHatName hat if it has been defined
2. try to aa_change_hat(2) into an AADefaultHatName hat if it has been defined
for the server/vhost, otherwise it will
3. try to aa_change_hat(2) into the URI itself, otherwise it will
4. try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
will
@@ -115,7 +114,7 @@ with the prefork MPM configuration -- threaded configurations of Apache
may not work correctly.
There are likely other bugs lurking about; if you find any, please report
them at L<http://https://bugs.launchpad.net/apparmor/+filebug>.
them at L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO

View File

@@ -27,6 +27,15 @@
DISTRIBUTION=AppArmor
VERSION=$(shell cat common/Version)
AWK:=$(shell which awk)
ifndef AWK
$(error awk utility required for build but not available)
endif
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
map = $(foreach a,$(2),$(call $(1),$(a)))
# OVERRIDABLE variables
# Set these variables before including Make.rules to change its behavior
# SPECFILE - for packages that have a non-standard specfile name
@@ -127,6 +136,17 @@ endif
endif
ifndef PYTHON_VERSIONS
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
endif
ifndef PYTHON
PYTHON = $(firstword ${PYTHON_VERSIONS})
endif
#Helper function to be used with $(call pyalldo, run_test_with_all.py)
pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
.PHONY: version
.SILENT: version
version:

View File

@@ -1 +1 @@
2.8.0
2.8.5

View File

@@ -0,0 +1,285 @@
From 05bf1eb7276886a3eda0588a8e012b558b693e96 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Thu, 22 Jul 2010 02:32:02 -0700
Subject: [PATCH 1/6] UBUNTU: SAUCE: AppArmor: Add profile introspection file
to interface
Add the dynamic profiles file to the interace, to allow load policy
introspection.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
---
security/apparmor/Kconfig | 9 ++
security/apparmor/apparmorfs.c | 231 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 240 insertions(+)
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b..51ebf96 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
boot.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+ bool "Enable AppArmor 2.4 compatability"
+ depends on SECURITY_APPARMOR
+ default y
+ help
+ This option enables compatability with AppArmor 2.4. It is
+ recommended if compatability with older versions of AppArmor
+ is desired.
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 16c15ec..42b7c9f 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -182,6 +182,234 @@ const struct file_operations aa_fs_seq_file_ops = {
.release = single_release,
};
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ struct aa_namespace *parent;
+
+ /* is next namespace a child */
+ if (!list_empty(&ns->sub_ns)) {
+ struct aa_namespace *next;
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+ read_lock(&next->lock);
+ return next;
+ }
+
+ /* check if the next ns is a sibling, parent, gp, .. */
+ parent = ns->parent;
+ while (parent) {
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+ read_lock(&ns->lock);
+ return ns;
+ }
+ if (parent == root)
+ return NULL;
+ ns = parent;
+ parent = parent->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+static struct aa_profile *__first_profile(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ for ( ; ns; ns = __next_namespace(root, ns)) {
+ if (!list_empty(&ns->base.profiles))
+ return list_first_entry(&ns->base.profiles,
+ struct aa_profile, base.list);
+ }
+ return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+ struct aa_profile *parent;
+ struct aa_namespace *ns = p->ns;
+
+ /* is next profile a child */
+ if (!list_empty(&p->base.profiles))
+ return list_first_entry(&p->base.profiles, typeof(*p),
+ base.list);
+
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
+ parent = p->parent;
+ while (parent) {
+ list_for_each_entry_continue(p, &parent->base.profiles,
+ base.list)
+ return p;
+ p = parent;
+ parent = parent->parent;
+ }
+
+ /* is next another profile in the namespace */
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace (NOT NULL)
+ * @profile: current profile (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+ struct aa_profile *profile)
+{
+ struct aa_profile *next = __next_profile(profile);
+ if (next)
+ return next;
+
+ /* finished all profiles in namespace move to next namespace */
+ return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+ __acquires(root->lock)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *root = aa_current_profile()->ns;
+ loff_t l = *pos;
+ f->private = aa_get_namespace(root);
+
+
+ /* find the first profile */
+ read_lock(&root->lock);
+ profile = __first_profile(root, root);
+
+ /* skip to position */
+ for (; profile && l > 0; l--)
+ profile = next_profile(root, profile);
+
+ return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private;
+ (*pos)++;
+
+ return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+ __releases(root->lock)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private, *ns;
+
+ if (profile) {
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+ read_unlock(&ns->lock);
+ }
+ read_unlock(&root->lock);
+ aa_put_namespace(root);
+}
+
+/**
+ * seq_show_profile - show a profile entry
+ * @f: seq_file to file
+ * @p: current position (profile) (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_namespace *root = f->private;
+
+ if (profile->ns != root)
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+ return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
+
+static int profiles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int profiles_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+const struct file_operations aa_fs_profiles_fops = {
+ .open = profiles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = profiles_release,
+};
+#endif /* CONFIG_SECURITY_APPARMOR_COMPAT_24 */
+
/** Base file system setup **/
static struct aa_fs_entry aa_fs_entry_file[] = {
@@ -210,6 +438,9 @@ static struct aa_fs_entry aa_fs_entry_apparmor[] = {
AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops),
+#endif
AA_FS_DIR("features", aa_fs_entry_features),
{ }
};
--
1.7.10.4

View File

@@ -0,0 +1,603 @@
From 4facdf9db37c12ff655c91270d9030e2ed805ca2 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 4 Oct 2010 15:03:36 -0700
Subject: [PATCH 2/6] UBUNTU: SAUCE: AppArmor: basic networking rules
Base support for network mediation.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/.gitignore | 2 +-
security/apparmor/Makefile | 42 +++++++++-
security/apparmor/apparmorfs.c | 1 +
security/apparmor/include/audit.h | 4 +
security/apparmor/include/net.h | 44 ++++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++++
security/apparmor/net.c | 162 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 46 ++++++++++
10 files changed, 414 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 4d995ae..d5b291e 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -1,6 +1,6 @@
#
# Generated include files
#
-af_names.h
+net_names.h
capability_names.h
rlim_names.h
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 806bd19..19daa85 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o
+ resource.o sid.o file.o net.o
-clean-files := capability_names.h rlim_names.h
+clean-files := capability_names.h rlim_names.h net_names.h
# Build a lower case string table of capability names
@@ -20,6 +20,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
echo "};" >> $@
+# Build a lower case string table of address family names
+# Transform lines from
+# define AF_LOCAL 1 /* POSIX name for AF_UNIX */
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [1] = "local",
+# [2] = "inet",
+#
+# and build the securityfs entries for the mapping.
+# Transforms lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# #define AA_FS_AF_MASK "local inet"
+quiet_cmd_make-af = GEN $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
+ sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+ echo "};" >> $@ ;\
+ echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
+ sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
+ $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
+
+# Build a lower case string table of sock type names
+# Transform lines from
+# SOCK_STREAM = 1,
+# to
+# [1] = "stream",
+quiet_cmd_make-sock = GEN $@
+cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
+ sed $^ >>$@ -r -n \
+ -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+ echo "};" >> $@
# Build a lower case string table of rlimit names.
# Transforms lines from
@@ -56,6 +88,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
$(obj)/capability.o : $(obj)/capability_names.h
+$(obj)/net.o : $(obj)/net_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
$(src)/Makefile
@@ -63,3 +96,8 @@ $(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \
$(src)/Makefile
$(call cmd,make-rlim)
+$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
+ $(srctree)/include/linux/net.h \
+ $(src)/Makefile
+ $(call cmd,make-af)
+ $(call cmd,make-sock)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 42b7c9f..114fb23 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -429,6 +429,7 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
static struct aa_fs_entry aa_fs_entry_features[] = {
AA_FS_DIR("domain", aa_fs_entry_domain),
AA_FS_DIR("file", aa_fs_entry_file),
+ AA_FS_DIR("network", aa_fs_entry_network),
AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
{ }
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 4b7e189..17734f9 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -127,6 +127,10 @@ struct apparmor_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
};
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..cb8a121
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,44 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+#include "apparmorfs.h"
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+ u16 allow[AF_MAX];
+ u16 audit[AF_MAX];
+ u16 quiet[AF_MAX];
+};
+
+extern struct aa_fs_entry aa_fs_entry_network[];
+
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
+ int type, int protocol, struct sock *sk);
+extern int aa_revalidate_sk(int op, struct sock *sk);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+ /* NOP */
+}
+
+#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index bda4569..eb13a73 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -27,6 +27,7 @@
#include "capability.h"
#include "domain.h"
#include "file.h"
+#include "net.h"
#include "resource.h"
extern const char *const profile_mode_names[];
@@ -157,6 +158,7 @@ struct aa_policydb {
* @policy: general match rules governing policy
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
+ * @net: network controls for the profile
* @rlimits: rlimits for the profile
*
* The AppArmor profile contains the basic confinement data. Each profile
@@ -194,6 +196,7 @@ struct aa_profile {
struct aa_policydb policy;
struct aa_file_rules file;
struct aa_caps caps;
+ struct aa_net net;
struct aa_rlimit rlimits;
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8ea39aa..f628734 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -32,6 +32,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
+#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
@@ -614,6 +615,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
return error;
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
+ NULL);
+ return error;
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_BIND, sk);
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_CONNECT, sk);
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_LISTEN, sk);
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_ACCEPT, sk);
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SENDMSG, sk);
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_RECVMSG, sk);
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -646,6 +745,19 @@ static struct security_operations apparmor_ops = {
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .socket_create = apparmor_socket_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
+
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 0000000..003dd18
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,162 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "net_names.h"
+
+struct aa_fs_entry aa_fs_entry_network[] = {
+ AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
+ { }
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ audit_log_format(ab, " family=");
+ if (address_family_names[sa->u.net->family]) {
+ audit_log_string(ab, address_family_names[sa->u.net->family]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
+ }
+ audit_log_format(ab, " sock_type=");
+ if (sock_type_names[sa->aad->net.type]) {
+ audit_log_string(ab, sock_type_names[sa->aad->net.type]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
+ }
+ audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
+}
+
+/**
+ * audit_net - audit network access
+ * @profile: profile being enforced (NOT NULL)
+ * @op: operation being checked
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ * @sk: socket auditing is being applied to
+ * @error: error code for failure else 0
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+ int protocol, struct sock *sk, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa;
+ struct apparmor_audit_data aad = { };
+ struct lsm_network_audit net = { };
+ if (sk) {
+ sa.type = LSM_AUDIT_DATA_NET;
+ } else {
+ sa.type = LSM_AUDIT_DATA_NONE;
+ }
+ /* todo fill in socket addr info */
+ sa.aad = &aad;
+ sa.u.net = &net;
+ sa.aad->op = op,
+ sa.u.net->family = family;
+ sa.u.net->sk = sk;
+ sa.aad->net.type = type;
+ sa.aad->net.protocol = protocol;
+ sa.aad->error = error;
+
+ if (likely(!sa.aad->error)) {
+ u16 audit_mask = profile->net.audit[sa.u.net->family];
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+ !(1 << sa.aad->net.type & audit_mask)))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ u16 quiet_mask = profile->net.quiet[sa.u.net->family];
+ u16 kill_mask = 0;
+ u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
+
+ if (denied & kill_mask)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ if ((denied & quiet_mask) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
+ }
+
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @op: operation being checked
+ * @profile: profile being enforced (NOT NULL)
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
+ int protocol, struct sock *sk)
+{
+ u16 family_mask;
+ int error;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->net.allow[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ return audit_net(profile, op, family, type, protocol, sk, error);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @op: operation being checked
+ * @sk: sock being revalidated (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(int op, struct sock *sk)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* aa_revalidate_sk should not be called from interrupt context
+ * don't mediate these calls as they are not task related
+ */
+ if (in_interrupt())
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
+ sk->sk_protocol, sk);
+
+ return error;
+}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index cf5fd22..27c8161 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
aa_free_file_rules(&profile->file);
aa_free_cap_rules(&profile->caps);
+ aa_free_net_rules(&profile->net);
aa_free_rlimit_rules(&profile->rlimits);
aa_free_sid(profile->sid);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 329b1fd..1b90dfa 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -193,6 +193,19 @@ fail:
return 0;
}
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+ if (unpack_nameX(e, AA_U16, name)) {
+ if (!inbounds(e, sizeof(u16)))
+ return 0;
+ if (data)
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+ e->pos += sizeof(u16);
+ return 1;
+ }
+ return 0;
+}
+
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
if (unpack_nameX(e, AA_U32, name)) {
@@ -471,6 +484,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
+ size_t size = 0;
int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -564,6 +578,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
if (!unpack_rlimits(e, profile))
goto fail;
+ size = unpack_array(e, "net_allowed_af");
+ if (size) {
+
+ for (i = 0; i < size; i++) {
+ /* discard extraneous rules that this kernel will
+ * never request
+ */
+ if (i >= AF_MAX) {
+ u16 tmp;
+ if (!unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL))
+ goto fail;
+ continue;
+ }
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ }
+ /*
+ * allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ profile->net.allow[AF_UNIX] = 0xffff;
+ profile->net.allow[AF_NETLINK] = 0xffff;
+
if (unpack_nameX(e, AA_STRUCT, "policydb")) {
/* generic policy dfa - optional and may be NULL */
profile->policy.dfa = unpack_dfa(e);
--
1.7.10.4

View File

@@ -0,0 +1,38 @@
From 4b25e62dc1e8d81d80f778e1e57b7c38ba4fd901 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 29 Jun 2012 17:34:00 -0700
Subject: [PATCH 3/6] apparmor: Fix quieting of audit messages for network
mediation
If a profile specified a quieting of network denials for a given rule by
either the quiet or deny rule qualifiers, the resultant quiet mask for
denied requests was applied incorrectly, resulting in two potential bugs.
1. The misapplied quiet mask would prevent denials from being correctly
tested against the kill mask/mode. Thus network access requests that
should have resulted in the application being killed did not.
2. The actual quieting of the denied network request was not being applied.
This would result in network rejections always being logged even when
they had been specifically marked as quieted.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/net.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
index 003dd18..6e6e5c9 100644
--- a/security/apparmor/net.c
+++ b/security/apparmor/net.c
@@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
} else {
u16 quiet_mask = profile->net.quiet[sa.u.net->family];
u16 kill_mask = 0;
- u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
+ u16 denied = (1 << sa.aad->net.type);
if (denied & kill_mask)
audit_type = AUDIT_APPARMOR_KILL;
--
1.7.10.4

View File

@@ -0,0 +1,98 @@
From e2d745442133f625e715f713c0441f0f2a7ea6ad Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 29 Jun 2012 17:34:01 -0700
Subject: [PATCH 4/6] apparmor: Ensure apparmor does not mediate kernel based
sockets
Currently apparmor makes the assumption that kernel sockets are unmediated
because mediation is only done against tasks that have a profile attached.
Ensure we never get in a situation where a kernel socket is being mediated
by tagging the sk_security field for kernel sockets.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/include/net.h | 2 ++
security/apparmor/lsm.c | 18 ++++++++++++++++++
security/apparmor/net.c | 3 +++
3 files changed, 23 insertions(+)
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index cb8a121..bc8198b 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -19,6 +19,8 @@
#include "apparmorfs.h"
+#define AA_SOCK_KERN 0xAA
+
/* struct aa_net - network confinement data
* @allowed: basic network families permissions
* @audit_network: which network permissions to force audit
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index f628734..a172d01 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -630,6 +630,16 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
return error;
}
+static int apparmor_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern)
+{
+ if (kern)
+ /* tag kernel sockets so we don't mediate them later */
+ sock->sk->sk_security = (void *) AA_SOCK_KERN;
+
+ return 0;
+}
+
static int apparmor_socket_bind(struct socket *sock,
struct sockaddr *address, int addrlen)
{
@@ -713,6 +723,12 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
}
+static void apparmor_sk_clone_security(const struct sock *sk,
+ struct sock *newsk)
+{
+ newsk->sk_security = sk->sk_security;
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -746,6 +762,7 @@ static struct security_operations apparmor_ops = {
.setprocattr = apparmor_setprocattr,
.socket_create = apparmor_socket_create,
+ .socket_post_create = apparmor_socket_post_create,
.socket_bind = apparmor_socket_bind,
.socket_connect = apparmor_socket_connect,
.socket_listen = apparmor_socket_listen,
@@ -757,6 +774,7 @@ static struct security_operations apparmor_ops = {
.socket_getsockopt = apparmor_socket_getsockopt,
.socket_setsockopt = apparmor_socket_setsockopt,
.socket_shutdown = apparmor_socket_shutdown,
+ .sk_clone_security = apparmor_sk_clone_security,
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
index 6e6e5c9..baa4df1 100644
--- a/security/apparmor/net.c
+++ b/security/apparmor/net.c
@@ -153,6 +153,9 @@ int aa_revalidate_sk(int op, struct sock *sk)
if (in_interrupt())
return 0;
+ if (sk->sk_security == (void *) AA_SOCK_KERN)
+ return 0;
+
profile = __aa_current_profile();
if (!unconfined(profile))
error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
--
1.7.10.4

View File

@@ -0,0 +1,957 @@
From 272431fc90fab50ea9593d969d3ab8d98f03627c Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 16 May 2012 10:58:05 -0700
Subject: [PATCH 5/6] UBUNTU: SAUCE: apparmor: Add the ability to mediate
mount
Add the ability for apparmor to do mediation of mount operations. Mount
rules require an updated apparmor_parser (2.8 series) for policy compilation.
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
Example mount commands
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
umount,
umount /m*,
See the apparmor userspace for full documentation
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
---
security/apparmor/Makefile | 2 +-
security/apparmor/apparmorfs.c | 13 +
security/apparmor/audit.c | 4 +
security/apparmor/domain.c | 2 +-
security/apparmor/include/apparmor.h | 3 +-
security/apparmor/include/audit.h | 11 +
security/apparmor/include/domain.h | 2 +
security/apparmor/include/mount.h | 54 +++
security/apparmor/lsm.c | 59 ++++
security/apparmor/mount.c | 620 ++++++++++++++++++++++++++++++++++
10 files changed, 767 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/mount.h
create mode 100644 security/apparmor/mount.c
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 19daa85..63e0a4c 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o net.o
+ resource.o sid.o file.o net.o mount.o
clean-files := capability_names.h rlim_names.h net_names.h
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 114fb23..ee77ec9 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -426,10 +426,23 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
{ }
};
+static struct aa_fs_entry aa_fs_entry_mount[] = {
+ AA_FS_FILE_STRING("mask", "mount umount"),
+ { }
+};
+
+static struct aa_fs_entry aa_fs_entry_namespaces[] = {
+ AA_FS_FILE_BOOLEAN("profile", 1),
+ AA_FS_FILE_BOOLEAN("pivot_root", 1),
+ { }
+};
+
static struct aa_fs_entry aa_fs_entry_features[] = {
AA_FS_DIR("domain", aa_fs_entry_domain),
AA_FS_DIR("file", aa_fs_entry_file),
AA_FS_DIR("network", aa_fs_entry_network),
+ AA_FS_DIR("mount", aa_fs_entry_mount),
+ AA_FS_DIR("namespaces", aa_fs_entry_namespaces),
AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
{ }
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 3ae28db..e267963 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -44,6 +44,10 @@ const char *const op_table[] = {
"file_mmap",
"file_mprotect",
+ "pivotroot",
+ "mount",
+ "umount",
+
"create",
"post_create",
"bind",
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index b81ea10..afa8671 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -242,7 +242,7 @@ static const char *next_name(int xtype, const char *name)
*
* Returns: refcounted profile, or NULL on failure (MAYBE NULL)
*/
-static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
{
struct aa_profile *new_profile = NULL;
struct aa_namespace *ns = profile->ns;
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 40aedd9..e243d96 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -29,8 +29,9 @@
#define AA_CLASS_NET 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6
+#define AA_CLASS_MOUNT 7
-#define AA_CLASS_LAST AA_CLASS_DOMAIN
+#define AA_CLASS_LAST AA_CLASS_MOUNT
/* Control parameters settable through module/boot flags */
extern enum audit_mode aa_g_audit;
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 17734f9..66a738c 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -73,6 +73,10 @@ enum aa_ops {
OP_FMMAP,
OP_FMPROT,
+ OP_PIVOTROOT,
+ OP_MOUNT,
+ OP_UMOUNT,
+
OP_CREATE,
OP_POST_CREATE,
OP_BIND,
@@ -122,6 +126,13 @@ struct apparmor_audit_data {
unsigned long max;
} rlim;
struct {
+ const char *src_name;
+ const char *type;
+ const char *trans;
+ const char *data;
+ unsigned long flags;
+ } mnt;
+ struct {
const char *target;
u32 request;
u32 denied;
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index de04464..a3f70c5 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -23,6 +23,8 @@ struct aa_domain {
char **table;
};
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
+
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
int apparmor_bprm_secureexec(struct linux_binprm *bprm);
void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
new file mode 100644
index 0000000..bc17a53
--- /dev/null
+++ b/security/apparmor/include/mount.h
@@ -0,0 +1,54 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_MOUNT_H
+#define __AA_MOUNT_H
+
+#include <linux/fs.h>
+#include <linux/path.h>
+
+#include "domain.h"
+#include "policy.h"
+
+/* mount perms */
+#define AA_MAY_PIVOTROOT 0x01
+#define AA_MAY_MOUNT 0x02
+#define AA_MAY_UMOUNT 0x04
+#define AA_AUDIT_DATA 0x40
+#define AA_CONT_MATCH 0x40
+
+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
+
+int aa_remount(struct aa_profile *profile, struct path *path,
+ unsigned long flags, void *data);
+
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
+ const char *old_name, unsigned long flags);
+
+
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
+ unsigned long flags);
+
+int aa_move_mount(struct aa_profile *profile, struct path *path,
+ const char *old_name);
+
+int aa_new_mount(struct aa_profile *profile, const char *dev_name,
+ struct path *path, const char *type, unsigned long flags,
+ void *data);
+
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
+
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
+ struct path *new_path);
+
+#endif /* __AA_MOUNT_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index a172d01..5da8af9 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -36,6 +36,7 @@
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
+#include "include/mount.h"
/* Flag indicating whether initialization completed */
int apparmor_initialized __initdata;
@@ -504,6 +505,60 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
}
+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
+ unsigned long flags, void *data)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* Discard magic */
+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+ flags &= ~MS_MGC_MSK;
+
+ flags &= ~AA_MS_IGNORE_MASK;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile)) {
+ if (flags & MS_REMOUNT)
+ error = aa_remount(profile, path, flags, data);
+ else if (flags & MS_BIND)
+ error = aa_bind_mount(profile, path, dev_name, flags);
+ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
+ MS_UNBINDABLE))
+ error = aa_mount_change_type(profile, path, flags);
+ else if (flags & MS_MOVE)
+ error = aa_move_mount(profile, path, dev_name);
+ else
+ error = aa_new_mount(profile, dev_name, path, type,
+ flags, data);
+ }
+ return error;
+}
+
+static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_umount(profile, mnt, flags);
+
+ return error;
+}
+
+static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_pivotroot(profile, old_path, new_path);
+
+ return error;
+}
+
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -737,6 +792,10 @@ static struct security_operations apparmor_ops = {
.capget = apparmor_capget,
.capable = apparmor_capable,
+ .sb_mount = apparmor_sb_mount,
+ .sb_umount = apparmor_sb_umount,
+ .sb_pivotroot = apparmor_sb_pivotroot,
+
.path_link = apparmor_path_link,
.path_unlink = apparmor_path_unlink,
.path_symlink = apparmor_path_symlink,
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
new file mode 100644
index 0000000..478aa4d
--- /dev/null
+++ b/security/apparmor/mount.c
@@ -0,0 +1,620 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor mediation of files
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/domain.h"
+#include "include/file.h"
+#include "include/match.h"
+#include "include/mount.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+
+static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
+{
+ if (flags & MS_RDONLY)
+ audit_log_format(ab, "ro");
+ else
+ audit_log_format(ab, "rw");
+ if (flags & MS_NOSUID)
+ audit_log_format(ab, ", nosuid");
+ if (flags & MS_NODEV)
+ audit_log_format(ab, ", nodev");
+ if (flags & MS_NOEXEC)
+ audit_log_format(ab, ", noexec");
+ if (flags & MS_SYNCHRONOUS)
+ audit_log_format(ab, ", sync");
+ if (flags & MS_REMOUNT)
+ audit_log_format(ab, ", remount");
+ if (flags & MS_MANDLOCK)
+ audit_log_format(ab, ", mand");
+ if (flags & MS_DIRSYNC)
+ audit_log_format(ab, ", dirsync");
+ if (flags & MS_NOATIME)
+ audit_log_format(ab, ", noatime");
+ if (flags & MS_NODIRATIME)
+ audit_log_format(ab, ", nodiratime");
+ if (flags & MS_BIND)
+ audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
+ if (flags & MS_MOVE)
+ audit_log_format(ab, ", move");
+ if (flags & MS_SILENT)
+ audit_log_format(ab, ", silent");
+ if (flags & MS_POSIXACL)
+ audit_log_format(ab, ", acl");
+ if (flags & MS_UNBINDABLE)
+ audit_log_format(ab, flags & MS_REC ? ", runbindable" :
+ ", unbindable");
+ if (flags & MS_PRIVATE)
+ audit_log_format(ab, flags & MS_REC ? ", rprivate" :
+ ", private");
+ if (flags & MS_SLAVE)
+ audit_log_format(ab, flags & MS_REC ? ", rslave" :
+ ", slave");
+ if (flags & MS_SHARED)
+ audit_log_format(ab, flags & MS_REC ? ", rshared" :
+ ", shared");
+ if (flags & MS_RELATIME)
+ audit_log_format(ab, ", relatime");
+ if (flags & MS_I_VERSION)
+ audit_log_format(ab, ", iversion");
+ if (flags & MS_STRICTATIME)
+ audit_log_format(ab, ", strictatime");
+ if (flags & MS_NOUSER)
+ audit_log_format(ab, ", nouser");
+}
+
+/**
+ * audit_cb - call back for mount specific audit fields
+ * @ab: audit_buffer (NOT NULL)
+ * @va: audit struct to audit values of (NOT NULL)
+ */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ if (sa->aad->mnt.type) {
+ audit_log_format(ab, " fstype=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.type);
+ }
+ if (sa->aad->mnt.src_name) {
+ audit_log_format(ab, " srcname=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
+ }
+ if (sa->aad->mnt.trans) {
+ audit_log_format(ab, " trans=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.trans);
+ }
+ if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
+ audit_log_format(ab, " flags=\"");
+ audit_mnt_flags(ab, sa->aad->mnt.flags);
+ audit_log_format(ab, "\"");
+ }
+ if (sa->aad->mnt.data) {
+ audit_log_format(ab, " options=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.data);
+ }
+}
+
+/**
+ * audit_mount - handle the auditing of mount operations
+ * @profile: the profile being enforced (NOT NULL)
+ * @gfp: allocation flags
+ * @op: operation being mediated (NOT NULL)
+ * @name: name of object being mediated (MAYBE NULL)
+ * @src_name: src_name of object being mediated (MAYBE_NULL)
+ * @type: type of filesystem (MAYBE_NULL)
+ * @trans: name of trans (MAYBE NULL)
+ * @flags: filesystem idependent mount flags
+ * @data: filesystem mount flags
+ * @request: permissions requested
+ * @perms: the permissions computed for the request (NOT NULL)
+ * @info: extra information message (MAYBE NULL)
+ * @error: 0 if operation allowed else failure error code
+ *
+ * Returns: %0 or error on failure
+ */
+static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
+ const char *name, const char *src_name,
+ const char *type, const char *trans,
+ unsigned long flags, const void *data, u32 request,
+ struct file_perms *perms, const char *info, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa = { };
+ struct apparmor_audit_data aad = { };
+
+ if (likely(!error)) {
+ u32 mask = perms->audit;
+
+ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
+ mask = 0xffff;
+
+ /* mask off perms that are not being force audited */
+ request &= mask;
+
+ if (likely(!request))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ /* only report permissions that were denied */
+ request = request & ~perms->allow;
+
+ if (request & perms->kill)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ /* quiet known rejects, assumes quiet and kill do not overlap */
+ if ((request & perms->quiet) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ request &= ~perms->quiet;
+
+ if (!request)
+ return COMPLAIN_MODE(profile) ?
+ complain_error(error) : error;
+ }
+
+ sa.type = LSM_AUDIT_DATA_NONE;
+ sa.aad = &aad;
+ sa.aad->op = op;
+ sa.aad->name = name;
+ sa.aad->mnt.src_name = src_name;
+ sa.aad->mnt.type = type;
+ sa.aad->mnt.trans = trans;
+ sa.aad->mnt.flags = flags;
+ if (data && (perms->audit & AA_AUDIT_DATA))
+ sa.aad->mnt.data = data;
+ sa.aad->info = info;
+ sa.aad->error = error;
+
+ return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
+}
+
+/**
+ * match_mnt_flags - Do an ordered match on mount flags
+ * @dfa: dfa to match against
+ * @state: state to start in
+ * @flags: mount flags to match against
+ *
+ * Mount flags are encoded as an ordered match. This is done instead of
+ * checking against a simple bitmask, to allow for logical operations
+ * on the flags.
+ *
+ * Returns: next state after flags match
+ */
+static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
+ unsigned long flags)
+{
+ unsigned int i;
+
+ for (i = 0; i <= 31 ; ++i) {
+ if ((1 << i) & flags)
+ state = aa_dfa_next(dfa, state, i + 1);
+ }
+
+ return state;
+}
+
+/**
+ * compute_mnt_perms - compute mount permission associated with @state
+ * @dfa: dfa to match against (NOT NULL)
+ * @state: state match finished in
+ *
+ * Returns: mount permissions
+ */
+static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
+ unsigned int state)
+{
+ struct file_perms perms;
+
+ perms.kill = 0;
+ perms.allow = dfa_user_allow(dfa, state);
+ perms.audit = dfa_user_audit(dfa, state);
+ perms.quiet = dfa_user_quiet(dfa, state);
+ perms.xindex = dfa_user_xindex(dfa, state);
+
+ return perms;
+}
+
+static const char const *mnt_info_table[] = {
+ "match succeeded",
+ "failed mntpnt match",
+ "failed srcname match",
+ "failed type match",
+ "failed flags match",
+ "failed data match"
+};
+
+/*
+ * Returns 0 on success else element that match failed in, this is the
+ * index into the mnt_info_table above
+ */
+static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
+ const char *mntpnt, const char *devname,
+ const char *type, unsigned long flags,
+ void *data, bool binary, struct file_perms *perms)
+{
+ unsigned int state;
+
+ state = aa_dfa_match(dfa, start, mntpnt);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 1;
+
+ if (devname)
+ state = aa_dfa_match(dfa, state, devname);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 2;
+
+ if (type)
+ state = aa_dfa_match(dfa, state, type);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 3;
+
+ state = match_mnt_flags(dfa, state, flags);
+ if (!state)
+ return 4;
+ *perms = compute_mnt_perms(dfa, state);
+ if (perms->allow & AA_MAY_MOUNT)
+ return 0;
+
+ /* only match data if not binary and the DFA flags data is expected */
+ if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 4;
+
+ state = aa_dfa_match(dfa, state, data);
+ if (!state)
+ return 5;
+ *perms = compute_mnt_perms(dfa, state);
+ if (perms->allow & AA_MAY_MOUNT)
+ return 0;
+ }
+
+ /* failed at end of flags match */
+ return 4;
+}
+
+/**
+ * match_mnt - handle path matching for mount
+ * @profile: the confining profile
+ * @mntpnt: string for the mntpnt (NOT NULL)
+ * @devname: string for the devname/src_name (MAYBE NULL)
+ * @type: string for the dev type (MAYBE NULL)
+ * @flags: mount flags to match
+ * @data: fs mount data (MAYBE NULL)
+ * @binary: whether @data is binary
+ * @perms: Returns: permission found by the match
+ * @info: Returns: infomation string about the match for logging
+ *
+ * Returns: 0 on success else error
+ */
+static int match_mnt(struct aa_profile *profile, const char *mntpnt,
+ const char *devname, const char *type,
+ unsigned long flags, void *data, bool binary,
+ struct file_perms *perms, const char **info)
+{
+ int pos;
+
+ if (!profile->policy.dfa)
+ return -EACCES;
+
+ pos = do_match_mnt(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ mntpnt, devname, type, flags, data, binary, perms);
+ if (pos) {
+ *info = mnt_info_table[pos];
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static int path_flags(struct aa_profile *profile, struct path *path)
+{
+ return profile->path_flags |
+ S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
+}
+
+int aa_remount(struct aa_profile *profile, struct path *path,
+ unsigned long flags, void *data)
+{
+ struct file_perms perms = { };
+ const char *name, *info = NULL;
+ char *buffer = NULL;
+ int binary, error;
+
+ binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
+ NULL, flags, data, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
+ const char *dev_name, unsigned long flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *old_buffer = NULL;
+ const char *name, *old_name = NULL, *info = NULL;
+ struct path old_path;
+ int error;
+
+ if (!dev_name || !*dev_name)
+ return -EINVAL;
+
+ flags &= MS_REC | MS_BIND;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ &old_buffer, &old_name, &info);
+ path_put(&old_path);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ kfree(buffer);
+ kfree(old_buffer);
+
+ return error;
+}
+
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
+ unsigned long flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL;
+ const char *name, *info = NULL;
+ int error;
+
+ /* These are the flags allowed by do_change_type() */
+ flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
+ MS_UNBINDABLE);
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
+ &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
+ NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_move_mount(struct aa_profile *profile, struct path *path,
+ const char *orig_name)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *old_buffer = NULL;
+ const char *name, *old_name = NULL, *info = NULL;
+ struct path old_path;
+ int error;
+
+ if (!orig_name || !*orig_name)
+ return -EINVAL;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ &old_buffer, &old_name, &info);
+ path_put(&old_path);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ kfree(buffer);
+ kfree(old_buffer);
+
+ return error;
+}
+
+int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
+ struct path *path, const char *type, unsigned long flags,
+ void *data)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *dev_buffer = NULL;
+ const char *name = NULL, *dev_name = NULL, *info = NULL;
+ int binary = 1;
+ int error;
+
+ dev_name = orig_dev_name;
+ if (type) {
+ int requires_dev;
+ struct file_system_type *fstype = get_fs_type(type);
+ if (!fstype)
+ return -ENODEV;
+
+ binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
+ requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
+ put_filesystem(fstype);
+
+ if (requires_dev) {
+ struct path dev_path;
+
+ if (!dev_name || !*dev_name) {
+ error = -ENOENT;
+ goto out;
+ }
+
+ error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&dev_path,
+ path_flags(profile, &dev_path),
+ &dev_buffer, &dev_name, &info);
+ path_put(&dev_path);
+ if (error)
+ goto audit;
+ }
+ }
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, dev_name, type, flags, data, binary,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name,
+ type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+ kfree(dev_buffer);
+
+out:
+ return error;
+
+}
+
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL;
+ const char *name, *info = NULL;
+ int error;
+
+ struct path path = { mnt, mnt->mnt_root };
+ error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ if (!error && profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+ }
+
+ if (AA_MAY_UMOUNT & ~perms.allow)
+ error = -EACCES;
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
+ NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
+ struct path *new_path)
+{
+ struct file_perms perms = { };
+ struct aa_profile *target = NULL;
+ char *old_buffer = NULL, *new_buffer = NULL;
+ const char *old_name, *new_name = NULL, *info = NULL;
+ int error;
+
+ error = aa_path_name(old_path, path_flags(profile, old_path),
+ &old_buffer, &old_name, &info);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(new_path, path_flags(profile, new_path),
+ &new_buffer, &new_name, &info);
+ if (error)
+ goto audit;
+
+ if (profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ new_name);
+ state = aa_dfa_null_transition(profile->policy.dfa, state);
+ state = aa_dfa_match(profile->policy.dfa, state, old_name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+ }
+
+ if (AA_MAY_PIVOTROOT & perms.allow) {
+ if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
+ target = x_table_lookup(profile, perms.xindex);
+ if (!target)
+ error = -ENOENT;
+ else
+ error = aa_replace_current_profile(target);
+ }
+ } else
+ error = -EACCES;
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
+ old_name, NULL, target ? target->base.name : NULL,
+ 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error);
+ aa_put_profile(target);
+ kfree(old_buffer);
+ kfree(new_buffer);
+
+ return error;
+}
--
1.7.10.4

View File

@@ -0,0 +1,70 @@
From f58c91bc1871d604f88d0056099dc34f8ce3ae21 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 24 Oct 2012 06:27:32 -0700
Subject: [PATCH 6/6] apparmor: fix IRQ stack overflow during free_profile
BugLink: http://bugs.launchpad.net/bugs/1056078
Profile replacement can cause long chains of profiles to build up when
the profile being replaced is pinned. When the pinned profile is finally
freed, it puts the reference to its replacement, which may in turn nest
another call to free_profile on the stack. Because this may happen for
each profile in the replacedby chain this can result in a recusion that
causes the stack to overflow.
Break this nesting by directly walking the chain of replacedby profiles
(ie. use iteration instead of recursion to free the list). This results
in at most 2 levels of free_profile being called, while freeing a
replacedby chain.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
---
security/apparmor/policy.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 27c8161..56e5304 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -724,6 +724,8 @@ fail:
*/
static void free_profile(struct aa_profile *profile)
{
+ struct aa_profile *p;
+
AA_DEBUG("%s(%p)\n", __func__, profile);
if (!profile)
@@ -752,7 +754,27 @@ static void free_profile(struct aa_profile *profile)
aa_put_dfa(profile->xmatch);
aa_put_dfa(profile->policy.dfa);
- aa_put_profile(profile->replacedby);
+ /* put the profile reference for replacedby, but not via
+ * put_profile(kref_put).
+ * replacedby can form a long chain that can result in cascading
+ * frees that blows the stack because kref_put makes a nested fn
+ * call (it looks like recursion, with free_profile calling
+ * free_profile) for each profile in the chain lp#1056078.
+ */
+ for (p = profile->replacedby; p; ) {
+ if (atomic_dec_and_test(&p->base.count.refcount)) {
+ /* no more refs on p, grab its replacedby */
+ struct aa_profile *next = p->replacedby;
+ /* break the chain */
+ p->replacedby = NULL;
+ /* now free p, chain is broken */
+ free_profile(p);
+
+ /* follow up with next profile in the chain */
+ p = next;
+ } else
+ break;
+ }
kzfree(profile);
}
--
1.7.10.4

View File

@@ -0,0 +1,285 @@
From 259cf7251194d81a4a3c4e6d76c2cf9e38d5647d Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Thu, 22 Jul 2010 02:32:02 -0700
Subject: [PATCH 1/6] UBUNTU: SAUCE: AppArmor: Add profile introspection file
to interface
Add the dynamic profiles file to the interace, to allow load policy
introspection.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
---
security/apparmor/Kconfig | 9 ++
security/apparmor/apparmorfs.c | 231 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 240 insertions(+)
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b..51ebf96 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
boot.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+ bool "Enable AppArmor 2.4 compatability"
+ depends on SECURITY_APPARMOR
+ default y
+ help
+ This option enables compatability with AppArmor 2.4. It is
+ recommended if compatability with older versions of AppArmor
+ is desired.
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 16c15ec..42b7c9f 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -182,6 +182,234 @@ const struct file_operations aa_fs_seq_file_ops = {
.release = single_release,
};
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ struct aa_namespace *parent;
+
+ /* is next namespace a child */
+ if (!list_empty(&ns->sub_ns)) {
+ struct aa_namespace *next;
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+ read_lock(&next->lock);
+ return next;
+ }
+
+ /* check if the next ns is a sibling, parent, gp, .. */
+ parent = ns->parent;
+ while (parent) {
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+ read_lock(&ns->lock);
+ return ns;
+ }
+ if (parent == root)
+ return NULL;
+ ns = parent;
+ parent = parent->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+static struct aa_profile *__first_profile(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ for ( ; ns; ns = __next_namespace(root, ns)) {
+ if (!list_empty(&ns->base.profiles))
+ return list_first_entry(&ns->base.profiles,
+ struct aa_profile, base.list);
+ }
+ return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+ struct aa_profile *parent;
+ struct aa_namespace *ns = p->ns;
+
+ /* is next profile a child */
+ if (!list_empty(&p->base.profiles))
+ return list_first_entry(&p->base.profiles, typeof(*p),
+ base.list);
+
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
+ parent = p->parent;
+ while (parent) {
+ list_for_each_entry_continue(p, &parent->base.profiles,
+ base.list)
+ return p;
+ p = parent;
+ parent = parent->parent;
+ }
+
+ /* is next another profile in the namespace */
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace (NOT NULL)
+ * @profile: current profile (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+ struct aa_profile *profile)
+{
+ struct aa_profile *next = __next_profile(profile);
+ if (next)
+ return next;
+
+ /* finished all profiles in namespace move to next namespace */
+ return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+ __acquires(root->lock)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *root = aa_current_profile()->ns;
+ loff_t l = *pos;
+ f->private = aa_get_namespace(root);
+
+
+ /* find the first profile */
+ read_lock(&root->lock);
+ profile = __first_profile(root, root);
+
+ /* skip to position */
+ for (; profile && l > 0; l--)
+ profile = next_profile(root, profile);
+
+ return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private;
+ (*pos)++;
+
+ return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+ __releases(root->lock)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private, *ns;
+
+ if (profile) {
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+ read_unlock(&ns->lock);
+ }
+ read_unlock(&root->lock);
+ aa_put_namespace(root);
+}
+
+/**
+ * seq_show_profile - show a profile entry
+ * @f: seq_file to file
+ * @p: current position (profile) (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_namespace *root = f->private;
+
+ if (profile->ns != root)
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+ return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
+
+static int profiles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int profiles_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+const struct file_operations aa_fs_profiles_fops = {
+ .open = profiles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = profiles_release,
+};
+#endif /* CONFIG_SECURITY_APPARMOR_COMPAT_24 */
+
/** Base file system setup **/
static struct aa_fs_entry aa_fs_entry_file[] = {
@@ -210,6 +438,9 @@ static struct aa_fs_entry aa_fs_entry_apparmor[] = {
AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops),
+#endif
AA_FS_DIR("features", aa_fs_entry_features),
{ }
};
--
1.7.10.4

View File

@@ -0,0 +1,603 @@
From 0317e6ba6aa4adc71f645b7da5318f4caa69267e Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 4 Oct 2010 15:03:36 -0700
Subject: [PATCH 2/6] UBUNTU: SAUCE: AppArmor: basic networking rules
Base support for network mediation.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/.gitignore | 2 +-
security/apparmor/Makefile | 42 +++++++++-
security/apparmor/apparmorfs.c | 1 +
security/apparmor/include/audit.h | 4 +
security/apparmor/include/net.h | 44 ++++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++++
security/apparmor/net.c | 162 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 46 ++++++++++
10 files changed, 414 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 4d995ae..d5b291e 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -1,6 +1,6 @@
#
# Generated include files
#
-af_names.h
+net_names.h
capability_names.h
rlim_names.h
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 806bd19..19daa85 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o
+ resource.o sid.o file.o net.o
-clean-files := capability_names.h rlim_names.h
+clean-files := capability_names.h rlim_names.h net_names.h
# Build a lower case string table of capability names
@@ -20,6 +20,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
echo "};" >> $@
+# Build a lower case string table of address family names
+# Transform lines from
+# define AF_LOCAL 1 /* POSIX name for AF_UNIX */
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [1] = "local",
+# [2] = "inet",
+#
+# and build the securityfs entries for the mapping.
+# Transforms lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# #define AA_FS_AF_MASK "local inet"
+quiet_cmd_make-af = GEN $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
+ sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+ echo "};" >> $@ ;\
+ echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
+ sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
+ $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
+
+# Build a lower case string table of sock type names
+# Transform lines from
+# SOCK_STREAM = 1,
+# to
+# [1] = "stream",
+quiet_cmd_make-sock = GEN $@
+cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
+ sed $^ >>$@ -r -n \
+ -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+ echo "};" >> $@
# Build a lower case string table of rlimit names.
# Transforms lines from
@@ -56,6 +88,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
$(obj)/capability.o : $(obj)/capability_names.h
+$(obj)/net.o : $(obj)/net_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
$(src)/Makefile
@@ -63,3 +96,8 @@ $(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \
$(src)/Makefile
$(call cmd,make-rlim)
+$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
+ $(srctree)/include/linux/net.h \
+ $(src)/Makefile
+ $(call cmd,make-af)
+ $(call cmd,make-sock)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 42b7c9f..114fb23 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -429,6 +429,7 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
static struct aa_fs_entry aa_fs_entry_features[] = {
AA_FS_DIR("domain", aa_fs_entry_domain),
AA_FS_DIR("file", aa_fs_entry_file),
+ AA_FS_DIR("network", aa_fs_entry_network),
AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
{ }
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 4b7e189..17734f9 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -127,6 +127,10 @@ struct apparmor_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
};
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..cb8a121
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,44 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+#include "apparmorfs.h"
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+ u16 allow[AF_MAX];
+ u16 audit[AF_MAX];
+ u16 quiet[AF_MAX];
+};
+
+extern struct aa_fs_entry aa_fs_entry_network[];
+
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
+ int type, int protocol, struct sock *sk);
+extern int aa_revalidate_sk(int op, struct sock *sk);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+ /* NOP */
+}
+
+#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index bda4569..eb13a73 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -27,6 +27,7 @@
#include "capability.h"
#include "domain.h"
#include "file.h"
+#include "net.h"
#include "resource.h"
extern const char *const profile_mode_names[];
@@ -157,6 +158,7 @@ struct aa_policydb {
* @policy: general match rules governing policy
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
+ * @net: network controls for the profile
* @rlimits: rlimits for the profile
*
* The AppArmor profile contains the basic confinement data. Each profile
@@ -194,6 +196,7 @@ struct aa_profile {
struct aa_policydb policy;
struct aa_file_rules file;
struct aa_caps caps;
+ struct aa_net net;
struct aa_rlimit rlimits;
};
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8ea39aa..f628734 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -32,6 +32,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
+#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
@@ -614,6 +615,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
return error;
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
+ NULL);
+ return error;
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_BIND, sk);
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_CONNECT, sk);
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_LISTEN, sk);
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_ACCEPT, sk);
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SENDMSG, sk);
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_RECVMSG, sk);
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -646,6 +745,19 @@ static struct security_operations apparmor_ops = {
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .socket_create = apparmor_socket_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
+
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 0000000..003dd18
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,162 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "net_names.h"
+
+struct aa_fs_entry aa_fs_entry_network[] = {
+ AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
+ { }
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ audit_log_format(ab, " family=");
+ if (address_family_names[sa->u.net->family]) {
+ audit_log_string(ab, address_family_names[sa->u.net->family]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
+ }
+ audit_log_format(ab, " sock_type=");
+ if (sock_type_names[sa->aad->net.type]) {
+ audit_log_string(ab, sock_type_names[sa->aad->net.type]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
+ }
+ audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
+}
+
+/**
+ * audit_net - audit network access
+ * @profile: profile being enforced (NOT NULL)
+ * @op: operation being checked
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ * @sk: socket auditing is being applied to
+ * @error: error code for failure else 0
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+ int protocol, struct sock *sk, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa;
+ struct apparmor_audit_data aad = { };
+ struct lsm_network_audit net = { };
+ if (sk) {
+ sa.type = LSM_AUDIT_DATA_NET;
+ } else {
+ sa.type = LSM_AUDIT_DATA_NONE;
+ }
+ /* todo fill in socket addr info */
+ sa.aad = &aad;
+ sa.u.net = &net;
+ sa.aad->op = op,
+ sa.u.net->family = family;
+ sa.u.net->sk = sk;
+ sa.aad->net.type = type;
+ sa.aad->net.protocol = protocol;
+ sa.aad->error = error;
+
+ if (likely(!sa.aad->error)) {
+ u16 audit_mask = profile->net.audit[sa.u.net->family];
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+ !(1 << sa.aad->net.type & audit_mask)))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ u16 quiet_mask = profile->net.quiet[sa.u.net->family];
+ u16 kill_mask = 0;
+ u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
+
+ if (denied & kill_mask)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ if ((denied & quiet_mask) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
+ }
+
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @op: operation being checked
+ * @profile: profile being enforced (NOT NULL)
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
+ int protocol, struct sock *sk)
+{
+ u16 family_mask;
+ int error;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->net.allow[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ return audit_net(profile, op, family, type, protocol, sk, error);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @op: operation being checked
+ * @sk: sock being revalidated (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(int op, struct sock *sk)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* aa_revalidate_sk should not be called from interrupt context
+ * don't mediate these calls as they are not task related
+ */
+ if (in_interrupt())
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
+ sk->sk_protocol, sk);
+
+ return error;
+}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index cf5fd22..27c8161 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
aa_free_file_rules(&profile->file);
aa_free_cap_rules(&profile->caps);
+ aa_free_net_rules(&profile->net);
aa_free_rlimit_rules(&profile->rlimits);
aa_free_sid(profile->sid);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 329b1fd..1b90dfa 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -193,6 +193,19 @@ fail:
return 0;
}
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+ if (unpack_nameX(e, AA_U16, name)) {
+ if (!inbounds(e, sizeof(u16)))
+ return 0;
+ if (data)
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+ e->pos += sizeof(u16);
+ return 1;
+ }
+ return 0;
+}
+
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
if (unpack_nameX(e, AA_U32, name)) {
@@ -471,6 +484,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
+ size_t size = 0;
int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -564,6 +578,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
if (!unpack_rlimits(e, profile))
goto fail;
+ size = unpack_array(e, "net_allowed_af");
+ if (size) {
+
+ for (i = 0; i < size; i++) {
+ /* discard extraneous rules that this kernel will
+ * never request
+ */
+ if (i >= AF_MAX) {
+ u16 tmp;
+ if (!unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL))
+ goto fail;
+ continue;
+ }
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ }
+ /*
+ * allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ profile->net.allow[AF_UNIX] = 0xffff;
+ profile->net.allow[AF_NETLINK] = 0xffff;
+
if (unpack_nameX(e, AA_STRUCT, "policydb")) {
/* generic policy dfa - optional and may be NULL */
profile->policy.dfa = unpack_dfa(e);
--
1.7.10.4

View File

@@ -0,0 +1,38 @@
From b1cb9d1b4f0d585c271c584da954d9eb2e347b40 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 29 Jun 2012 17:34:00 -0700
Subject: [PATCH 3/6] apparmor: Fix quieting of audit messages for network
mediation
If a profile specified a quieting of network denials for a given rule by
either the quiet or deny rule qualifiers, the resultant quiet mask for
denied requests was applied incorrectly, resulting in two potential bugs.
1. The misapplied quiet mask would prevent denials from being correctly
tested against the kill mask/mode. Thus network access requests that
should have resulted in the application being killed did not.
2. The actual quieting of the denied network request was not being applied.
This would result in network rejections always being logged even when
they had been specifically marked as quieted.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/net.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
index 003dd18..6e6e5c9 100644
--- a/security/apparmor/net.c
+++ b/security/apparmor/net.c
@@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
} else {
u16 quiet_mask = profile->net.quiet[sa.u.net->family];
u16 kill_mask = 0;
- u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
+ u16 denied = (1 << sa.aad->net.type);
if (denied & kill_mask)
audit_type = AUDIT_APPARMOR_KILL;
--
1.7.10.4

View File

@@ -0,0 +1,98 @@
From f284c9554341aded2d599e9355574cac36c2dd23 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 29 Jun 2012 17:34:01 -0700
Subject: [PATCH 4/6] apparmor: Ensure apparmor does not mediate kernel based
sockets
Currently apparmor makes the assumption that kernel sockets are unmediated
because mediation is only done against tasks that have a profile attached.
Ensure we never get in a situation where a kernel socket is being mediated
by tagging the sk_security field for kernel sockets.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/include/net.h | 2 ++
security/apparmor/lsm.c | 18 ++++++++++++++++++
security/apparmor/net.c | 3 +++
3 files changed, 23 insertions(+)
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index cb8a121..bc8198b 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -19,6 +19,8 @@
#include "apparmorfs.h"
+#define AA_SOCK_KERN 0xAA
+
/* struct aa_net - network confinement data
* @allowed: basic network families permissions
* @audit_network: which network permissions to force audit
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index f628734..a172d01 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -630,6 +630,16 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
return error;
}
+static int apparmor_socket_post_create(struct socket *sock, int family,
+ int type, int protocol, int kern)
+{
+ if (kern)
+ /* tag kernel sockets so we don't mediate them later */
+ sock->sk->sk_security = (void *) AA_SOCK_KERN;
+
+ return 0;
+}
+
static int apparmor_socket_bind(struct socket *sock,
struct sockaddr *address, int addrlen)
{
@@ -713,6 +723,12 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
}
+static void apparmor_sk_clone_security(const struct sock *sk,
+ struct sock *newsk)
+{
+ newsk->sk_security = sk->sk_security;
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -746,6 +762,7 @@ static struct security_operations apparmor_ops = {
.setprocattr = apparmor_setprocattr,
.socket_create = apparmor_socket_create,
+ .socket_post_create = apparmor_socket_post_create,
.socket_bind = apparmor_socket_bind,
.socket_connect = apparmor_socket_connect,
.socket_listen = apparmor_socket_listen,
@@ -757,6 +774,7 @@ static struct security_operations apparmor_ops = {
.socket_getsockopt = apparmor_socket_getsockopt,
.socket_setsockopt = apparmor_socket_setsockopt,
.socket_shutdown = apparmor_socket_shutdown,
+ .sk_clone_security = apparmor_sk_clone_security,
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
index 6e6e5c9..baa4df1 100644
--- a/security/apparmor/net.c
+++ b/security/apparmor/net.c
@@ -153,6 +153,9 @@ int aa_revalidate_sk(int op, struct sock *sk)
if (in_interrupt())
return 0;
+ if (sk->sk_security == (void *) AA_SOCK_KERN)
+ return 0;
+
profile = __aa_current_profile();
if (!unconfined(profile))
error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
--
1.7.10.4

View File

@@ -0,0 +1,957 @@
From f5e962d77f98deab3461404567abd4759f5445a7 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 16 May 2012 10:58:05 -0700
Subject: [PATCH 5/6] UBUNTU: SAUCE: apparmor: Add the ability to mediate
mount
Add the ability for apparmor to do mediation of mount operations. Mount
rules require an updated apparmor_parser (2.8 series) for policy compilation.
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
Example mount commands
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
umount,
umount /m*,
See the apparmor userspace for full documentation
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
---
security/apparmor/Makefile | 2 +-
security/apparmor/apparmorfs.c | 13 +
security/apparmor/audit.c | 4 +
security/apparmor/domain.c | 2 +-
security/apparmor/include/apparmor.h | 3 +-
security/apparmor/include/audit.h | 11 +
security/apparmor/include/domain.h | 2 +
security/apparmor/include/mount.h | 54 +++
security/apparmor/lsm.c | 59 ++++
security/apparmor/mount.c | 620 ++++++++++++++++++++++++++++++++++
10 files changed, 767 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/mount.h
create mode 100644 security/apparmor/mount.c
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 19daa85..63e0a4c 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o net.o
+ resource.o sid.o file.o net.o mount.o
clean-files := capability_names.h rlim_names.h net_names.h
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 114fb23..ee77ec9 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -426,10 +426,23 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
{ }
};
+static struct aa_fs_entry aa_fs_entry_mount[] = {
+ AA_FS_FILE_STRING("mask", "mount umount"),
+ { }
+};
+
+static struct aa_fs_entry aa_fs_entry_namespaces[] = {
+ AA_FS_FILE_BOOLEAN("profile", 1),
+ AA_FS_FILE_BOOLEAN("pivot_root", 1),
+ { }
+};
+
static struct aa_fs_entry aa_fs_entry_features[] = {
AA_FS_DIR("domain", aa_fs_entry_domain),
AA_FS_DIR("file", aa_fs_entry_file),
AA_FS_DIR("network", aa_fs_entry_network),
+ AA_FS_DIR("mount", aa_fs_entry_mount),
+ AA_FS_DIR("namespaces", aa_fs_entry_namespaces),
AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
{ }
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 3ae28db..e267963 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -44,6 +44,10 @@ const char *const op_table[] = {
"file_mmap",
"file_mprotect",
+ "pivotroot",
+ "mount",
+ "umount",
+
"create",
"post_create",
"bind",
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index b81ea10..afa8671 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -242,7 +242,7 @@ static const char *next_name(int xtype, const char *name)
*
* Returns: refcounted profile, or NULL on failure (MAYBE NULL)
*/
-static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
{
struct aa_profile *new_profile = NULL;
struct aa_namespace *ns = profile->ns;
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 40aedd9..e243d96 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -29,8 +29,9 @@
#define AA_CLASS_NET 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6
+#define AA_CLASS_MOUNT 7
-#define AA_CLASS_LAST AA_CLASS_DOMAIN
+#define AA_CLASS_LAST AA_CLASS_MOUNT
/* Control parameters settable through module/boot flags */
extern enum audit_mode aa_g_audit;
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 17734f9..66a738c 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -73,6 +73,10 @@ enum aa_ops {
OP_FMMAP,
OP_FMPROT,
+ OP_PIVOTROOT,
+ OP_MOUNT,
+ OP_UMOUNT,
+
OP_CREATE,
OP_POST_CREATE,
OP_BIND,
@@ -122,6 +126,13 @@ struct apparmor_audit_data {
unsigned long max;
} rlim;
struct {
+ const char *src_name;
+ const char *type;
+ const char *trans;
+ const char *data;
+ unsigned long flags;
+ } mnt;
+ struct {
const char *target;
u32 request;
u32 denied;
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index de04464..a3f70c5 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -23,6 +23,8 @@ struct aa_domain {
char **table;
};
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
+
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
int apparmor_bprm_secureexec(struct linux_binprm *bprm);
void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
new file mode 100644
index 0000000..bc17a53
--- /dev/null
+++ b/security/apparmor/include/mount.h
@@ -0,0 +1,54 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_MOUNT_H
+#define __AA_MOUNT_H
+
+#include <linux/fs.h>
+#include <linux/path.h>
+
+#include "domain.h"
+#include "policy.h"
+
+/* mount perms */
+#define AA_MAY_PIVOTROOT 0x01
+#define AA_MAY_MOUNT 0x02
+#define AA_MAY_UMOUNT 0x04
+#define AA_AUDIT_DATA 0x40
+#define AA_CONT_MATCH 0x40
+
+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
+
+int aa_remount(struct aa_profile *profile, struct path *path,
+ unsigned long flags, void *data);
+
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
+ const char *old_name, unsigned long flags);
+
+
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
+ unsigned long flags);
+
+int aa_move_mount(struct aa_profile *profile, struct path *path,
+ const char *old_name);
+
+int aa_new_mount(struct aa_profile *profile, const char *dev_name,
+ struct path *path, const char *type, unsigned long flags,
+ void *data);
+
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
+
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
+ struct path *new_path);
+
+#endif /* __AA_MOUNT_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index a172d01..5da8af9 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -36,6 +36,7 @@
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
+#include "include/mount.h"
/* Flag indicating whether initialization completed */
int apparmor_initialized __initdata;
@@ -504,6 +505,60 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
}
+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
+ unsigned long flags, void *data)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* Discard magic */
+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+ flags &= ~MS_MGC_MSK;
+
+ flags &= ~AA_MS_IGNORE_MASK;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile)) {
+ if (flags & MS_REMOUNT)
+ error = aa_remount(profile, path, flags, data);
+ else if (flags & MS_BIND)
+ error = aa_bind_mount(profile, path, dev_name, flags);
+ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
+ MS_UNBINDABLE))
+ error = aa_mount_change_type(profile, path, flags);
+ else if (flags & MS_MOVE)
+ error = aa_move_mount(profile, path, dev_name);
+ else
+ error = aa_new_mount(profile, dev_name, path, type,
+ flags, data);
+ }
+ return error;
+}
+
+static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_umount(profile, mnt, flags);
+
+ return error;
+}
+
+static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_pivotroot(profile, old_path, new_path);
+
+ return error;
+}
+
static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
@@ -737,6 +792,10 @@ static struct security_operations apparmor_ops = {
.capget = apparmor_capget,
.capable = apparmor_capable,
+ .sb_mount = apparmor_sb_mount,
+ .sb_umount = apparmor_sb_umount,
+ .sb_pivotroot = apparmor_sb_pivotroot,
+
.path_link = apparmor_path_link,
.path_unlink = apparmor_path_unlink,
.path_symlink = apparmor_path_symlink,
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
new file mode 100644
index 0000000..478aa4d
--- /dev/null
+++ b/security/apparmor/mount.c
@@ -0,0 +1,620 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor mediation of files
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/domain.h"
+#include "include/file.h"
+#include "include/match.h"
+#include "include/mount.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+
+static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
+{
+ if (flags & MS_RDONLY)
+ audit_log_format(ab, "ro");
+ else
+ audit_log_format(ab, "rw");
+ if (flags & MS_NOSUID)
+ audit_log_format(ab, ", nosuid");
+ if (flags & MS_NODEV)
+ audit_log_format(ab, ", nodev");
+ if (flags & MS_NOEXEC)
+ audit_log_format(ab, ", noexec");
+ if (flags & MS_SYNCHRONOUS)
+ audit_log_format(ab, ", sync");
+ if (flags & MS_REMOUNT)
+ audit_log_format(ab, ", remount");
+ if (flags & MS_MANDLOCK)
+ audit_log_format(ab, ", mand");
+ if (flags & MS_DIRSYNC)
+ audit_log_format(ab, ", dirsync");
+ if (flags & MS_NOATIME)
+ audit_log_format(ab, ", noatime");
+ if (flags & MS_NODIRATIME)
+ audit_log_format(ab, ", nodiratime");
+ if (flags & MS_BIND)
+ audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
+ if (flags & MS_MOVE)
+ audit_log_format(ab, ", move");
+ if (flags & MS_SILENT)
+ audit_log_format(ab, ", silent");
+ if (flags & MS_POSIXACL)
+ audit_log_format(ab, ", acl");
+ if (flags & MS_UNBINDABLE)
+ audit_log_format(ab, flags & MS_REC ? ", runbindable" :
+ ", unbindable");
+ if (flags & MS_PRIVATE)
+ audit_log_format(ab, flags & MS_REC ? ", rprivate" :
+ ", private");
+ if (flags & MS_SLAVE)
+ audit_log_format(ab, flags & MS_REC ? ", rslave" :
+ ", slave");
+ if (flags & MS_SHARED)
+ audit_log_format(ab, flags & MS_REC ? ", rshared" :
+ ", shared");
+ if (flags & MS_RELATIME)
+ audit_log_format(ab, ", relatime");
+ if (flags & MS_I_VERSION)
+ audit_log_format(ab, ", iversion");
+ if (flags & MS_STRICTATIME)
+ audit_log_format(ab, ", strictatime");
+ if (flags & MS_NOUSER)
+ audit_log_format(ab, ", nouser");
+}
+
+/**
+ * audit_cb - call back for mount specific audit fields
+ * @ab: audit_buffer (NOT NULL)
+ * @va: audit struct to audit values of (NOT NULL)
+ */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ if (sa->aad->mnt.type) {
+ audit_log_format(ab, " fstype=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.type);
+ }
+ if (sa->aad->mnt.src_name) {
+ audit_log_format(ab, " srcname=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
+ }
+ if (sa->aad->mnt.trans) {
+ audit_log_format(ab, " trans=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.trans);
+ }
+ if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
+ audit_log_format(ab, " flags=\"");
+ audit_mnt_flags(ab, sa->aad->mnt.flags);
+ audit_log_format(ab, "\"");
+ }
+ if (sa->aad->mnt.data) {
+ audit_log_format(ab, " options=");
+ audit_log_untrustedstring(ab, sa->aad->mnt.data);
+ }
+}
+
+/**
+ * audit_mount - handle the auditing of mount operations
+ * @profile: the profile being enforced (NOT NULL)
+ * @gfp: allocation flags
+ * @op: operation being mediated (NOT NULL)
+ * @name: name of object being mediated (MAYBE NULL)
+ * @src_name: src_name of object being mediated (MAYBE_NULL)
+ * @type: type of filesystem (MAYBE_NULL)
+ * @trans: name of trans (MAYBE NULL)
+ * @flags: filesystem idependent mount flags
+ * @data: filesystem mount flags
+ * @request: permissions requested
+ * @perms: the permissions computed for the request (NOT NULL)
+ * @info: extra information message (MAYBE NULL)
+ * @error: 0 if operation allowed else failure error code
+ *
+ * Returns: %0 or error on failure
+ */
+static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
+ const char *name, const char *src_name,
+ const char *type, const char *trans,
+ unsigned long flags, const void *data, u32 request,
+ struct file_perms *perms, const char *info, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa = { };
+ struct apparmor_audit_data aad = { };
+
+ if (likely(!error)) {
+ u32 mask = perms->audit;
+
+ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
+ mask = 0xffff;
+
+ /* mask off perms that are not being force audited */
+ request &= mask;
+
+ if (likely(!request))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ /* only report permissions that were denied */
+ request = request & ~perms->allow;
+
+ if (request & perms->kill)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ /* quiet known rejects, assumes quiet and kill do not overlap */
+ if ((request & perms->quiet) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ request &= ~perms->quiet;
+
+ if (!request)
+ return COMPLAIN_MODE(profile) ?
+ complain_error(error) : error;
+ }
+
+ sa.type = LSM_AUDIT_DATA_NONE;
+ sa.aad = &aad;
+ sa.aad->op = op;
+ sa.aad->name = name;
+ sa.aad->mnt.src_name = src_name;
+ sa.aad->mnt.type = type;
+ sa.aad->mnt.trans = trans;
+ sa.aad->mnt.flags = flags;
+ if (data && (perms->audit & AA_AUDIT_DATA))
+ sa.aad->mnt.data = data;
+ sa.aad->info = info;
+ sa.aad->error = error;
+
+ return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
+}
+
+/**
+ * match_mnt_flags - Do an ordered match on mount flags
+ * @dfa: dfa to match against
+ * @state: state to start in
+ * @flags: mount flags to match against
+ *
+ * Mount flags are encoded as an ordered match. This is done instead of
+ * checking against a simple bitmask, to allow for logical operations
+ * on the flags.
+ *
+ * Returns: next state after flags match
+ */
+static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
+ unsigned long flags)
+{
+ unsigned int i;
+
+ for (i = 0; i <= 31 ; ++i) {
+ if ((1 << i) & flags)
+ state = aa_dfa_next(dfa, state, i + 1);
+ }
+
+ return state;
+}
+
+/**
+ * compute_mnt_perms - compute mount permission associated with @state
+ * @dfa: dfa to match against (NOT NULL)
+ * @state: state match finished in
+ *
+ * Returns: mount permissions
+ */
+static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
+ unsigned int state)
+{
+ struct file_perms perms;
+
+ perms.kill = 0;
+ perms.allow = dfa_user_allow(dfa, state);
+ perms.audit = dfa_user_audit(dfa, state);
+ perms.quiet = dfa_user_quiet(dfa, state);
+ perms.xindex = dfa_user_xindex(dfa, state);
+
+ return perms;
+}
+
+static const char const *mnt_info_table[] = {
+ "match succeeded",
+ "failed mntpnt match",
+ "failed srcname match",
+ "failed type match",
+ "failed flags match",
+ "failed data match"
+};
+
+/*
+ * Returns 0 on success else element that match failed in, this is the
+ * index into the mnt_info_table above
+ */
+static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
+ const char *mntpnt, const char *devname,
+ const char *type, unsigned long flags,
+ void *data, bool binary, struct file_perms *perms)
+{
+ unsigned int state;
+
+ state = aa_dfa_match(dfa, start, mntpnt);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 1;
+
+ if (devname)
+ state = aa_dfa_match(dfa, state, devname);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 2;
+
+ if (type)
+ state = aa_dfa_match(dfa, state, type);
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 3;
+
+ state = match_mnt_flags(dfa, state, flags);
+ if (!state)
+ return 4;
+ *perms = compute_mnt_perms(dfa, state);
+ if (perms->allow & AA_MAY_MOUNT)
+ return 0;
+
+ /* only match data if not binary and the DFA flags data is expected */
+ if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
+ state = aa_dfa_null_transition(dfa, state);
+ if (!state)
+ return 4;
+
+ state = aa_dfa_match(dfa, state, data);
+ if (!state)
+ return 5;
+ *perms = compute_mnt_perms(dfa, state);
+ if (perms->allow & AA_MAY_MOUNT)
+ return 0;
+ }
+
+ /* failed at end of flags match */
+ return 4;
+}
+
+/**
+ * match_mnt - handle path matching for mount
+ * @profile: the confining profile
+ * @mntpnt: string for the mntpnt (NOT NULL)
+ * @devname: string for the devname/src_name (MAYBE NULL)
+ * @type: string for the dev type (MAYBE NULL)
+ * @flags: mount flags to match
+ * @data: fs mount data (MAYBE NULL)
+ * @binary: whether @data is binary
+ * @perms: Returns: permission found by the match
+ * @info: Returns: infomation string about the match for logging
+ *
+ * Returns: 0 on success else error
+ */
+static int match_mnt(struct aa_profile *profile, const char *mntpnt,
+ const char *devname, const char *type,
+ unsigned long flags, void *data, bool binary,
+ struct file_perms *perms, const char **info)
+{
+ int pos;
+
+ if (!profile->policy.dfa)
+ return -EACCES;
+
+ pos = do_match_mnt(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ mntpnt, devname, type, flags, data, binary, perms);
+ if (pos) {
+ *info = mnt_info_table[pos];
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static int path_flags(struct aa_profile *profile, struct path *path)
+{
+ return profile->path_flags |
+ S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
+}
+
+int aa_remount(struct aa_profile *profile, struct path *path,
+ unsigned long flags, void *data)
+{
+ struct file_perms perms = { };
+ const char *name, *info = NULL;
+ char *buffer = NULL;
+ int binary, error;
+
+ binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
+ NULL, flags, data, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
+ const char *dev_name, unsigned long flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *old_buffer = NULL;
+ const char *name, *old_name = NULL, *info = NULL;
+ struct path old_path;
+ int error;
+
+ if (!dev_name || !*dev_name)
+ return -EINVAL;
+
+ flags &= MS_REC | MS_BIND;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ &old_buffer, &old_name, &info);
+ path_put(&old_path);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ kfree(buffer);
+ kfree(old_buffer);
+
+ return error;
+}
+
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
+ unsigned long flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL;
+ const char *name, *info = NULL;
+ int error;
+
+ /* These are the flags allowed by do_change_type() */
+ flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
+ MS_UNBINDABLE);
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
+ &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
+ NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_move_mount(struct aa_profile *profile, struct path *path,
+ const char *orig_name)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *old_buffer = NULL;
+ const char *name, *old_name = NULL, *info = NULL;
+ struct path old_path;
+ int error;
+
+ if (!orig_name || !*orig_name)
+ return -EINVAL;
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ &old_buffer, &old_name, &info);
+ path_put(&old_path);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ kfree(buffer);
+ kfree(old_buffer);
+
+ return error;
+}
+
+int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
+ struct path *path, const char *type, unsigned long flags,
+ void *data)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL, *dev_buffer = NULL;
+ const char *name = NULL, *dev_name = NULL, *info = NULL;
+ int binary = 1;
+ int error;
+
+ dev_name = orig_dev_name;
+ if (type) {
+ int requires_dev;
+ struct file_system_type *fstype = get_fs_type(type);
+ if (!fstype)
+ return -ENODEV;
+
+ binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
+ requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
+ put_filesystem(fstype);
+
+ if (requires_dev) {
+ struct path dev_path;
+
+ if (!dev_name || !*dev_name) {
+ error = -ENOENT;
+ goto out;
+ }
+
+ error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(&dev_path,
+ path_flags(profile, &dev_path),
+ &dev_buffer, &dev_name, &info);
+ path_put(&dev_path);
+ if (error)
+ goto audit;
+ }
+ }
+
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ error = match_mnt(profile, name, dev_name, type, flags, data, binary,
+ &perms, &info);
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name,
+ type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
+ error);
+ kfree(buffer);
+ kfree(dev_buffer);
+
+out:
+ return error;
+
+}
+
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
+{
+ struct file_perms perms = { };
+ char *buffer = NULL;
+ const char *name, *info = NULL;
+ int error;
+
+ struct path path = { mnt, mnt->mnt_root };
+ error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
+ &info);
+ if (error)
+ goto audit;
+
+ if (!error && profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+ }
+
+ if (AA_MAY_UMOUNT & ~perms.allow)
+ error = -EACCES;
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
+ NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
+ kfree(buffer);
+
+ return error;
+}
+
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
+ struct path *new_path)
+{
+ struct file_perms perms = { };
+ struct aa_profile *target = NULL;
+ char *old_buffer = NULL, *new_buffer = NULL;
+ const char *old_name, *new_name = NULL, *info = NULL;
+ int error;
+
+ error = aa_path_name(old_path, path_flags(profile, old_path),
+ &old_buffer, &old_name, &info);
+ if (error)
+ goto audit;
+
+ error = aa_path_name(new_path, path_flags(profile, new_path),
+ &new_buffer, &new_name, &info);
+ if (error)
+ goto audit;
+
+ if (profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ new_name);
+ state = aa_dfa_null_transition(profile->policy.dfa, state);
+ state = aa_dfa_match(profile->policy.dfa, state, old_name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+ }
+
+ if (AA_MAY_PIVOTROOT & perms.allow) {
+ if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
+ target = x_table_lookup(profile, perms.xindex);
+ if (!target)
+ error = -ENOENT;
+ else
+ error = aa_replace_current_profile(target);
+ }
+ } else
+ error = -EACCES;
+
+audit:
+ error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
+ old_name, NULL, target ? target->base.name : NULL,
+ 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error);
+ aa_put_profile(target);
+ kfree(old_buffer);
+ kfree(new_buffer);
+
+ return error;
+}
--
1.7.10.4

View File

@@ -0,0 +1,70 @@
From 663d5bbe6197bf990721c37ec877ea8ba5840202 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 24 Oct 2012 06:27:32 -0700
Subject: [PATCH 6/6] apparmor: fix IRQ stack overflow during free_profile
BugLink: http://bugs.launchpad.net/bugs/1056078
Profile replacement can cause long chains of profiles to build up when
the profile being replaced is pinned. When the pinned profile is finally
freed, it puts the reference to its replacement, which may in turn nest
another call to free_profile on the stack. Because this may happen for
each profile in the replacedby chain this can result in a recusion that
causes the stack to overflow.
Break this nesting by directly walking the chain of replacedby profiles
(ie. use iteration instead of recursion to free the list). This results
in at most 2 levels of free_profile being called, while freeing a
replacedby chain.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
---
security/apparmor/policy.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 27c8161..56e5304 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -724,6 +724,8 @@ fail:
*/
static void free_profile(struct aa_profile *profile)
{
+ struct aa_profile *p;
+
AA_DEBUG("%s(%p)\n", __func__, profile);
if (!profile)
@@ -752,7 +754,27 @@ static void free_profile(struct aa_profile *profile)
aa_put_dfa(profile->xmatch);
aa_put_dfa(profile->policy.dfa);
- aa_put_profile(profile->replacedby);
+ /* put the profile reference for replacedby, but not via
+ * put_profile(kref_put).
+ * replacedby can form a long chain that can result in cascading
+ * frees that blows the stack because kref_put makes a nested fn
+ * call (it looks like recursion, with free_profile calling
+ * free_profile) for each profile in the chain lp#1056078.
+ */
+ for (p = profile->replacedby; p; ) {
+ if (atomic_dec_and_test(&p->base.count.refcount)) {
+ /* no more refs on p, grab its replacedby */
+ struct aa_profile *next = p->replacedby;
+ /* break the chain */
+ p->replacedby = NULL;
+ /* now free p, chain is broken */
+ free_profile(p);
+
+ /* follow up with next profile in the chain */
+ p = next;
+ } else
+ break;
+ }
kzfree(profile);
}
--
1.7.10.4

View File

@@ -1,6 +1,7 @@
#!/bin/sh
DIE=0
package=libapparmor
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
@@ -19,7 +20,7 @@ DIE=0
DIE=1
}
(libtool --version) < /dev/null > /dev/null 2>&1 || {
(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have libtool installed to compile $package."
echo "Download the appropriate package for your system,"

View File

@@ -10,6 +10,7 @@ AM_INIT_AUTOMAKE(libapparmor1, apparmor_version)
AM_PROG_LEX
AC_PROG_YACC
AC_PROG_SED
PKG_PROG_PKG_CONFIG
AC_PATH_PROG([SWIG], [swig])

View File

@@ -99,16 +99,25 @@ Insufficient kernel memory was available.
=item B<EPERM>
The calling application is not confined by apparmor.
The calling application is not confined by apparmor, the specified
I<subprofile> is not a I<hat profile>, the task is being ptraced and the
tracing task does not have permission to trace the specified I<subprofile> or the no_new_privs execution bit is
enabled.
=item B<ECHILD>
The application's profile has no hats defined for it.
=item B<ENOENT>
The specified I<subprofile> does not exist in this profile but other hats
are defined.
=item B<EACCES>
The specified I<subprofile> does not exist in this profile or the
process tried to change another process's domain.
The specified magic token did not match, and permissions to change to
the specified I<subprofile> has been denied. This will in most situations
also result in the task being killed, to prevent brute force attacks.
=back
@@ -239,7 +248,7 @@ The output when run:
=head1 BUGS
None known. If you find any, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>. Note that
L<https://bugs.launchpad.net/apparmor/+filebug>. Note that
aa_change_hat(2) provides no memory barriers between different areas of a
program; if address space separation is required, then separate processes
should be used.

View File

@@ -74,8 +74,9 @@ errno(3) is set appropriately.
=item B<EINVAL>
The apparmor kernel module is not loaded or the communication via the
F</proc/*/attr/current> file did not conform to protocol.
The apparmor kernel module is not loaded, neither a profile nor a namespace
was specified, or the communication via the F</proc/*/attr/current> file did
not conform to protocol.
=item B<ENOMEM>
@@ -83,12 +84,18 @@ Insufficient kernel memory was available.
=item B<EPERM>
The calling application is not confined by apparmor.
The calling application is not confined by apparmor, or the no_new_privs
bit is set.
=item B<EACCES>
The task does not have sufficient permissions to change its domain.
=item B<ENOENT>
The specified profile does not exist, or is not visible from the current
Namespace.
=back
=head1 EXAMPLE
@@ -190,7 +197,7 @@ used (in addition to the one for 'i_cant_be_trusted_anymore', above):
=head1 BUGS
None known. If you find any, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>. Note that using
L<https://bugs.launchpad.net/apparmor/+filebug>. Note that using
aa_change_profile(2) without execve(2) provides no memory barriers between
different areas of a program; if address space separation is required, then
separate processes should be used.

View File

@@ -110,7 +110,7 @@ The apparmor filesystem mount could not be found
=head1 BUGS
None known. If you find any, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO

View File

@@ -103,7 +103,7 @@ The confinement data is to large to fit in the supplied buffer.
=head1 BUGS
None known. If you find any, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO

View File

@@ -17,9 +17,9 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
# Check for a version of Python >= 2.1.0
#
AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
ac_supports_python_ver=`$PYTHON -c "import sys, string; \
ver = string.split(sys.version)[[0]]; \
print ver >= '2.1.0'"`
ac_supports_python_ver=`$PYTHON -c "import sys; \
ver = sys.version.split()[[0]]; \
sys.stdout.write(str(ver >= '2.1.0'))"`
if test "$ac_supports_python_ver" != "True"; then
if test -z "$PYTHON_NOVERSIONCHECK"; then
AC_MSG_RESULT([no])
@@ -44,9 +44,9 @@ to something else than an empty string.
#
if test -n "$1"; then
AC_MSG_CHECKING([for a version of Python $1])
ac_supports_python_ver=`$PYTHON -c "import sys, string; \
ver = string.split(sys.version)[[0]]; \
print ver $1"`
ac_supports_python_ver=`$PYTHON -c "import sys; \
ver = sys.version.split()[[0]]; \
sys.stdout.write("%s\n" % (ver == $1))"`
if test "$ac_supports_python_ver" = "True"; then
AC_MSG_RESULT([yes])
else
@@ -79,9 +79,12 @@ $ac_distutils_result])
# Check for Python include path
#
AC_MSG_CHECKING([for Python include path])
if type $PYTHON-config; then
PYTHON_CPPFLAGS=`$PYTHON-config --includes`
fi
if test -z "$PYTHON_CPPFLAGS"; then
python_path=`$PYTHON -c "import distutils.sysconfig; \
print distutils.sysconfig.get_python_inc();"`
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
if test -n "${python_path}"; then
python_path="-I$python_path"
fi
@@ -94,25 +97,26 @@ $ac_distutils_result])
# Check for Python library path
#
AC_MSG_CHECKING([for Python library path])
if type $PYTHON-config; then
PYTHON_LDFLAGS=`$PYTHON-config --ldflags`
fi
if test -z "$PYTHON_LDFLAGS"; then
# (makes two attempts to ensure we've got a version number
# from the interpreter)
py_version=`$PYTHON -c "from distutils.sysconfig import *; \
from string import join; \
print join(get_config_vars('VERSION'))"`
py_version=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
sys.stdout.write('%s\n' % ''.join(get_config_vars('VERSION')))"`
if test "$py_version" == "[None]"; then
if test -n "$PYTHON_VERSION"; then
py_version=$PYTHON_VERSION
else
py_version=`$PYTHON -c "import sys; \
print sys.version[[:3]]"`
sys.stdout.write("%s\n" % sys.version[[:3]])"`
fi
fi
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
from string import join; \
print '-L' + get_python_lib(0,1), \
'-lpython';"`$py_version
PYTHON_LDFLAGS=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
sys.stdout.write('-L' + get_python_lib(0,1) + ' -lpython\n')"`$py_version`$PYTHON -c \
"import sys; sys.stdout.write('%s' % getattr(sys,'abiflags',''))"`
fi
AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS])
@@ -122,8 +126,8 @@ $ac_distutils_result])
#
AC_MSG_CHECKING([for Python site-packages path])
if test -z "$PYTHON_SITE_PKG"; then
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
print distutils.sysconfig.get_python_lib(0,0);"`
PYTHON_SITE_PKG=`$PYTHON -c "import sys; import distutils.sysconfig; \
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_lib(0,0));"`
fi
AC_MSG_RESULT([$PYTHON_SITE_PKG])
AC_SUBST([PYTHON_SITE_PKG])
@@ -133,9 +137,9 @@ $ac_distutils_result])
#
AC_MSG_CHECKING(python extra libraries)
if test -z "$PYTHON_EXTRA_LIBS"; then
PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
conf = distutils.sysconfig.get_config_var; \
print conf('LOCALMODLIBS'), conf('LIBS')"`
PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import distutils.sysconfig; \
conf = distutils.sysconfig.get_config_var; \
sys.stdout.write('%s %s\n' % (conf('LOCALMODLIBS'), conf('LIBS')))"`
fi
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
AC_SUBST(PYTHON_EXTRA_LIBS)
@@ -145,9 +149,9 @@ $ac_distutils_result])
#
AC_MSG_CHECKING(python extra linking flags)
if test -z "$PYTHON_EXTRA_LDFLAGS"; then
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
conf = distutils.sysconfig.get_config_var; \
print conf('LINKFORSHARED')"`
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import distutils.sysconfig; \
conf = distutils.sysconfig.get_config_var; \
sys.stdout.write('%s\n' % conf('LINKFORSHARED'))"`
fi
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
AC_SUBST(PYTHON_EXTRA_LDFLAGS)

View File

@@ -1,5 +1,29 @@
INCLUDES = $(all_includes)
# variables to set the library versions used by libtool
# Use these rules to update the library version.
# 1. Update the version information only immediately before a public release
# of your software. More frequent updates are unnecessary, and only
# guarantee that the current interface number gets larger faster.
# 2. If the library source code has changed at all since the last update,
# then
# - increment AA_LIB_REVISION
# 3. If any interfaces have been added, removed, or changed since the last
# update,
# - increment AA_LIB_CURRENT
# - set AA_LIB_REVISION to 0.
# 4. If any interfaces have been added since the last public release, then
# - increment AA_LIB_AGE.
# 5. If any interfaces have been removed or changed since the last public
# release, then
# - set AA_LIB_AGE to 0.
#
AA_LIB_CURRENT = 1
AA_LIB_REVISION = 7
AA_LIB_AGE = 0
SUFFIXES = .pc.in .pc
BUILT_SOURCES = grammar.h scanner.h af_protos.h
AM_LFLAGS = -v
AM_YFLAGS = -d -p aalogparse_
@@ -23,15 +47,24 @@ lib_LTLIBRARIES = libapparmor.la libimmunix.la
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c
libapparmor_la_LDFLAGS = -version-info 1:2:0 -XCClinker -dynamic \
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic \
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map -Wl,-soname=libapparmor.so.1
libimmunix_la_SOURCES = kernel_interface.c libimmunix_warning.c
libimmunix_la_LDFLAGS = -version-info 1:2:0 -Wl,--version-script=$(top_srcdir)/src/libapparmor.map -Wl,-soname=libimmunix.so.1
libimmunix_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -Wl,--version-script=$(top_srcdir)/src/libapparmor.map -Wl,-soname=libimmunix.so.1
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libapparmor.pc
CLEANFILES = libapparmor.pc
%.pc: %.pc.in $(top_builddir)/config.status
$(AM_V_GEN)cd "$(top_builddir)" && \
$(SHELL) ./config.status --file="src/$@"
tst_aalogmisc_SOURCES = tst_aalogmisc.c
tst_aalogmisc_LDADD = .libs/libapparmor.a
check_PROGRAMS = tst_aalogmisc
TESTS = $(check_PROGRAMS)
EXTRA_DIST = grammar.y scanner.l libapparmor.map
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc

View File

@@ -81,7 +81,7 @@ aa_record_event_type lookup_aa_event(unsigned int type)
%type <t_str> safe_string protocol
%token <t_long> TOK_DIGITS TOK_TYPE_UNKNOWN
%token <t_str> TOK_QUOTED_STRING TOK_ID TOK_MODE TOK_DMESG_STAMP
%token <t_str> TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE_TIME
%token <t_str> TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE TOK_TIME
%token <t_str> TOK_HEXSTRING TOK_TYPE_OTHER TOK_MSG_REST
%token <t_str> TOK_IP_ADDR
@@ -175,13 +175,17 @@ other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
syslog_type:
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
| syslog_date TOK_ID TOK_SYSLOG_KERNEL key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_AUDIT TOK_COLON key_type audit_id key_list
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
;
/* when audit dispatches a message it doesn't prepend the audit type string */
@@ -203,7 +207,10 @@ audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS
free($7);
} ;
syslog_date: TOK_DATE_MONTH TOK_DIGITS TOK_DATE_TIME { /* do nothing? */ }
syslog_date: TOK_DATE_MONTH TOK_DIGITS TOK_TIME
{ free($1); free($3); /* do nothing? */ }
| TOK_DATE TOK_TIME
{ free($1); free($2); /* do nothing */ }
;
key_list: key

View File

@@ -279,7 +279,8 @@ int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode)
if (rc == -1) {
free(buffer);
*buf = NULL;
*mode = NULL;
if (mode)
*mode = NULL;
} else
*buf = buffer;
@@ -333,7 +334,7 @@ int aa_change_hat(const char *subprofile, unsigned long token)
int rc = -1;
int len = 0;
char *buf = NULL;
const char *fmt = "changehat %016x^%s";
const char *fmt = "changehat %016lx^%s";
/* both may not be null */
if (!(token || subprofile)) {

View File

@@ -77,6 +77,10 @@ void free_record(aa_log_record *record)
free(record->net_protocol);
if (record->net_sock_type != NULL)
free(record->net_sock_type);
if (record->net_local_addr != NULL)
free(record->net_local_addr);
if (record->net_foreign_addr != NULL)
free(record->net_foreign_addr);
free(record);
}

View File

@@ -1,3 +1,5 @@
#If you update this file please update the library version in Makefile.am
IMMUNIX_1.0 {
global:
change_hat;

View File

@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libapparmor
Description: AppArmor library for for utility functions
Version: @VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lapparmor

View File

@@ -75,10 +75,12 @@ void string_buf_append(unsigned int length, char *text)
ws [ \t\r\n]
equals "="
digits [0-9]+
digit [[:digit:]]
digits {digit}+
hex [A-F0-9]
colon ":"
minus "-"
plus "+"
open_paren "("
close_paren ")"
ID [^ \t\n\(\)="'!]
@@ -144,8 +146,12 @@ ip_addr [a-f[:digit:].:]{3,}
/* syslog tokens */
syslog_kernel kernel{colon}
syslog_yyyymmdd {digit}{4}{minus}{digit}{2}{minus}{digit}{2}
syslog_date {syslog_yyyymmdd}
syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?
syslog_time {digits}{digits}{colon}{digits}{digits}{colon}{digits}{digits}
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:]_-]+
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
@@ -170,6 +176,7 @@ yy_flex_debug = 0;
<audit_id>{
{digits} { yylval->t_str = strdup(yytext); return(TOK_AUDIT_DIGITS);}
{colon}{ws} { yy_pop_state(yyscanner); return(TOK_COLON); }
{colon} { return(TOK_COLON); }
{period} { return(TOK_PERIOD); }
{open_paren} { return(TOK_OPEN_PAREN); }
@@ -291,7 +298,9 @@ yy_flex_debug = 0;
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
{syslog_month} { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_DATE_TIME); }
{syslog_date} { yylval->t_str = strdup(yytext); return(TOK_DATE); }
{syslog_date}T/{syslog_time} { yylval->t_str = strndup(yytext, strlen(yytext)-1); return(TOK_DATE); }
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_TIME); }
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }

View File

@@ -0,0 +1 @@
Sep 2 11:53:23 utopic-amd64 kernel: [182243.243324] audit: type=1400 audit(1409684003.960:273342): apparmor="DENIED" operation="mkdir" profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/mkdir" name="/tmp/sdtest.7283-14445-r31VAP/tmpdir/" pid=7314 comm="mkdir" requested_mask="c" denied_mask="c" fsuid=0 ouid=0

View File

@@ -0,0 +1,15 @@
START
File: test_multi/syslog_audit_01.in
Event type: AA_RECORD_DENIED
Audit ID: 1409684003.960:273342
Operation: mkdir
Mask: c
Denied Mask: c
fsuid: 0
ouid: 0
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/mkdir
Name: /tmp/sdtest.7283-14445-r31VAP/tmpdir/
Command: mkdir
PID: 7314
Epoch: 1409684003
Audit subid: 273342

View File

@@ -0,0 +1 @@
Dec 7 13:18:59 rosa kernel: audit: type=1400 audit(1417954745.397:82): apparmor="ALLOWED" operation="open" profile="/home/simi/bin/aa-test" name="/usr/bin/" pid=3231 comm="ls" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,15 @@
START
File: test_multi/syslog_audit_02.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1417954745.397:82
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /home/simi/bin/aa-test
Name: /usr/bin/
Command: ls
PID: 3231
Epoch: 1417954745
Audit subid: 82

View File

@@ -0,0 +1 @@
Jan 1 15:09:04 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_01.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
Jan 1 15:09:04+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_02.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
Jan 1 15:09:04.562575 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_03.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
Jan 1 15:09:04.562575+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_04.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
Jan 1 15:09:04-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_05.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
Jan 1 15:09:04.562575-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_06.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_07.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_08.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04.562575 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_09.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04.562575+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_10.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_11.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01 15:09:04.562575-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_12.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_13.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_14.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04.562575 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_15.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04.562575+08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_16.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_17.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -0,0 +1 @@
2013-01-01T15:09:04.562575-08:00 localhost kernel: [ 1911.569682] type=1400 audit(1357024144.556:6368): apparmor="ALLOWED" operation="open" parent=5390 profile="/usr/lib/virtualbox/VBoxSVC//null-2d" name="/sys/class/power_supply/" pid=5457 comm=4143504920506F6C6C6572 requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/syslog_datetime_18.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1357024144.556:6368
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 0
Profile: /usr/lib/virtualbox/VBoxSVC//null-2d
Name: /sys/class/power_supply/
Command: ACPI Poller
Parent: 5390
PID: 5457
Epoch: 1357024144
Audit subid: 6368

View File

@@ -48,7 +48,7 @@ but it may help you understand your profiles better.
B<apparmor.vim> does not properly detect dark versus light backgrounds.
Patches accepted. If you find any bugs, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO

View File

@@ -28,22 +28,99 @@ apparmor_parser - loads AppArmor profiles into the kernel
=head1 SYNOPSIS
B<apparmor_parser [-adrR] [--add] [--debug] [--replace] [--remove]
[--preprocess] [--Include n] [--base n] [ --Complain ]>
B<apparmor_parser [options] E<lt>commandE<gt> [profile]...>
B<apparmor_parser [options] E<lt>commandE<gt>>
B<apparmor_parser [-hv] [--help] [--version]>
=head1 DESCRIPTION
B<apparmor_parser> is used to import new apparmor.d(5) profiles
into the Linux kernel. The profiles restrict the operations available
to processes by executable name.
B<apparmor_parser> is used as a general tool to compile, and manage AppArmor
policy, including loading new apparmor.d(5) profiles into the Linux kernel.
AppArmor profiles restrict the operations available to processes.
The profiles are loaded into the Linux kernel by the B<apparmor_parser>
program, which takes its input from standard input. The input supplied to
B<apparmor_parser> should be in the format described in apparmor.d(5).
program, which by default takes its input from standard input. The input
supplied to B<apparmor_parser> should be in the format described in
apparmor.d(5).
=head1 OPTIONS
=head1 COMMANDS
The command set is broken into four subcategories.
=over 4
=item unprivileged commands
Commands that don't require any privilege and don't operate on profiles.
=item unprivileged profile commands
Commands that operate on a profile either specified on the command line or
read from stdin if no profile was specified.
=item privileged commands
Commands that require the MAC_ADMIN capability within the affected AppArmor
namespace to load policy into the kernel or filesystem write permissions to
update the affected privileged files (cache etc).
=item privileged profile commands
Commands that require privilege and operate on profiles.
=back
=head1 Unprivileged commands
=over 4
=item -V, --version
Print the version number and exit.
=item -h, --help
Give a quick reference guide.
=back
=head1 Unprivileged profile commands
=over 4
=item -N, --names
Produce a list of policies from a given set of profiles (implies -K).
=item -p, --preprocess
Apply preprocessing to the input profile(s) by flattening includes into
the output profile and dump to stdout.
=item -S, --stdout
Writes a binary (cached) profile to stdout (implies -K and -T).
=item -o file, --ofile file
Writes a binary (cached) profile to the specified file (implies -K and -T)
=back
=head1 Privileged commands
=over 4
=item --purge-cache
Unconditionally clear out cached profiles.
=back
=head1 Privileged profile commands
=over 4
@@ -67,25 +144,22 @@ Note that it still requires a complete AppArmor definition as described
in apparmor.d(5) even though the contents of the definition aren't
used.
=item -C, --Complain
=back
For the profile to load in complain mode.
=head1 OPTIONS
=over 4
=item -B, --binary
Load a binary (cached) profile, as produced with the -S option.
Treat the profile files specified on the command line (or stdin if none
specified) as binary cache files, produced with the -S or -o options,
and load to the kernel as specified by -a, -r, and -R (implies -K
and -T).
=item -N, --names
=item -C, --Complain
Produce a list of policies from a given set of profiles (implies -K).
=item -S, --stdout
Writes a binary (cached) profile to stdout (implies -K and -T).
=item -o file, --ofile file
Writes a binary (cached) profile to the specified file (implies -K and -T)
Force the profile to load in complain mode.
=item -b n, --base n
@@ -138,6 +212,11 @@ by default. In cases where abstractions have been changed, and the parser
is running with "--replace", it may make sense to also use
"--skip-read-cache" with the "--write-cache" option.
=item --skip-bad-cache
Skip updating the cache if it contains cached profiles in a bad or
inconsistent state
=item -L, --cache-loc
Set the location of the cache directory. If not specified the cache location
@@ -149,6 +228,9 @@ Perform all actions except the actual loading of a profile into the kernel.
This is useful for testing profile generation, caching, etc, without making
changes to the running kernel profiles.
This also removes the need for privilege to execute the commands that
manage policy in the kernel
=item -q, --quiet
Do not report on the profiles as they are loaded, and not show warnings.
@@ -157,15 +239,6 @@ Do not report on the profiles as they are loaded, and not show warnings.
Report on the profiles as they are loaded, and show warnings.
=item -V, --version
Print the version number and exit.
=item -p, --preprocess
Dump the input profile to stdout out applying preprocessing flattening
includes into the output profile.
=item -d, --debug
Given once, only checks the profiles to ensure syntactic correctness.
@@ -198,10 +271,6 @@ of time to complete.
Use --help=optimize to see a full list of which optimization flags are
supported.
=item -h, --help
Give a quick reference guide.
=back
=head1 CONFIG FILE
@@ -239,7 +308,7 @@ All other options override previously set values.
=head1 BUGS
If you find any bugs, please report them at
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO

View File

@@ -57,6 +57,8 @@ extern "C" void aare_delete_ruleset(aare_ruleset_t *rules)
if (rules->root)
rules->root->release();
free(rules);
aare_reset_matchflags();
}
}

View File

@@ -92,10 +92,10 @@ CHFA::CHFA(DFA &dfa, map<uchar, uchar> &eq, dfaflags_t flags): eq(eq)
default_base.push_back(make_pair(dfa.nonmatching, 0));
num.insert(make_pair(dfa.nonmatching, num.size()));
accept.resize(dfa.states.size());
accept2.resize(dfa.states.size());
next_check.resize(optimal);
free_list.resize(optimal);
accept.resize(max(dfa.states.size(), (size_t) 2));
accept2.resize(max(dfa.states.size(), (size_t) 2));
next_check.resize(max(optimal, (size_t) 256));
free_list.resize(next_check.size());
accept[0] = 0;
accept2[0] = 0;

View File

@@ -57,6 +57,7 @@ static inline Chars* insert_char_range(Chars* cset, uchar a, uchar b)
%pure-parser
/* %error-verbose */
%lex-param {YYLEX_PARAM}
%parse-param {Node **root}
%parse-param {const char *text}
%name-prefix = "regex_"

View File

@@ -265,6 +265,7 @@ extern int regex_type;
extern int perms_create;
extern int net_af_max_override;
extern int kernel_load;
extern int kernel_supports_setload;
extern int kernel_supports_network;
extern int kernel_supports_mount;
extern int flag_changehat_version;

View File

@@ -26,6 +26,7 @@ int regex_type = AARE_DFA;
int perms_create = 0; /* perms contain create flag */
int net_af_max_override = -1; /* use kernel to determine af_max */
int kernel_load = 1;
int kernel_supports_setload = 0; /* kernel supports atomic set loads */
int kernel_supports_network = 1; /* kernel supports network rules */
int kernel_supports_mount = 0; /* kernel supports mount rules */
int flag_changehat_version = FLAG_CHANGEHAT_1_5;

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