2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-03 15:55:46 +00:00

Compare commits

...

59 Commits

Author SHA1 Message Date
John Johansen
c52cf4d537 AppArmor 2.7 2011-12-15 04:20:50 -08:00
Steve Beattie
1e8dc4f375 This fixes the libapparmor log parsing library to properly parse log
entries where the comm entry has been hex-encoded. This occurs when the
binary being confined contains a space or other problematic character in
its filename. A test case is included.
2011-11-30 11:07:48 -08:00
Steve Beattie
7988124de5 Add a testcase for libapparmor for encoded profiles to ensure that
https://bugs.launchpad.net/apparmor/+bug/897957/ is in the utils and not
the parsing library itself.
2011-11-30 09:53:04 -08:00
Steve Beattie
f0aa65c832 abstractions/python: for some reason, the python runtimes need access
to pyconfig.h

Bug: https://launchpad.net/bugs/840734
2011-11-30 08:56:45 -08:00
Christian Boltz
1c96c09ec9 /usr/sbin/traceroute6 is a symlink to /usr/sbin/traceroute.
This patch allows "network inet6 raw" in addition to the ipv4 rule.

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

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-11-30 13:15:21 +01:00
Christian Boltz
9685aae967 rpmlint complains about an outdated FSF address in parser/COPYING.GPL.
This commit upgrades the COPYING.GPL file to the latest version from
http://www.gnu.org/licenses/gpl-2.0.txt - which means some small text 
and whitespace changes and of course the correct address.

Acked-by: John Johansen <john.johansen@canonical.com>
2011-11-27 13:52:06 +01:00
John Johansen
c7a6608777 bzr tag apparmor_2.7.0-rc2 2011-11-10 09:59:36 -08:00
John Johansen
bca67d3d27 apparmor-2.7~rc2 2011-11-10 09:51:18 -08:00
John Johansen
9c39909a9c Author: Michael (kensington)
When executing apparmor_status from rc functions and utils are not installed, this message is received:

AppArmor is enabled,
Install the apparmor-utils package to receive more detailed
status information here (or examine directly).

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-11-10 09:43:10 -08:00
John Johansen
f278505db2 Author: Michael (kensington)
parser/Makefile has a number of issues.

* Some warnings are produced: "make[1]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule."
* CXX is not always respected
* LDFLAGS are not always respected

modified to apply and retain $(Q) by John Johansen

Signed-off-by: John Johansen <john.johansen@canoncial.com>
2011-11-10 09:36:52 -08:00
John Johansen
e91cc118df Author: Michael (kensington)
When running installing apparmor-utils from Makefile, some warnings are
generated: make[1]: warning: jobserver unavailable: using -j1. Add
 `+' to parent make rule.

Use $(MAKE) instead of make

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-11-10 09:27:29 -08:00
John Johansen
e1763ba13c Auther: Michael (kensington)
libapparmor python bindings fail to build with python-3.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-11-10 09:22:09 -08:00
Seth Arnold
cad0c3c8a9 Include mknod in file operations aa-logprof / aa-genprof processing 2011-11-08 19:06:49 -08:00
Christian Boltz
49103b30f2 Make abstractions/winbind work on 64bit systems (valid.dat etc. are in
/usr/lib64/samba/ in openSUSE 64bit installations)

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-11-01 18:35:29 +01:00
Christian Boltz
df47a59ecb Allow loading the libraries used for Samba "vfs objects = ..."
References: https://bugzilla.novell.com/show_bug.cgi?id=725967

Signed-off-by: Christian Boltz <apparmor@cboltz.de>

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-11-01 18:28:49 +01:00
Christian Boltz
091ec763f9 split off abstractions/ldapclient from abstractions/nameservice
Original openSUSE changelog entry:

Thu Jan  6 16:23:19 UTC 2011 - rhafer@suse.de

- Splitted ldap related things from nameservice into separate
  profile and added some missing paths (bnc#662761)
2011-11-01 17:08:37 +01:00
Christian Boltz
33b7c5316f create the directory /etc/apparmor.d/disable which is required by aa-disable
Acked-by: John Johansen <john.johansen@canonical.com>
2011-10-20 00:23:19 +02:00
Christian Boltz
986093cf8d More helpful error message for "aa-notify -p" if a user is not member of
the group configured in notify.conf / use_group=...

Acked-by: John Johansen <john.johansen@canonical.com>
2011-10-20 00:20:02 +02:00
John Johansen
33c62acc5c Update version to 2.7~rc1 2011-10-12 16:45:45 -07:00
Christian Boltz
8b671f013a add the option --display to set the $DISPLAY environment variable in aa-notify.
If $DISPLAY is not set and --display is not used, aa-notify prints a 
warning that notifications won't be shown (exact warning text depends if 
using sudo or not).

Acked-by: John Johansen <john.johansen@canonical.com>
2011-10-12 13:08:25 +02:00
Christian Boltz
5789ab84a6 allow read access for /proc/*/mounts in the dovecot profile
Reported by Tim Edwards in the opensuse-factory	mailinglist.


Acked-by: John Johansen <john.johansen@canonical.com>
2011-10-12 13:05:00 +02:00
Christian Boltz
6d6e04dc12 fix a syntax error in remove_profiles() in rc.apparmor.functions by
adding a forgotten pipe.

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-10-12 00:45:11 +02:00
John Johansen
7a7c99f3a1 Commit the example parser.conf file that was supposed to be part of
commit r1834

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-10-09 20:15:03 -07:00
John Johansen
9896f5edbd Add an example parser.conf file
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
2011-10-07 14:43:54 -07:00
John Johansen
12a98135bf Provide a more user friendly error message when cache is
requested and fails to be created.  Also don't make the
warning output conditional on the showcache flag as we
should be showing warning/errors by default.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-10-07 14:42:55 -07:00
Jamie Strandboge
a30dfb6b19 utils/aa-notify:
- set HOME (and DISPLAY) only once on startup to avoid NSS lookups

Acked-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <opensuse@cboltz.de>
2011-09-30 18:00:52 -05:00
Christian Boltz
a4d4eddd92 while aa-eventd is deprecated and no longer installed, parser/Makefile
happily continued to install the initscript for aa-eventd.

This was reported by Jiri Srain as part of 
https://bugzilla.novell.com/show_bug.cgi?id=720617

This commit removes the lines that install the aaeventd initscript
from parser/Makefile.

Acked-by: John Johansen <john.johansen@canonical.com>
2011-10-01 00:23:39 +02:00
Christian Boltz
b393893c7a sudo resets the environment variable $HOME and removes $DISPLAY on
openSUSE, which results in non-working desktop notifications in aa-notify
because $notify_exe is unable to connect to DBUS to display the message.

This patch sets the correct value for $HOME.

The code for setting $DISPLAY is still under discussion, therefore only
a TODO note is included in this commit for $DISPLAY.

Acked-By: John Johansen <john.johansen@canonical.com>
2011-09-24 13:19:10 +02:00
John Johansen
572fb7e943 AppArmor_2.7-beta2
Signed-off-by: John Johansen@canonical.com
2011-09-15 13:55:48 -07:00
John Johansen
7173d7a6a5 Remove extra space insert at from of ${TAG_VERSION} when doing the ~ to -
substitution.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-09-15 13:28:01 -07:00
John Johansen
7b577d72b5 Remove ~ based tags again
Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-09-15 12:50:10 -07:00
Christian Boltz
5a140c2e5c while debugging the issue in rc.apparmor.suse (see patch for
rc.apparmor.suse), I noticed that "rcapparmor restart" is
totally silent.

The attached patch prints a message in __apparmor_restart().

It also replaces the hardcoded "return 0" with $?. I'm quite sure this
won't catch all errors, but it's still better than the hardcoded success
message.

Acked-by: John Johansen <john.johansen@canonical.com>
2011-09-15 21:23:25 +02:00
Christian Boltz
e922cdb113 sbin.syslog-ng profile:
- fix permissions for additional-log-sockets.conf (the comma in {var/,} 
  was at the wrong place, which broke the /var/run/ case)
- add read permissions for /sys/devices/system/cpu/online
  (that was even new for Peter, but I trust him not to post faked 
  audit.log lines ;-)

Acked-by: John Johansen <john.johansen@canonical.com>
2011-09-15 21:21:57 +02:00
Christian Boltz
189da8236c the last patch to the usr.sbin.dnsmasq profile (r1758) contained a wrong
filename.

References: https://bugzilla.novell.com/show_bug.cgi?id=678749#c11

Acked-by: John Johansen <john.johansen@canonical.com>
2011-09-15 20:58:54 +02:00
Christian Boltz
2c62d802b6 It looks like rc.apparmor.functions renamed "aa_log_action_begin()" to
"aa_log_action_start()" (probably for 2.6), but the rc.apparmor.suse 
initscript was not updated.

This patch fixes the function name in the rc.apparmor.suse initscript.

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

Acked-by: John Johansen <john.johansen@canonical.com>
2011-09-15 20:20:23 +02:00
Christian Boltz
23df761b70 Make the VENDOR_PERL directoy autodetected in utils/Makefile instead of
hardcoding it.

Acked-by: Kees Cook <kees@ubuntu.com>
2011-09-15 20:17:58 +02:00
Christian Boltz
6a80641ee2 perl modules don't need execute permissions.
This patch installs the perl modules with mode 644 instead of 755.

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-09-13 20:58:24 +02:00
Christian Boltz
02e1e94ab9 add a missing "make install" call to README in the libapparmor section.
Acked-by: John Johansen <john.johansen@canonical.com>
2011-09-12 22:30:17 +02:00
Jamie Strandboge
f28b91b8cf add gwenview to abstractions/ubuntu-browsers.d/multimedia. This is the
default image viewer in Kubuntu (LP: #840973)
2011-09-07 15:00:45 -05:00
Jamie Strandboge
6849615de6 adjust ubuntu-email abstraction for thunderbird rapid release process 2011-09-02 13:21:06 -05:00
John Johansen
743f84099d Allow passing of DEBUG from make into the compile
Fix the build so
    
  make DEBUG=1
    
results in a compile with DEBUG turned on.
    
Also fix build errors in the compile with DEBUG is defined
    
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees.cook@canonical.com>
2011-09-01 11:57:54 -07:00
John Johansen
a041b1738c Remove apparmor_2.6.0~rc1 and apparmor_2.6.0~rc1 tags so git can sync
yet again!

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-31 16:15:44 -07:00
John Johansen
1056ef8418 Add missing documentation updates for aa_is_confined and aa_get_con.
This documentation should have been checked in as part of the patches
that added aa_is_confined and aa_get_con.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-31 16:07:55 -07:00
John Johansen
ac77e10a0f Fix missing pid_t dependency in apparmor.h
The define for pid_t is missing in apparmor.h so that if it is included
in programs that don't also include sys/types.h the compile will break.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees.cook@canonical.com>
2011-08-31 16:01:54 -07:00
John Johansen
eae6f0525c Add missing introspection regression test that should have been checked in
with the introspection patches.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-31 15:58:27 -07:00
John Johansen
341b7e61da Add compatibility patches for linux kernel 3.1 2011-08-27 12:56:53 -07:00
John Johansen
eb6d2224bd Updated kernel compatibilty patches for linux 3.0 2011-08-27 12:25:22 -07:00
Christian Boltz
bb1b5f986b Add permissions needed for Active Directory authentification to Samba
profiles.

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

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-27 20:50:42 +02:00
Steve Beattie
1c1cc65cbd Update useradd and userdel profiles to use wutmp abstraction. 2011-08-26 18:58:31 -07:00
Steve Beattie
5dedd16bf5 Cleanup no longer necessary wutmp permission now that it's covered by
the wutmp abstraction.
2011-08-26 18:51:03 -07:00
Christian Boltz
66d51b575d From: Jeff Mahoney <jeffm@suse.com>
Subject: apparmor-profiles: Add samba config files
References: bnc#679182 bnc#666450

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

- updated to match trunk
- added changed path to nmbd profile (/var/cache/samba has moved to 
  /var/lib/samba on (at least) openSUSE 11.4), bnc#679182#c8
  For backward compability, it also allows /var/spool/samba.
- Note: The smbd profile already contains both locations.
by Christian Boltz <apparmor@cboltz.de>

updated according to the comments from Steve Beattie
by Christian Boltz <apparmor@cboltz.de>

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-27 01:52:27 +02:00
Christian Boltz
f26df713c0 Dovecot profile update:
- allow /var/spool/mail, not only the /var/mail symlink
- allow @{HOME}/Mail/
- allow capability fsetid, read access to /etc/lsb-release and 
  SuSE-release and k for /var/{lib,run}/dovecot in usr.bin.dovecot

References:
- dovecot: Added support for /var/spool/mail (bnc#691072)
- Updated dovecot profile (bnc#681267).

Patch taken from openSUSE:11.4:Update:Test, file apparmor-profiles-dovecot
updated to match trunk by Christian Boltz <apparmor@cboltz.de>

Change compared to the patch posted to the ML:
- link rule instead of adding l permissions for /var/lib/dovecot and 
  /var/run/dovecot (as proposed by John Johansen)

Acked-By: John Johansen <john.johansen@canonical.com> on IRC
2011-08-27 01:12:10 +02:00
Steve Beattie
b8f486dee9 Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.

In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.

An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.

To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)).  So to me, awk (sans GNU extensions) looks to
be the least bad option here.

Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
Christian Boltz
ac7e66684c Add various capabilities to smbd that are needed for the way powerpoint
handles files. See bnc#705319 for details.

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

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-26 23:19:30 +02:00
Steve Beattie
be3d2bc1a4 Update traceroute profile to include installed path on Ubuntu/Debian. 2011-08-25 15:36:30 -07:00
Christian Boltz
8f28eebe5a Add capability setuid and setgid to nscd profile. Needed by unscd
to switch to a non-root user. unscd is installed as /usr/sbin/nscd
at least at openSUSE.

Original changelog entry from unscd package:
Mon Sep  7 17:30:36 CEST 2009 - pbaudis[at]suse.cz
- Provide the /etc/apparmor.d/usr.sbin.nscd file and make it allow
  for change to the nobody user [bnc#535467]

Currently the nscd package from glibc and the unscd package both contain
a usr.sbin.nscd profile which needs to maintained/updated manually.
With this patch, the profile could be moved back to the
apparmor-profiles package.


Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-24 00:57:42 +02:00
Christian Boltz
d17a87bd28 bnc#685674 - The "-I" flag of traceroute is blocked by apparmor
* Do Apr 07 2011 jeffm@suse.de
- Add raw network access to traceroute profile (bnc#685674).

Acked-By: Steve Beattie <steve@nxnw.org>
2011-08-23 02:10:14 +02:00
Christian Boltz
59eb0af705 nscd: allow mkdir for /var/run/nscd/
References: https://bugzilla.novell.com/show_bug.cgi?id=647718

Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-23 01:22:41 +02:00
Christian Boltz
7d5840d449 apparmor.vim:
- allow "deny [filename] x" rules
- add support for "make clean"

Acked-by: John Johansen <john.johansen@canonical.com>
2011-08-21 23:49:25 +02:00
58 changed files with 2519 additions and 113 deletions

View File

@@ -23,7 +23,7 @@ __SETUP_DIR?=.
# We create a separate version for tags because git can't handle tags
# with embedded ~s in them. No spaces around '-' or they'll get
# embedded in ${VERSION}
TAG_VERSION=$(subst ~,-, ${VERSION})
TAG_VERSION=$(subst ~,-,${VERSION})
.PHONY: tarball
tarball: clean

1
README
View File

@@ -65,6 +65,7 @@ $ sh ./autogen.sh
$ sh ./configure --prefix=/usr --with-perl # see below
$ make
$ make check
$ make install
[optional arguments to libapparmor's configure include --with-python
and --with-ruby, to generate python and ruby bindings to libapparmor,

View File

@@ -1 +1 @@
2.7.0~beta1
2.7.0

View File

@@ -0,0 +1,553 @@
From dc13dec93dbd04bfa7a9ba67df1b8ed3431d8d48 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:39 -0700
Subject: [PATCH 1/3] AppArmor: compatibility patch for v5 network controll
Add compatibility for v5 network rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
include/linux/lsm_audit.h | 4 +
security/apparmor/Makefile | 19 ++++-
security/apparmor/include/net.h | 40 +++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 48 ++++++++++-
8 files changed, 394 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 88e78de..c63979a 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -124,6 +124,10 @@ struct common_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
} apparmor_audit_data;
#endif
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50..7cefef9 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 af_names.h
# Build a lower case string table of capability names
@@ -44,9 +44,24 @@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
echo "};" >> $@
+# Build a lower case string table of address family names.
+# Transform lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [2] = "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 "};" >> $@
+
+
$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
+$(obj)/net.o : $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
$(call cmd,make-rlim)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
\ No newline at end of file
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..3c7d599
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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>
+
+/* 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 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 aeda5cf..6776929 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 *profile_mode_names[];
@@ -145,6 +146,7 @@ struct aa_namespace {
* @size: the memory consumed by this profiles rules
* @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
@@ -181,6 +183,7 @@ struct aa_profile {
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 3d2fd14..aa293ae 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"
@@ -621,6 +622,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",
@@ -652,6 +751,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..1765901
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,170 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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 "af_names.h"
+
+static const char *sock_type_names[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
+/* 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;
+ if (sk) {
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
+ } else {
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ }
+ /* todo fill in socket addr info */
+
+ 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 4f0eade..4d5ce13 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 d6d9a57..f4874c4 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -190,6 +190,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)) {
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -559,6 +573,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;
+
/* get file rules */
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {
--
1.7.5.4

View File

@@ -0,0 +1,391 @@
From a2515f25ad5a7833ddc5a032d34eee6a5ddee3a2 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:40 -0700
Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 1 +
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 18 ++-
security/apparmor/include/apparmorfs.h | 6 +
5 files changed, 319 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/apparmorfs-24.c
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/Makefile b/security/apparmor/Makefile
index 7cefef9..0bb604b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,6 +5,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
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
clean-files := capability_names.h rlim_names.h af_names.h
diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
new file mode 100644
index 0000000..dc8c744
--- /dev/null
+++ b/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,287 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+ "user::other";
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+ .read = aa_features_read,
+};
+
+/**
+ * __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,
+};
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 0848292..28c52ac 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
aafs_remove(".remove");
aafs_remove(".replace");
aafs_remove(".load");
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ aafs_remove("profiles");
+ aafs_remove("matching");
+ aafs_remove("features");
+#endif
securityfs_remove(aa_fs_dentry);
aa_fs_dentry = NULL;
}
@@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
aa_fs_dentry = NULL;
goto error;
}
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+ if (error)
+ goto error;
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
+ if (error)
+ goto error;
+#endif
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a..14f955c 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,4 +17,10 @@
extern void __init aa_destroy_aafs(void);
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+extern const struct file_operations aa_fs_profiles_fops;
+#endif
+
#endif /* __AA_APPARMORFS_H */
--
1.7.5.4

View File

@@ -0,0 +1,69 @@
From 7a10d093f9779f42cb8d6affcb6a4436d3ebd6d3 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:41 -0700
Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken
userspace
The apparmor_parser when compiling policy could generate invalid dfas
that did not have sufficient padding to avoid invalid references, when
used by the kernel. The kernels check to verify the next/check table
size was broken meaning invalid dfas were being created by userspace
and not caught.
To remain compatible with old tools that are not fixed, pad the loaded
dfas next/check table. The dfa's themselves are valid except for the
high padding for potentially invalid transitions (high bounds error),
which have a maximimum is 256 entries. So just allocate an extra null filled
256 entries for the next/check tables. This will guarentee all bounds
are good and invalid transitions go to the null (0) state.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/match.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4..081491e 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -57,8 +57,17 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
if (bsize < tsize)
goto out;
+ /* Pad table allocation for next/check by 256 entries to remain
+ * backwards compatible with old (buggy) tools and remain safe without
+ * run time checks
+ */
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
+ tsize += 256 * th.td_flags;
+
table = kvmalloc(tsize);
if (table) {
+ /* ensure the pad is clear, else there will be errors */
+ memset(table, 0, tsize);
*table = th;
if (th.td_flags == YYTD_DATA8)
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
goto out;
if (flags & DFA_FLAG_VERIFY_STATES) {
+ int warning = 0;
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
/* TODO: do check that DEF state recursion terminates */
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (warning)
+ continue;
+ printk(KERN_WARNING "AppArmor DFA next/check "
+ "upper bounds error fixed, upgrade "
+ "user space tools \n");
+ warning = 1;
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;
--
1.7.5.4

View File

@@ -0,0 +1,553 @@
From dc13dec93dbd04bfa7a9ba67df1b8ed3431d8d48 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:39 -0700
Subject: [PATCH 1/3] AppArmor: compatibility patch for v5 network controll
Add compatibility for v5 network rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
include/linux/lsm_audit.h | 4 +
security/apparmor/Makefile | 19 ++++-
security/apparmor/include/net.h | 40 +++++++++
security/apparmor/include/policy.h | 3 +
security/apparmor/lsm.c | 112 +++++++++++++++++++++++
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1 +
security/apparmor/policy_unpack.c | 48 ++++++++++-
8 files changed, 394 insertions(+), 3 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 88e78de..c63979a 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -124,6 +124,10 @@ struct common_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
} apparmor_audit_data;
#endif
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50..7cefef9 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 af_names.h
# Build a lower case string table of capability names
@@ -44,9 +44,24 @@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
echo "};" >> $@
+# Build a lower case string table of address family names.
+# Transform lines from
+# #define AF_INET 2 /* Internet IP Protocol */
+# to
+# [2] = "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 "};" >> $@
+
+
$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
+$(obj)/net.o : $(obj)/af_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
$(call cmd,make-rlim)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+ $(call cmd,make-af)
\ No newline at end of file
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 0000000..3c7d599
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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>
+
+/* 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 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 aeda5cf..6776929 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 *profile_mode_names[];
@@ -145,6 +146,7 @@ struct aa_namespace {
* @size: the memory consumed by this profiles rules
* @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
@@ -181,6 +183,7 @@ struct aa_profile {
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 3d2fd14..aa293ae 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"
@@ -621,6 +622,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",
@@ -652,6 +751,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..1765901
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,170 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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 "af_names.h"
+
+static const char *sock_type_names[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
+/* 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;
+ if (sk) {
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
+ } else {
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ }
+ /* todo fill in socket addr info */
+
+ 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 4f0eade..4d5ce13 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 d6d9a57..f4874c4 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -190,6 +190,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)) {
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
{
struct aa_profile *profile = NULL;
const char *name = NULL;
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -559,6 +573,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;
+
/* get file rules */
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {
--
1.7.5.4

View File

@@ -0,0 +1,391 @@
From a2515f25ad5a7833ddc5a032d34eee6a5ddee3a2 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:40 -0700
Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 1 +
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 18 ++-
security/apparmor/include/apparmorfs.h | 6 +
5 files changed, 319 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/apparmorfs-24.c
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/Makefile b/security/apparmor/Makefile
index 7cefef9..0bb604b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,6 +5,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
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
clean-files := capability_names.h rlim_names.h af_names.h
diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
new file mode 100644
index 0000000..dc8c744
--- /dev/null
+++ b/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,287 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 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.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+ "user::other";
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+ .read = aa_features_read,
+};
+
+/**
+ * __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,
+};
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 0848292..28c52ac 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
aafs_remove(".remove");
aafs_remove(".replace");
aafs_remove(".load");
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ aafs_remove("profiles");
+ aafs_remove("matching");
+ aafs_remove("features");
+#endif
securityfs_remove(aa_fs_dentry);
aa_fs_dentry = NULL;
}
@@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
aa_fs_dentry = NULL;
goto error;
}
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+ if (error)
+ goto error;
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
+ if (error)
+ goto error;
+#endif
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a..14f955c 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,4 +17,10 @@
extern void __init aa_destroy_aafs(void);
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+extern const struct file_operations aa_fs_profiles_fops;
+#endif
+
#endif /* __AA_APPARMORFS_H */
--
1.7.5.4

View File

@@ -0,0 +1,69 @@
From 7a10d093f9779f42cb8d6affcb6a4436d3ebd6d3 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Wed, 10 Aug 2011 22:02:41 -0700
Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken
userspace
The apparmor_parser when compiling policy could generate invalid dfas
that did not have sufficient padding to avoid invalid references, when
used by the kernel. The kernels check to verify the next/check table
size was broken meaning invalid dfas were being created by userspace
and not caught.
To remain compatible with old tools that are not fixed, pad the loaded
dfas next/check table. The dfa's themselves are valid except for the
high padding for potentially invalid transitions (high bounds error),
which have a maximimum is 256 entries. So just allocate an extra null filled
256 entries for the next/check tables. This will guarentee all bounds
are good and invalid transitions go to the null (0) state.
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/match.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4..081491e 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -57,8 +57,17 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
if (bsize < tsize)
goto out;
+ /* Pad table allocation for next/check by 256 entries to remain
+ * backwards compatible with old (buggy) tools and remain safe without
+ * run time checks
+ */
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
+ tsize += 256 * th.td_flags;
+
table = kvmalloc(tsize);
if (table) {
+ /* ensure the pad is clear, else there will be errors */
+ memset(table, 0, tsize);
*table = th;
if (th.td_flags == YYTD_DATA8)
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
goto out;
if (flags & DFA_FLAG_VERIFY_STATES) {
+ int warning = 0;
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
/* TODO: do check that DEF state recursion terminates */
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (warning)
+ continue;
+ printk(KERN_WARNING "AppArmor DFA next/check "
+ "upper bounds error fixed, upgrade "
+ "user space tools \n");
+ warning = 1;
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;
--
1.7.5.4

View File

@@ -22,24 +22,36 @@
=head1 NAME
aa_is_enabled - determine if apparmor is available
aa_find_mountpoint - find where the apparmor interface filesystem is mounted
=head1 SYNOPSIS
B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_is_enabled(void);>
B<int aa_find_mountpoint(char **mnt);>
Link with B<-lapparmor> when compiling.
=head1 DESCRIPTION
The aa_is_enabled function returns true (1) if apparmor is enabled. If it
isn't it sets the errno to reflect the reason it is not enabled and returns 0.
The aa_find_mountpoint function finds where the apparmor filesystem is mounted
on the system, and returns a string containing the mount path. It is the
caller's responsibility to free(3) the returned path.
=head1 RETURN VALUE
B<aa_is_enabled>
On success 1 is returned. On error, 0 is returned, and errno(3) is set
appropriately.
B<aa_find_mountpoint>
On success zero is returned. On error, -1 is returned, and errno(3) is set
appropriately.
@@ -47,6 +59,36 @@ appropriately.
=over 4
B<aa_is_enabled>
=item B<ENOSYS>
AppArmor extensions to the system are not available.
=item B<ECANCELED>
AppArmor is available on the system but has been disabled at boot.
=item B<ENOENT>
AppArmor is available (and maybe even enforcing policy) but the interface is
not available.
=item B<ENOMEM>
Insufficient memory was available.
=item B<EPERM>
Did not have sufficient permissions to determine if AppArmor is enabled.
=item B<EACCES>
+Did not have sufficient permissions to determine if AppArmor is enabled.
B<aa_find_mountpoint>
=item B<ENOMEM>
Insufficient memory was available.

View File

@@ -33,7 +33,7 @@ aa_getpeercon - get the confinement of a socket's other end (peer)
B<#include E<lt>sys/apparmor.hE<gt>>
B<int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
char **mode);>
char **mode);>
B<int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);>
@@ -93,6 +93,10 @@ Access to the specified I<file/task> was denied.
The specified I<file/task> does not exist or is not visible.
=item B<ERANGE>
The confinement data is to large to fit in the supplied buffer.
=back
=head1 BUGS

View File

@@ -18,6 +18,8 @@
#ifndef _SYS_APPARMOR_H_
#define _SYS_APPARMOR_H 1
#include <sys/types.h>
__BEGIN_DECLS
/* Prototypes for apparmor state queries */

View File

@@ -246,7 +246,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
{ ret_record->fsuid = $3;}
| TOK_KEY_OUID TOK_EQUALS TOK_DIGITS
{ ret_record->ouid = $3;}
| TOK_KEY_COMM TOK_EQUALS TOK_QUOTED_STRING
| TOK_KEY_COMM TOK_EQUALS safe_string
{ ret_record->comm = $3;}
| TOK_KEY_APPARMOR TOK_EQUALS apparmor_event
| TOK_KEY_CAPABILITY TOK_EQUALS TOK_DIGITS

View File

@@ -265,7 +265,7 @@ yy_flex_debug = 0;
{key_error} { return(TOK_KEY_ERROR); }
{key_fsuid} { return(TOK_KEY_FSUID); }
{key_ouid} { return(TOK_KEY_OUID); }
{key_comm} { return(TOK_KEY_COMM); }
{key_comm} { BEGIN(safe_string); return(TOK_KEY_COMM); }
{key_capability} { return(TOK_KEY_CAPABILITY); }
{key_capname} { return(TOK_KEY_CAPNAME); }
{key_offset} { return(TOK_KEY_OFFSET); }

View File

@@ -13,7 +13,7 @@ setup(name = 'LibAppArmor',
ext_package = 'LibAppArmor',
ext_modules = [Extension('_LibAppArmor', ['libapparmor_wrap.c'],
include_dirs=['@top_srcdir@/src'],
extra_link_args = string.split('-L@top_builddir@/src/.libs -lapparmor'),
# static: extra_link_args = string.split('@top_builddir@/src/.libs/libapparmor.a'),
extra_link_args = '-L@top_builddir@/src/.libs -lapparmor'.split(),
# static: extra_link_args = '@top_builddir@/src/.libs/libapparmor.a'.split(),
)],
)

View File

@@ -0,0 +1 @@
type=AVC msg=audit(1322676143.201:455): apparmor="ALLOWED" operation="open" parent=10357 profile=2F686F6D652F73746576652F746D702F6D792070726F672E7368 name=2F686F6D652F73746576652F746D702F6D792070726F672E7368 pid=22918 comm=6D792070726F672E7368 requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000

View File

@@ -0,0 +1,16 @@
START
File: test_multi/testcase_encoded_comm.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1322676143.201:455
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 1000
Profile: /home/steve/tmp/my prog.sh
Name: /home/steve/tmp/my prog.sh
Command: my prog.sh
Parent: 10357
PID: 22918
Epoch: 1322676143
Audit subid: 455

View File

@@ -0,0 +1 @@
Aug 23 17:29:45 hostname kernel: [289763.843292] type=1400 audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=74657374207370616365 name="/lib/x86_64-linux-gnu/libdl-2.13.so" pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

View File

@@ -0,0 +1,16 @@
START
File: test_multi/testcase_encoded_profile.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1322614912.304:857
Operation: getattr
Mask: r
Denied Mask: r
fsuid: 0
ouid: 0
Profile: test space
Name: /lib/x86_64-linux-gnu/libdl-2.13.so
Command: bash
Parent: 16001
PID: 17011
Epoch: 1322614912
Audit subid: 857

View File

@@ -1,15 +1,15 @@
This license applies to all source files within the AppArmor parser
package.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -18,7 +18,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -58,8 +58,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -113,7 +113,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -171,7 +171,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -228,7 +228,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -258,7 +258,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -280,9 +280,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -294,7 +294,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) <year> <name of author>
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
@@ -306,17 +306,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -339,5 +338,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -49,7 +49,7 @@ ifndef CFLAGS
CFLAGS = -g -O2 -pipe
ifdef DEBUG
CFLAGS += -pg
CFLAGS += -pg -D DEBUG
endif
endif #CFLAGS
@@ -115,7 +115,7 @@ endif
export Q VERBOSE BUILD_OUTPUT
po/${NAME}.pot: ${SRCS} ${HDRS}
make -C po ${NAME}.pot NAME=${NAME} SOURCES="${SRCS} ${HDRS}"
$(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${SRCS} ${HDRS}"
techdoc.pdf: techdoc.tex
while pdflatex $< ${BUILD_OUTPUT} || exit 1 ; \
@@ -141,7 +141,7 @@ pdf: techdoc.pdf
docs: manpages htmlmanpages pdf
indep: docs
$(Q)make -C po all
$(Q)$(MAKE) -C po all
all: arch indep
@@ -149,10 +149,10 @@ all: arch indep
.PHONY: libstdc++.a
libstdc++.a:
rm -f ./libstdc++.a
ln -s `g++ -print-file-name=libstdc++.a`
ln -s `$(CXX) -print-file-name=libstdc++.a`
apparmor_parser: $(OBJECTS) $(AAREOBJECTS)
g++ $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
$(CXX) $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
${LEXLIB} $(AAREOBJECTS) $(AARE_LDFLAGS)
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
@@ -231,13 +231,13 @@ check: tests
.SILENT: tests
tests: apparmor_parser ${TESTS}
sh -e -c 'for test in ${TESTS} ; do echo "*** running $${test}" && ./$${test}; done'
$(Q)make -s -C tst tests
$(Q)$(MAKE) -s -C tst tests
# always need to rebuild.
.SILENT: $(AAREOBJECT)
.PHONY: $(AAREOBJECT)
$(AAREOBJECT):
make -C $(AAREDIR) CFLAGS="$(EXTRA_CXXFLAGS)"
$(MAKE) -C $(AAREDIR) CFLAGS="$(EXTRA_CXXFLAGS)"
.PHONY: install-rhel4
install-rhel4: install-redhat
@@ -246,17 +246,14 @@ install-rhel4: install-redhat
install-redhat:
install -m 755 -d $(DESTDIR)/etc/init.d
install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
install -m 755 rc.aaeventd.redhat $(DESTDIR)/etc/init.d/aaeventd
.PHONY: install-suse
install-suse:
install -m 755 -d $(DESTDIR)/etc/init.d
install -m 755 rc.apparmor.$(subst install-,,$(@)) $(DESTDIR)/etc/init.d/boot.apparmor
install -m 755 rc.aaeventd.$(subst install-,,$(@)) $(DESTDIR)/etc/init.d/aaeventd
install -m 755 -d $(DESTDIR)/sbin
ln -sf /etc/init.d/boot.apparmor $(DESTDIR)/sbin/rcapparmor
ln -sf rcapparmor $(DESTDIR)/sbin/rcsubdomain
ln -sf /etc/init.d/aaeventd $(DESTDIR)/sbin/rcaaeventd
.PHONY: install-slackware
install-slackware:
@@ -288,11 +285,12 @@ install-arch: $(INSTALLDEPS)
install-indep:
install -m 755 -d $(INSTALL_CONFDIR)
install -m 644 subdomain.conf $(INSTALL_CONFDIR)
install -m 644 parser.conf $(INSTALL_CONFDIR)
install -m 755 -d ${DESTDIR}/var/lib/apparmor
install -m 755 -d $(APPARMOR_BIN_PREFIX)
install -m 755 rc.apparmor.functions $(APPARMOR_BIN_PREFIX)
make -C po install NAME=${NAME} DESTDIR=${DESTDIR}
make install_manpages DESTDIR=${DESTDIR}
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
.SILENT: clean
.PHONY: clean
@@ -306,11 +304,11 @@ clean: _clean
rm -f af_names.h
rm -f cap_names.h
rm -rf techdoc.aux techdoc.log techdoc.pdf techdoc.toc techdor.txt techdoc/
make -s -C $(AAREDIR) clean
make -s -C po clean
make -s -C tst clean
$(MAKE) -s -C $(AAREDIR) clean
$(MAKE) -s -C po clean
$(MAKE) -s -C tst clean
.SILENT: dist_clean
dist_clean:
@make clean
@$(MAKE) clean
@rm -f $(LEX_C_FILES) $(YACC_C_FILES)

View File

@@ -103,6 +103,7 @@ make install DESTDIR=${RPM_BUILD_ROOT} \
/etc/init.d/aaeventd
%endif
%config(noreplace) /etc/apparmor/subdomain.conf
%config(noreplace) /etc/apparmor/parser.conf
/var/lib/apparmor
%dir %attr(-, root, root) %{apparmor_bin_prefix}
%{apparmor_bin_prefix}/rc.apparmor.functions

58
parser/parser.conf Normal file
View File

@@ -0,0 +1,58 @@
# parser.conf is a global AppArmor config file for the apparmor_parser
#
# It can be used to specify the default options for the parser, which
# can then be overriden by options passed on the command line.
#
# Leading whitespace is ignored and lines that begin with # are treated
# as comments.
#
# Config options are specified one per line using the same format as the
# longform command line options (without the preceding --).
#
# If a value is specified twice the last version to appear is used.
## Suppress Warnings
#quiet
## Be verbose
#verbose
## Set include path
#Include /etc/apparmor.d/abstractions
## Set location of apparmor filesystem
#subdomainfs /sys/kernel/security/apparmor
## Set match-string to use - for forcing compiler to treat different kernels
## the same
# match-string "pattern=aadfa audit perms=crwxamlk/ user::other"
## Turn creating/updating of the cache on by default
#write-cache
## Show cache hits
#show-cache
## skip cached policy
#skip-cache
## skip reading cache but allow updating
#skip-read-cache
#### Set Optimizaions. Multiple Optimizations can be set, one per line ####
# For supported optimizations see
# apparmor_parser --help=O
## Turn on equivalence classes
#equiv
## Turn off expr tree simplification
#Optimize=no-expr-simplify
## Turn off DFA minimization
#Optimize=no-minimize
## Adjust compression
#Optimize=compress-small
#Optimize=compress-fast

View File

@@ -1007,8 +1007,7 @@ out:
}
else {
unlink(cachetemp);
if (show_cache)
PERROR("Removed cache attempt: %s\n", cachetemp);
PERROR("Warning failed to create cache: %s\n", basename);
}
free(cachetemp);
}

View File

@@ -240,7 +240,7 @@ profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
post_process_nt_entries(cod);
PDEBUG("%s: flags='%s%s'\n",
$3,
$2,
cod->flags.complain ? "complain, " : "",
cod->flags.audit ? "audit" : "");
@@ -280,7 +280,7 @@ hat: hat_start profile_base
{
struct codomain *cod = $2;
if ($2)
PDEBUG("Matched: hat %s { ... }\n", code->name);
PDEBUG("Matched: hat %s { ... }\n", cod->name);
cod->flags.hat = 1;
$$ = cod;
@@ -384,7 +384,7 @@ valuelist: valuelist TOK_VALUE
struct value_list *new = calloc(1, sizeof(struct value_list));
if (!new)
yyerror(_("Memory allocation error."));
PDEBUG("Matched: value (%s)\n", $1);
PDEBUG("Matched: value list\n");
new->value = $2;
new->next = $1;

View File

@@ -83,15 +83,6 @@ SECURITYFS=/sys/kernel/security
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
if [ -d "/var/lib/${MODULE}" ] ; then
APPARMOR_TMPDIR="/var/lib/${MODULE}"
elif [ -d "/var/lib/${OLD_MODULE}" ] ; then
APPARMOR_TMPDIR="/var/lib/${OLD_MODULE}"
else
APPARMOR_TMPDIR="/tmp"
fi
# keep exit status from parser during profile load. 0 is good, 1 is bad
STATUS=0
@@ -221,7 +212,6 @@ parse_profiles() {
profiles_names_list() {
# run the parser on all of the apparmor profiles
TMPFILE=$1
if [ ! -f "$PARSER" ]; then
aa_log_failure_msg "- AppArmor parser not found"
exit 1
@@ -234,9 +224,9 @@ profiles_names_list() {
for profile in $PROFILE_DIR/*; do
if skip_profile "${profile}" && [ -f "${profile}" ] ; then
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '//')
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" )
if [ $? -eq 0 ]; then
echo "$LIST_ADD" >>$TMPFILE
echo "$LIST_ADD"
fi
fi
done
@@ -408,18 +398,16 @@ remove_profiles() {
fi
retval=0
#the list of profiles isn't stable once we start adding or removing
#them so store to tmp first (in reverse order so hat profiles are removed first)
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort -r > "$MODULE_PLIST"
cat "$MODULE_PLIST" | while read profile ; do
# We filter child profiles as removing the parent will remove
# the children
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
LC_COLLATE=C sort | grep -v // | while read profile ; do
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
rc=$?
if [ ${rc} -ne 0 ] ; then
retval=${rc}
fi
done
rm "$MODULE_PLIST"
return ${retval}
}
@@ -459,20 +447,41 @@ __apparmor_restart() {
return 4
fi
aa_log_daemon_msg "Restarting AppArmor"
configure_owlsm
parse_profiles reload
PNAMES_LIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
profiles_names_list ${PNAMES_LIST}
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
# Clean out running profiles not associated with the current profile
# set, excluding the libvirt dynamically generated profiles.
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | egrep -v '^libvirt-[0-9a-f\-]+$' | sort >"$MODULE_PLIST"
sort "$PNAMES_LIST" | comm -2 -3 "$MODULE_PLIST" - | while IFS= read profile ; do
# Note that we reverse sort the list of profiles to remove to
# ensure that child profiles (e.g. hats) are removed before the
# parent. We *do* need to remove the child profile and not rely
# on removing the parent profile when the profile has had its
# child profile names changed.
profiles_names_list | awk '
BEGIN {
while (getline < "'${SFS_MOUNTPOINT}'/profiles" ) {
str = sub(/ \((enforce|complain)\)$/, "", $0);
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
arr[$str] = $str
}
}
{ if (length(arr[$0]) > 0) { delete arr[$0] } }
END {
for (key in arr)
if (length(arr[key]) > 0) {
printf("%s\n", arr[key])
}
}
' | LC_COLLATE=C sort -r | while IFS= read profile ; do
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
done
rm "$MODULE_PLIST"
rm "$PNAMES_LIST"
return 0
# will not catch all errors, but still better than nothing
rc=$?
aa_log_end_msg $rc
return $rc
}
apparmor_restart() {
@@ -516,11 +525,11 @@ apparmor_status () {
${SD_STATUS} --verbose
return $?
fi
if ! is_apparmor_present apparmor subdomain ; then
if ! is_apparmor_loaded ; then
echo "AppArmor is not loaded."
rc=1
else
echo "AppArmor is enabled,"
echo "AppArmor is enabled."
rc=0
fi
echo "Install the apparmor-utils package to receive more detailed"

View File

@@ -77,7 +77,7 @@ aa_log_failure_msg() {
log_failure_msg '\n'$*
}
aa_log_action_begin() {
aa_log_action_start() {
echo -n
}

View File

@@ -52,6 +52,7 @@ install: local
install -m 755 -d ${PROFILES_DEST}
install -m 755 -d ${PROFILES_DEST}/abstractions \
${PROFILES_DEST}/apache2.d \
${PROFILES_DEST}/disable \
${PROFILES_DEST}/program-chunks \
${PROFILES_DEST}/tunables \
${PROFILES_DEST}/tunables/home.d \

View File

@@ -0,0 +1,21 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2011 Novell/SUSE
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# files required by LDAP clients (e.g. nss_ldap/pam_ldap)
/etc/ldap.conf r,
/etc/ldap.secret r,
/etc/openldap/* r,
/etc/openldap/cacerts/* r,
# SASL plugins and config
/etc/sasl2/* r,
/usr/lib{,32,64}/sasl2/* r,
#include <abstractions/ssl_certs>

View File

@@ -16,8 +16,6 @@
/etc/group r,
/etc/host.conf r,
/etc/hosts r,
/etc/ldap.conf r,
/etc/ldap.secret r,
/etc/nsswitch.conf r,
/etc/gai.conf r,
/etc/passwd r,
@@ -32,9 +30,6 @@
/etc/samba/lmhosts r,
/etc/services r,
# all openldap config
/etc/openldap/* r,
/etc/ldap/** r,
# db backend
/var/lib/misc/*.db r,
# The Name Service Cache Daemon can cache lookups, sometimes leading
@@ -60,6 +55,9 @@
# nis
#include <abstractions/nis>
# ldap
#include <abstractions/ldapclient>
# winbind
#include <abstractions/winbind>

View File

@@ -29,3 +29,6 @@
# wx paths
/usr/lib/wx/python/*.pth r,
# python build configuration and headers
/usr/include/python{2,3}.[0-7]*/pyconfig.h

View File

@@ -9,11 +9,11 @@
#
# ------------------------------------------------------------------
/etc/samba/smb.conf r,
/etc/samba/* r,
/usr/share/samba/*.dat r,
/var/lib/samba/**.tdb rwk,
/var/log/samba/cores/ rw,
/var/log/samba/cores/* w,
/var/log/samba/cores/** rw,
/var/log/samba/log.* w,
/{,var/}run/samba/*.tdb rw,

View File

@@ -11,6 +11,7 @@
/usr/bin/shotwell PUxr,
/usr/bin/digikam PUxr,
/usr/bin/f-spot PUxr,
/usr/bin/gwenview PUxr,
#include <abstractions/ubuntu-media-players>
owner @{HOME}/.macromedia/** rw,

View File

@@ -16,5 +16,5 @@
/usr/bin/tkrat PUx,
/usr/lib/thunderbird/thunderbird PUx,
/usr/lib/thunderbird-3*/thunderbird{,.sh} PUx,
/usr/lib/thunderbird-[1-9]*/thunderbird{,.sh} PUx,

View File

@@ -13,7 +13,7 @@
/tmp/.winbindd/pipe rw,
/var/{lib,run}/samba/winbindd_privileged/pipe rw,
/etc/samba/smb.conf r,
/usr/lib/samba/valid.dat r,
/usr/lib/samba/upcase.dat r,
/usr/lib/samba/lowcase.dat r,
/usr/lib*/samba/valid.dat r,
/usr/lib*/samba/upcase.dat r,
/usr/lib*/samba/lowcase.dat r,

View File

@@ -38,6 +38,7 @@
/etc/hosts.deny r,
/etc/hosts.allow r,
/sbin/syslog-ng mr,
/sys/devices/system/cpu/online r,
/usr/share/syslog-ng/** r,
# chrooted applications
@{CHROOT_BASE}/var/lib/*/dev/log w,
@@ -45,7 +46,7 @@
@{CHROOT_BASE}/var/log/** w,
@{CHROOT_BASE}/{,var/}run/syslog-ng.pid krw,
@{CHROOT_BASE}/{,var/}run/syslog-ng.ctl rw,
/{var,/}run/syslog-ng/additional-log-sockets.conf r,
/{var/,}run/syslog-ng/additional-log-sockets.conf r,
# Site-specific additions and overrides. See local/README for details.
#include <local/sbin.syslog-ng>

View File

@@ -17,6 +17,7 @@
@{HOME}/mail/.imap/** klrw,
/usr/lib/dovecot/deliver mr,
/var/mail/* klrw,
/var/spool/mail/* klrw,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.lib.dovecot.deliver>

View File

@@ -13,7 +13,6 @@
/proc/*/mounts r,
/usr/lib/dovecot/dovecot-auth mr,
/{,var/}run/utmp k,
/{,var/}run/dovecot/** rw,
# required for postfix+dovecot integration
/var/spool/postfix/private/dovecot-auth w,

View File

@@ -11,11 +11,15 @@
@{HOME} r,
@{HOME}/Maildir/ rw,
@{HOME}/Maildir/** klrw,
@{HOME}/Mail/ rw,
@{HOME}/Mail/* klrw,
@{HOME}/Mail/.imap/** klrw,
@{HOME}/mail/ rw,
@{HOME}/mail/* klrw,
@{HOME}/mail/.imap/** klrw,
/usr/lib/dovecot/imap mr,
/var/mail/* klrw,
/var/spool/mail/* klrw,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.lib.dovecot.imap>

View File

@@ -9,6 +9,7 @@
capability setuid,
/var/mail/* klrw,
/var/spool/mail/* klrw,
@{HOME} r,
@{HOME}/mail/* klrw,
@{HOME}/mail/.imap/** klrw,

View File

@@ -30,7 +30,7 @@
/usr/sbin/dnsmasq mr,
/{,var/}run/*dnsmasq*.pid w,
/{,var/}run/dnsmasq-forwarders r,
/{,var/}run/dnsmasq-forwarders.conf r,
/{,var/}run/dnsmasq/ r,
/{,var/}run/dnsmasq/* rw,

View File

@@ -13,9 +13,13 @@
capability setgid,
capability setuid,
capability sys_chroot,
capability fsetid,
/etc/dovecot/** r,
/etc/mtab r,
/etc/lsb-release r,
/etc/SuSE-release r,
@{PROC}/[0-9]*/mounts r,
/usr/lib/dovecot/dovecot-auth Pxmr,
/usr/lib/dovecot/imap Pxmr,
/usr/lib/dovecot/imap-login Pxmr,
@@ -30,6 +34,7 @@
/var/lib/dovecot/* krw,
/{,var/}run/dovecot/ rw,
/{,var/}run/dovecot/** rw,
link /{,var/}run/dovecot/** -> /var/lib/dovecot/**,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.sbin.dovecot>

View File

@@ -7,13 +7,19 @@
capability net_bind_service,
/proc/sys/kernel/core_pattern r,
/usr/sbin/nmbd mr,
/var/cache/samba/browse.dat* rw,
/var/lib/samba/wins.dat* rw,
/{,var/}run/samba/** rk,
/{,var/}run/samba/nmbd.pid rw,
/var/log/samba/cores/nmbd/ rw,
/var/log/samba/cores/nmbd/** rw,
/var/{cache,lib}/samba/browse.dat* rw,
/var/{cache,lib}/samba/wins.dat* rw,
/var/{cache,lib}/samba/smb_krb5/ rw,
/var/{cache,lib}/samba/smb_krb5/krb5.conf* rw,
/var/{cache,lib}/samba/smb_tmp_krb5.* rw,
/var/{cache,lib}/samba/sync.* rw,
/var/{cache,lib}/samba/unexpected rw,
/{,var/}run/samba/** rwk,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.sbin.nmbd>

View File

@@ -17,6 +17,8 @@
#include <abstractions/ssl_certs>
capability net_bind_service,
capability setgid,
capability setuid,
network inet dgram,
network inet stream,
@@ -28,7 +30,7 @@
/var/lib/samba/winbindd_privileged/pipe rw,
/{,var/}run/.nscd_socket wl,
/{,var/}run/avahi-daemon/socket w,
/{,var/}run/nscd/ r,
/{,var/}run/nscd/ rw,
/{,var/}run/nscd/db* wl,
/{,var/}run/nscd/socket wl,
/var/{cache,run}/nscd/{passwd,group,services,hosts} rw,

View File

@@ -10,6 +10,10 @@
#include <abstractions/user-tmp>
#include <abstractions/wutmp>
capability dac_override,
capability dac_read_search,
capability fowner,
capability lease,
capability net_bind_service,
capability setgid,
capability setuid,
@@ -19,7 +23,10 @@
/etc/mtab r,
/etc/printcap r,
/proc/*/mounts r,
/proc/sys/kernel/core_pattern r,
/usr/lib*/samba/vfs/*.so mr,
/usr/sbin/smbd mr,
/etc/samba/* rwk,
/var/cache/samba/** rwk,
/var/cache/samba/printing/printers.tdb mrw,
/var/lib/samba/** rwk,

View File

@@ -10,13 +10,16 @@
# ------------------------------------------------------------------
#include <tunables/global>
/usr/sbin/traceroute {
/usr/{sbin/traceroute,bin/traceroute.db} {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/nameservice>
capability net_raw,
network inet raw,
network inet6 raw,
/usr/sbin/traceroute rmix,
@{PROC}/net/route r,

View File

@@ -18,6 +18,7 @@
#include <abstractions/perl>
#include <abstractions/consoles>
#include <abstractions/nameservice>
#include <abstractions/wutmp>
capability chown,
capability dac_override,
@@ -44,8 +45,6 @@
/usr/sbin/useradd rmix,
/usr/sbin/useradd.local rmix,
/var/log/faillog rw,
/var/log/lastlog rw,
/{,var/}run/nscd.pid rw,
/{,var/}run/utmp rw,
/var/spool/mail/* rw,
}

View File

@@ -18,6 +18,7 @@
#include <abstractions/consoles>
#include <abstractions/perl>
#include <abstractions/nameservice>
#include <abstractions/wutmp>
capability chown,
capability dac_override,
@@ -44,9 +45,7 @@
/usr/sbin/userdel-post.local rmix,
/usr/sbin/userdel-pre.local rmix,
/usr/sbin/userdel rmix,
/var/log/lastlog rw,
# XXX
/{,var/}run/nscd.pid r,
/{,var/}run/utmp rw,
/var/spool/mail/* wl,
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2002-2005 Novell/SUSE
*
* 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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <linux/unistd.h>
#include <sys/apparmor.h>
int main(int argc, char *argv[])
{
int rc;
char *profile, *mode;
if (argc < 3 || argc > 4) {
fprintf(stderr, "usage: %s <task> <expected profile> [<expect mode>]\n",
argv[0]);
return 1;
}
if (strcmp(argv[1], "self") == 0){
if (aa_getcon(&profile, &mode) == -1) {
int serrno = errno;
fprintf(stderr,
"FAIL: introspect_confinement %s failed - %s\n",
argv[1], strerror(errno));
exit(serrno);
}
} else {
char *end;
pid_t pid = strtol(argv[1], &end, 10);
if (end == argv[1] || *end != 0) {
int serrno = errno;
fprintf(stderr,
"FAIL: query_confinement - invalid pid: %s\n",
argv[1]);
exit(serrno);
} else if (aa_gettaskcon(pid, &profile, &mode) == -1) {
int serrno = errno;
fprintf(stderr,
"FAIL: query_confinement %s failed - %s\n",
argv[1], strerror(errno));
exit(serrno);
}
}
if (strcmp(profile, argv[2]) != 0) {
fprintf(stderr,
"FAIL: expected confinement \"%s\" != \"%s\"\n", argv[2],
profile);
exit(1);
}
if (argv[3] && (!mode || strcmp(mode, argv[3]) != 0)) {
fprintf(stderr,
"FAIL: expected mode \"%s\" != \"%s\"\n", argv[3],
mode ? mode : "(null)");
exit(1);
}
free(profile);
printf("PASS\n");
return 0;
}

View File

@@ -0,0 +1,67 @@
#! /bin/bash
# Copyright (C) 20011 Canonical
#
# 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.
#=NAME introspect
#=DESCRIPTION Test process confinement introspection
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
ok_ix_perm=rix
badperm=r
ok_ux_perm=ux
ok_px_perm=px
bad_mx_perm=rm
#self unconfined
runchecktest "introspect self unconfined" pass self unconfined
#self unconfined (mode)
runchecktest "introspect self unconfined (mode)" fail self unconfined enforce
#self confined - no access to introspection
genprofile
runchecktest "introspect self confined" fail self "$testexec"
#self confined
genprofile "/proc/*/attr/current":r
runchecktest "introspect self confined" pass self "$testexec"
#self confined (enforce)
runchecktest "introspect self confined" pass self "$testexec" enforce
#### TODO
# query unconfined of unconfined
# query unconfined of confined
# query unconfined of confined (enfore)
# query confined of unconfined - no access permission
# query confined of unconfined - access permission
# query confined of unconfined (mode) - access permission
# query confined of confined same profile - no access permission
# query confined of confined same profile
# query confined of confined same profile (enforce)
# query confined of confined diff profile - no access permission
# query confined of confined diff profile
# query confined of confined diff profile (enforce)

View File

@@ -2860,6 +2860,7 @@ sub add_event_to_tree ($) {
} elsif ($e->{operation} eq "open" ||
$e->{operation} eq "truncate" ||
$e->{operation} eq "mkdir" ||
$e->{operation} eq "mknod" ||
$e->{operation} eq "rename_src" ||
$e->{operation} eq "rename_dest" ||
$e->{operation} =~ m/^(unlink|rmdir|symlink_create|link)$/) {

View File

@@ -36,17 +36,17 @@ MODULES = ${MODDIR}/AppArmor.pm ${MODDIR}/Repository.pm \
MANPAGES = ${TOOLS:=.8} logprof.conf.5
all: ${MANPAGES} ${HTMLMANPAGES}
make -C po all
$(MAKE) -C po all
# need some better way of determining this
DESTDIR=/
BINDIR=${DESTDIR}/usr/sbin
CONFDIR=${DESTDIR}/etc/apparmor
VENDOR_PERL?=/usr/lib/perl5/vendor_perl
VENDOR_PERL=$(shell perl -e 'use Config; print $$Config{"vendorlib"};')
PERLDIR=${DESTDIR}${VENDOR_PERL}/${MODDIR}
po/${NAME}.pot: ${TOOLS}
make -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${MODULES}"
$(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${MODULES}"
.PHONY: install
install: ${MANPAGES} ${HTMLMANPAGES}
@@ -56,9 +56,9 @@ install: ${MANPAGES} ${HTMLMANPAGES}
ln -sf aa-status ${BINDIR}/apparmor_status
install -m 755 ${TOOLS} ${BINDIR}
install -d ${PERLDIR}
install -m 755 ${MODULES} ${PERLDIR}
make -C po install DESTDIR=${DESTDIR} NAME=${NAME}
make install_manpages DESTDIR=${DESTDIR}
install -m 644 ${MODULES} ${PERLDIR}
$(MAKE) -C po install DESTDIR=${DESTDIR} NAME=${NAME}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
.PHONY: clean
@@ -66,7 +66,7 @@ install: ${MANPAGES} ${HTMLMANPAGES}
clean: _clean
rm -f core core.* *.o *.s *.a *~
rm -f Make.rules
make -C po clean
$(MAKE) -C po clean
check:
for i in ${MODULES} ${PERLTOOLS} ; do \

View File

@@ -36,6 +36,8 @@ my %prefs;
my $conf = "/etc/apparmor/notify.conf";
my $user_conf = "$ENV{HOME}/.apparmor/notify.conf";
my $notify_exe = "/usr/bin/notify-send";
my $notify_home = "";
my $notify_display = "";
my $last_exe = "/usr/bin/last";
my $ps_exe = "/bin/ps";
my $url = "https://wiki.ubuntu.com/DebuggingApparmor";
@@ -80,6 +82,7 @@ my $login;
our $orig_euid = $>;
my $opt_d = '';
my $opt_display = '';
my $opt_h = '';
my $opt_l = '';
my $opt_p = '';
@@ -90,6 +93,7 @@ my $opt_u = '';
my $opt_w = 0;
GetOptions(
'debug|d' => \$opt_d,
'display=s' => \$opt_display,
'help|h' => \$opt_h,
'since-last|l' => \$opt_l,
'poll|p' => \$opt_p,
@@ -147,13 +151,38 @@ if (-s $conf) {
if (defined($prefs{use_group})) {
my ($name, $passwd, $gid, $members) = getgrnam($prefs{use_group});
if (not defined($members) or not defined($login) or (not grep { $_ eq $login } split(/ /, $members) and $login ne "root")) {
_error("'$login' must be in '$prefs{use_group}' group. Aborting");
_error("'$login' must be in '$prefs{use_group}' group. Aborting.\nAsk your admin to add you to this group or to change the group in\n$conf if you want to use aa-notify.");
}
}
}
if ($opt_p) {
-x "$notify_exe" or _error("Could not find '$notify_exe'. Please install libnotify-bin. Aborting");
# we need correct values for $HOME and $DISPLAY environment variables,
# otherwise $notify_exe won't be able to connect to DBUS to display the
# message. Do this here to avoid excessive lookups.
$notify_home = (getpwuid $>)[7]; # homedir of the user
if ($opt_display ne '') {
$notify_display = $opt_display;
} elsif (defined($ENV{'DISPLAY'})) {
$notify_display = $ENV{'DISPLAY'};
}
if ($notify_display eq '') {
my $sudo_warn_msg = '';
if (defined($ENV{'SUDO_USER'})) {
$sudo_warn_msg = ' (or reset by sudo)';
}
_warn("Environment variable \$DISPLAY not set$sudo_warn_msg.");
_warn ('Desktop notifications will not work.');
if ($sudo_warn_msg ne '') {
_warn ('Use sudo aa-notify -p --display "$DISPLAY" to set the environment variable.');
} else {
_warn ('Use something like aa-notify -p --display :0 to set the environment variable.')
}
}
} elsif ($opt_l) {
-x "$last_exe" or _error("Could not find '$last_exe'. Aborting");
}
@@ -305,6 +334,9 @@ sub send_message {
# notify-send needs $< to be the unprivileged user
$< = $>;
$notify_home ne "" and $ENV{'HOME'} = $notify_home;
$notify_display ne "" and $ENV{'DISPLAY'} = $notify_display;
# 'system' uses execvp() so no shell metacharacters here.
# $notify_exe is an absolute path so execvp won't search PATH.
system "$notify_exe", "-i", "gtk-dialog-warning", "-u", "critical", "--", "AppArmor Message", "$msg";
@@ -548,6 +580,8 @@ Display AppArmor notifications or messages for DENIED entries.
OPTIONS:
-p, --poll poll AppArmor logs and display notifications
--display $DISPLAY set the DISPLAY environment variable to $DISPLAY
(might be needed if sudo resets $DISPLAY)
-f FILE, --file=FILE search FILE for AppArmor messages
-l, --since-last display stats since last login
-s NUM, --since-days=NUM show stats for last NUM days (can be used alone

View File

@@ -1,2 +1,5 @@
apparmor.vim: apparmor.vim.in Makefile create-apparmor.vim.sh
sh create-apparmor.vim.sh
clean:
rm -f apparmor.vim

View File

@@ -188,6 +188,8 @@ syn match sdEntryPXe /@@FILE@@(r|m|k|Px|Cx|Pix|Cix)+@@TRANSITION@@@@EOL@@/ cont
syn match sdEntryIX /@@FILE@@(r|m|k|ix)+@@EOL@@/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude
" mr - mmap with PROT_EXEC
syn match sdEntryM /@@FILE@@(r|m|k)+@@EOL@@/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude
" special case: deny x is allowed (doesn't need to be ix, px, ux or cx)
syn match sdEntryM /@@DENYFILE@@(r|m|k|x)+@@EOL@@/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude
" if we've got u or i without x, it's an error
" rule is superfluous because of the '/.*/ is an error' rule ;-)

View File

@@ -21,6 +21,7 @@ sdFlagsRegex="($sdFlags)"
# '@@FILE@@' '\v^\s*((owner\s+)|(audit\s+)|(deny\s+))*(\/|\@\{\S*\})\S*\s+' \
replace \
'@@FILE@@' '\v^\s*(audit\s+)?(deny\s+)?(owner\s+)?(\/|\@\{\S*\})\S*\s+' \
'@@DENYFILE@@' '\v^\s*(audit\s+)?deny\s+(owner\s+)?(\/|\@\{\S*\})\S*\s+' \
'@@auditdenyowner@@' '(audit\s+)?(deny\s+)?(owner\s+)?' \
'@@auditdeny@@' '(audit\s+)?(deny\s+)?' \
'@@FILENAME@@' '(\/|\@\{\S*\})\S*' \