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

Compare commits

...

34 Commits

Author SHA1 Message Date
Steve Beattie
3186b09035 Merge from trunk revision 1805:
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.

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

Bug: https://launchpad.net/bugs/775785
2011-08-26 16:03:03 -07:00
Steve Beattie
3dfebc380d Merge from trunk rev 1789: logprof and genprof were creating Px and
Cx execute permissions with the modifiers as lowercase (meaning to
pass on sensitive environment variables to the exec'ed process) even
if the user told them not to when prompted. This patch fixes the issue.

Nominated-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2011-08-17 16:28:15 -07:00
Steve Beattie
e35765bed2 Merge from trunk rev 1749: Actually skip loading profiles that we report
we're skipping.

From: Arkadiusz Miskiewicz <arekm@maven.pl>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-08-04 16:22:10 -07:00
Jamie Strandboge
2b959a80f8 This is bug #815883. The dnsmasq profile needs to be updated for newer
libvirt. Patch is attached. The glob is needed since the lease file's
name is derived from the libvirt network name.
2011-07-27 09:32:35 -05:00
Steve Beattie
6c10463072 Merge from trunk rev 1740: Add
/usr/share/gnome/applications/mimeinfo.cache to gnome abstraction

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-07-14 13:05:32 -07:00
Steve Beattie
112db48794 Merge from trunk rev 1737: allow owner read access to
/var/run/lightdm/authority/[0-9]* in the X abstraction

Nominated-by: Jamie Strandboge <jamie@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-07-14 13:02:31 -07:00
John Johansen
7f5505263a Rename tags to remove use of ~
Rename tags
  apparmor_2.6.0~rc1 to apparmor_2.6.0-rc1
  apparmor_2.6.1~rc1 to apparmor_2.6.1-rc1

this is necessary for importing to the git mirror

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-06-06 03:26:08 -07:00
Steve Beattie
128c40c75f Merge from trunk commit 1721.1.2: This fixes a bug in sprintf use in
a few of the Perl tools, reported by Emanuel Bronshtein in LP: #781961.
																 Signed-off-by: Kees Cook <kees.cook@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-06-02 20:10:46 -07:00
Steve Beattie
106fa146fe Merge from trunk rev 1733: Bug:
https://bugs.launchpad.net/apparmor/+bug/788616

This patch fixes the init scripts helper functions file to
filter out the hat/child process separator as currently used
by the parser, '//' rather than what used to be used, the '^'
symbol. This fixes bugs where profiles that covered regexs (e.g.
'/usr/lib/firefox-4.0.1/firefox{,*[^s][^h]}') and thus were being
improperly filtered away and unloaded when reloading apparmor policy.

Nominated-By: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Kees Cook <kees@ubuntu.com>
2011-06-02 20:05:53 -07:00
Steve Beattie
ab63cb9142 Merge from trunk commit rev 1734:This patch adjusts the tag make
target to use a separate version with '~' replaced by '-'. This is
needed for mirroring to git as git can't handle '~'s embedded in tag
or branch names.

Tested by setting up a separate tag_version target like so:

tag_version:
	echo ${TAG_VERSION}

Nominated-By: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com>
2011-06-02 20:04:02 -07:00
John Johansen
d99e4232e5 Add 2.6.39 compatibility patches 2011-05-19 12:44:05 -07:00
Steve Beattie
3f3971562f Bah, fix up testcases I screwed up. 2011-03-29 02:47:17 -07:00
Steve Beattie
e8c894721b Merge from trunk rev 1702: The parser's lexer supports
variables defined matching the regex '[[:alpha:]][[:alnum:]_]*'
(i.e. a single alpha followed by any number of alphanumerics or
underscores). Unfortunately, the code that expends variables inside a
profile does not match this, it incorrectly matched '([[:alpha:]]|_)+'
(one or more alphas or underscores). This patch corrects the behavior
there as well as synchronizing the expected variable names in the
apparmor.d manpage and apparmor.vim syntax file.

It also adds unit tests and testcases to verify the behavior.

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com>
2011-03-28 11:00:24 -07:00
Steve Beattie
21a6df5b2c adjust version for 2.6.2 development cycle 2011-03-28 10:56:49 -07:00
Steve Beattie
4158b5e095 Fix up the profiles make install target for the tunables/multiarch.d/
change.
2011-03-23 16:07:55 -07:00
Steve Beattie
3706a9c31a Update version for release 2011-03-23 15:01:51 -07:00
Steve Beattie
6bd242fefc Merge from trunk rev 1700: fix typo in multi-arch comment. 2011-03-23 13:45:41 -07:00
Steve Beattie
2ef723e054 Merge from trunk rev 1699: This patch add multiarch support for common
shared library locations, as well as a tunables file and directory
to ease adding additional multiarch paths.

Bug: https://launchpad.net/bugs/736870
2011-03-23 12:27:16 -07:00
Steve Beattie
e268784406 Merge from trunk rev 1698: Update the toplevel README file to discuss
the needed apparmor compatibility patches, mention the profile
consistency check, and remove some variables that no longer need to
be set at build time.
2011-03-18 23:15:43 -07:00
Steve Beattie
be34a7e217 Merge from trunk rev 1697: disable the local include in the extras
firefox profile; the build process does not generate local files
for things in extras, and even if it did, this one is named in a
non-standard fashion (usr.bin.firefox vs. usr.lib.firefox.firefox).
2011-03-18 23:07:19 -07:00
Steve Beattie
d9832491bd Merge from trunk 1696: profiles/Makefile: fix 'check' target to
iterate over the profiles in the extras directory as intended and
fail the make if a parse failure occurs. Also, set the default parser
and logprof to be the intree ones; the system ones can still be used
by setting environment variables.  Finally, have the 'all' target
generate the local files. Also, set the parser base directory to
the apparmor.d directory (rather than as an added include, to avoid
outside contamination from system profiles and includes).

With these changes, make && make check should verify the profile set
is compilable and mostly consistent. (Alas, the current profiles are
not quite consistent).

Nominated-By: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com>
2011-03-18 23:05:38 -07:00
Steve Beattie
2a031e3d71 prep for releasing a 2.6.1 release candidate 2011-03-18 15:56:09 -07:00
Steve Beattie
1ed68f67a9 Merge from trunk rev 1695: This fixes the apparmor apache2 module
to link correctly against the built libapparmor, as well as working
around libtool so that the libapparmor library build directory does
not get added as an rpath to the module.

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

Bug: https://launchpad.net/bugs/737074
2011-03-17 23:35:45 -07:00
Steve Beattie
ffcb113465 Merge from trunk rev 1694: reduce the number of network protocols
filtered out of the parser at build time.

Bug: https://launchpad.net/bugs/732837
2011-03-17 11:18:43 -07:00
Steve Beattie
613a449db6 Merge from trunk rev 1693: Fix from PLD/Arkadiusz Miskiewicz
<arekm@maven.pl> to the initscript helper functions to correct some
log messages and to unload hats first, before their parents.

Nominated-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2011-03-17 10:24:25 -07:00
Steve Beattie
a14d06f8f6 Update repo url after branching 2.6 off of trunk, as well as adjust the
version to indicate that the branch is working towards a 2.6.1 release.
2011-03-10 10:08:24 -08:00
John Johansen
0b383ad769 Add tests to ensure parser is checking its own time stamp wrt profile cache
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2011-03-08 14:52:32 -08:00
John Johansen
55bad42088 apparmor_parser doesn't use its time stamp when determining if cache is stale
If the apparmor_parser is updated (outside of current packaging), when
doing profile loads it will use the existing cache of compiled profiles,
instead of forcing a recompile on profiles.

This can cause apparmor to load bad policy if the parser contains a bug
fix for the previous version of the parser.

This can be worked around in packaging by invalidating the cache and
forcing a profile reload when the parser is upgraded.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-03-08 14:49:03 -08:00
John Johansen
258c39d4a5 Profiles that specify a name and attachment specification fail to attach when the
attachment specification doesn't contain globbing.

eg.
   # profile name and attachment the same - attaches as expected
   profile /usr/lib/chromium-browser/chromium-browser

   # profile without attachment specification - does not attach as expected
  profile chromium-browser

  # profile with name and attachment specification where the attachment specification uses globbing - attaches as expected
  profile chromium-browser /usr/lib/chromium-browser/chromium-broswer*

  # profile with name and attachment specification without globbing - FAILS to attach when it should
  profile chromium-browser /usr/lib/chromium-browser/chromium-browser


This occurs because the xmatch_len is not set correctly for the profiles that specify
a name and an attachment specification, where the attachment specification does not
contain globbing characters.

In this situation the correct length for the xmatch_len is the length of the name, as
the shortest possible unambiguous match is the name length.

This patch does not fix a related bug where an attachment specification of ** will not
match (/**) will.
2011-03-08 10:12:09 -08:00
John Johansen
9819bf5df0 Ensure that the buffer read from /proc/sys/kernel/osrelease is null terminated
Signed-off-by: Jamie Strandboge <jamie@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2011-03-03 15:53:23 -08:00
John Johansen
174c89f772 override AF_MAX for kernels that don't support proper masking
Older versions of the apparmor kernel patches didn't handle receiving
network tables of a larger size than expected.

Allow the parser to detect the kernel version and override the AF_MAX
value for those kernels.

This also replaces the hack using a hardcoded limit of 36 for kernels
missing the features flag.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees.cook@canonical.com>
2011-03-03 15:45:10 -08:00
Steve Beattie
52e14b5c93 merged:
Kees Cook 2011-03-02 update AA url in README
2011-03-02 20:12:27 -08:00
Kees Cook
83ef426514 update AA url in README 2011-03-02 12:19:35 -08:00
Steve Beattie
e14c6c39f1 Make tcp test support current network syntax, reanable tcp test 2011-03-02 05:02:45 -08:00
42 changed files with 1425 additions and 86 deletions

View File

@@ -16,7 +16,7 @@ DIRS=parser \
common \
tests
REPO_URL?=lp:apparmor
REPO_URL?=lp:apparmor/2.6
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"
@@ -24,6 +24,11 @@ REPO_URL?=lp:apparmor
RELEASE_DIR=apparmor-${VERSION}
__SETUP_DIR?=.
# We create a separate version for tags because git can't handle tags
# with embedded ~s in them. No spaces around '-' or they'll get
# embedded in ${VERSION}
TAG_VERSION=$(subst ~,-, ${VERSION})
.PHONY: tarball
tarball: clean
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
@@ -56,4 +61,5 @@ setup:
.PHONY: tag
tag:
bzr tag apparmor_${VERSION}
bzr tag apparmor_${TAG_VERSION}

38
README
View File

@@ -17,7 +17,8 @@ library, available under the LGPL license, which allows change_hat(2)
and change_profile(2) to be used by non-GPL binaries).
For more information, you can read the techdoc.pdf (available after
building the parser) and http://apparmor.wiki.kernel.org.
building the parser) and by visiting the http://apparmor.net/ web
site.
-------------
@@ -29,13 +30,26 @@ AppArmor consists of several different parts:
changehat/ source for using changehat with Apache, PAM and Tomcat
common/ common makefile rules
desktop/ empty
kernel-patches/ patches for various kernel versions
kernel-patches/ compatibility patches for various kernel versions
libraries/ libapparmor source and language bindings
parser/ source for parser/loader and corresponding documentation
profiles/ configuration files, reference profiles and abstractions
tests/ regression and stress testsuites
utils/ high-level utilities for working with AppArmor
--------------------------------------
Important note on AppArmor kernel code
--------------------------------------
While most of the kernel AppArmor code has been accepted in the
upstream Linux kernel, a few important pieces were not included. These
missing pieces unfortunately are important bits for AppArmor userspace
and kernel interaction; therefore we have included compatibility
patches in the kernel-patches/ subdirectory, versioned by upstream
kernel (2.6.37 patches should apply cleanly to 2.6.38 source).
Without these patches applied to the kernel, the AppArmor userspace
will not function correctly.
------------------------------------------
Building and Installing AppArmor Userspace
@@ -48,10 +62,14 @@ the following order.
libapparmor:
$ cd ./libraries/libapparmor
$ sh ./autogen.sh
$ sh ./configure --prefix=/usr --with-perl
$ sh ./configure --prefix=/usr --with-perl # see below
$ make
$ make check
[optional arguments to libapparmor's configure include --with-python
and --with-ruby, to generate python and ruby bindings to libapparmor,
respectively.]
Utilities:
$ cd utils
@@ -69,23 +87,23 @@ $ make install
Apache mod_apparmor:
$ cd changehat/mod_apparmor
$ LIBS="-lapparmor" make
$ make # depends on libapparmor having been built first
$ make install
PAM AppArmor:
$ cd changehat/pam_apparmor
$ LIBS="-lapparmor -lpam" make
$ make # depends on libapparmor having been built first
$ make install
Profiles:
$ cd profiles
$ make
$ make check # depends on the parser having been built first
$ make install
-------------------
AppArmor Testsuites
-------------------
@@ -123,6 +141,14 @@ For details on structure and adding tests, see libraries/libapparmor/README.
$ cd libraries/libapparmor
$ make check
Profile checks
--------------
A basic consistency check to ensure that the parser and aa-logprof parse
successfully the current set of shipped profiles. The system or other
parser and logprof can be passed in by overriding the PARSER and LOGPROF
variables.
$ cd profiles
$ make && make check
Stress Tests
------------

View File

@@ -41,12 +41,15 @@ APXS:=$(shell if [ -x "/usr/sbin/apxs2" ] ; then \
fi )
APXS_INSTALL_DIR=$(shell ${APXS} -q LIBEXECDIR)
DESTDIR=
LIBAPPARMOR_FLAGS="-I../../libraries/libapparmor/src -L../../libraries/libapparmor/src/.libs -lapparmor"
# Need to pass -Wl twice here to get past both apxs2 and libtool, as
# libtool will add the path to the RPATH of the library if passed -L/some/path
LIBAPPARMOR_FLAGS=-I../../libraries/libapparmor/src -Wl,-Wl,-L../../libraries/libapparmor/src/.libs
LDLIBS=-lapparmor
all: $(TARGET) ${MANPAGES} ${HTMLMANPAGES}
%.so: %.c
${APXS} ${LIBAPPARMOR_FLAGS} -c $<
${APXS} ${LIBAPPARMOR_FLAGS} -c $< ${LDLIBS}
mv .libs/$@ .
.PHONY: install

View File

@@ -1 +1 @@
2.6.0
2.6.2~0.devel

View File

@@ -0,0 +1,553 @@
From 0ae314bc92d8b22250f04f85e4bd36ee9ed30890 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 4 Oct 2010 15:03:36 -0700
Subject: [PATCH 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 112a550..d5f3dd7 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -123,6 +123,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 ae3a698..05c018b 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"
@@ -620,6 +621,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",
@@ -651,6 +750,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 e33aaf7..fa3f1b4 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.0.4

View File

@@ -0,0 +1,391 @@
From cdc6b35345e5bcfe92bb2b52ef003f94ceedd40d Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Thu, 22 Jul 2010 02:32:02 -0700
Subject: [PATCH 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.0.4

View File

@@ -0,0 +1,68 @@
From f17b28f64b963c47e76737f7bb7f58ce3a7c5249 Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Tue, 20 Jul 2010 06:57:08 -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 06d764c..cf92856 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.0.4

View File

@@ -196,7 +196,7 @@ parser_version.h: Makefile
# These are the families that it doesn't make sense for apparmor to mediate.
# We use PF_ here since that is what is required in bits/socket.h, but we will
# rewrite these as AF_.
FILTER_FAMILIES=PF_RXRPC PF_MAX PF_UNSPEC PF_UNIX PF_LOCAL PF_NETLINK PF_LLC PF_IUCV PF_TIPC PF_CAN PF_ISDN PF_PHONET
FILTER_FAMILIES=PF_MAX PF_UNSPEC PF_UNIX PF_LOCAL PF_NETLINK
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')

View File

@@ -83,7 +83,7 @@ B<FILEGLOB> = (must start with '/' (after variable expansion), B<?*[]{}^> have s
B<ACCESS> = ( 'r' | 'w' | 'l' | 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx -> ' I<PROGRAMCHILD> | 'Cx -> ' I<PROGRAMCHILD> | 'm' ) [ I<ACCESS> ... ] (not all combinations are allowed; see below.)
B<VARIABLE> = '@{' I<ALPHA> [ I<ALPHANUMERIC> ... ] '}'
B<VARIABLE> = '@{' I<ALPHA> [ ( I<ALPHANUMERIC> | '_' ) ... ] '}'
B<VARIABLE ASSIGNMENT> = I<VARIABLE> ('=' | '+=') (space separated values)

View File

@@ -179,6 +179,7 @@ struct var_string {
#define FLAG_CHANGEHAT_1_4 2
#define FLAG_CHANGEHAT_1_5 3
extern int kernel_supports_network;
extern int net_af_max_override;
extern int flag_changehat_version;
extern int read_implies_exec;
extern dfaflags_t dfaflags;

View File

@@ -90,6 +90,7 @@ char *flags_string = NULL;
int regex_type = AARE_DFA;
int perms_create = 0; /* perms contain create flag */
int kernel_supports_network = 1; /* kernel supports network rules */
int net_af_max_override = -1; /* use kernel to determine af_max */
char *profile_namespace = NULL;
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
FILE *ofile = NULL;
@@ -804,6 +805,7 @@ int process_profile(int option, char *profilename)
char * cachename = NULL;
char * cachetemp = NULL;
char *basename = NULL;
FILE *cmd;
/* per-profile states */
force_complain = opt_force_complain;
@@ -851,6 +853,12 @@ int process_profile(int option, char *profilename)
update_mru_tstamp(yyin);
}
cmd = fopen("/proc/self/exe", "r");
if (cmd) {
update_mru_tstamp(cmd);
fclose(cmd);
}
retval = yyparse();
if (retval != 0)
goto out;

View File

@@ -29,6 +29,10 @@
#include <linux/limits.h>
#include <arpa/inet.h>
#include <linux/capability.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "parser.h"
#include "parser_yacc.h"
@@ -203,6 +207,69 @@ static struct network_tuple network_mappings[] = {
{NULL, 0, NULL, 0, NULL, 0}
};
/* The apparmor kernel patches up until 2.6.38 didn't handle networking
* tables with sizes > AF_MAX correctly. This could happen when the
* parser was built against newer kernel headers and then used to load
* policy on an older kernel. This could happen during upgrades or
* in multi-kernel boot systems.
*
* Try to detect the running kernel version and use that to determine
* AF_MAX
*/
#define PROC_VERSION "/proc/sys/kernel/osrelease"
static size_t kernel_af_max(void) {
char buffer[32];
int major;
int fd, res;
if (!net_af_max_override) {
return 0;
}
/* the override parameter is specifying the max value */
if (net_af_max_override > 0)
return net_af_max_override;
fd = open(PROC_VERSION, O_RDONLY);
if (!fd)
/* fall back to default provided during build */
return 0;
res = read(fd, &buffer, sizeof(buffer));
close(fd);
if (!res)
return 0;
buffer[sizeof(buffer)-1] = '\0';
res = sscanf(buffer, "2.6.%d", &major);
if (res != 1)
return 0;
switch(major) {
case 24:
case 25:
case 26:
return 34;
case 27:
return 35;
case 28:
case 29:
case 30:
return 36;
case 31:
case 32:
case 33:
case 34:
case 35:
return 37;
case 36:
case 37:
return 38;
/* kernels .38 and later should handle this correctly so no
* static mapping needed
*/
default:
return 0;
}
}
/* Yuck. We grab AF_* values to define above from linux/socket.h because
* they are more accurate than sys/socket.h for what the kernel actually
* supports. However, we can't just include linux/socket.h directly,
@@ -213,13 +280,29 @@ static struct network_tuple network_mappings[] = {
* hence the wrapping function.
*/
size_t get_af_max() {
size_t af_max;
/* HACK: declare that version without "create" had a static AF_MAX */
if (!perms_create) return 36;
if (!perms_create && !net_af_max_override)
net_af_max_override = -1;
#if AA_AF_MAX > AF_MAX
return AA_AF_MAX;
af_max = AA_AF_MAX;
#else
return AF_MAX;
af_max = AF_MAX;
#endif
/* HACK: some kernels didn't handle network tables from parsers
* compiled against newer kernel headers as they are larger than
* the running kernel expected. If net_override is defined check
* to see if there is a static max specified for that kernel
*/
if (net_af_max_override) {
size_t max = kernel_af_max();
if (max && max < af_max)
return max;
}
return af_max;
}
struct aa_network_entry *new_network_ent(unsigned int family,
unsigned int type,

View File

@@ -392,6 +392,8 @@ static int process_profile_name_xmatch(struct codomain *cod)
name = local_name(cod->name);
ptype = convert_aaregex_to_pcre(name, 0, tbuf, PATH_MAX + 3,
&cod->xmatch_len);
if (ptype == ePatternBasic)
cod->xmatch_len = strlen(name);
if (ptype == ePatternInvalid) {
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
@@ -414,8 +416,14 @@ static int process_profile_name_xmatch(struct codomain *cod)
struct alt_name *alt;
list_for_each(cod->altnames, alt) {
int len;
convert_aaregex_to_pcre(alt->name, 0, tbuf,
PATH_MAX + 3, &len);
ptype = convert_aaregex_to_pcre(alt->name, 0,
tbuf,
PATH_MAX + 3,
&len);
if (ptype == ePatternBasic)
len = strlen(alt->name);
if (len < cod->xmatch_len)
cod->xmatch_len = len;
if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) {
aare_delete_ruleset(rule);
return FALSE;

View File

@@ -36,8 +36,14 @@ static inline char *get_var_end(char *var)
while (*eptr) {
if (*eptr == '}')
return eptr;
if (!(*eptr == '_' || isalpha(*eptr)))
return NULL; /* invalid char */
/* first character must be alpha */
if (eptr == var) {
if (!isalpha(*eptr))
return NULL; /* invalid char */
} else {
if (!(*eptr == '_' || isalnum(*eptr)))
return NULL; /* invalid char */
}
eptr++;
}
return NULL; /* no terminating '}' */
@@ -317,6 +323,8 @@ int test_split_out_var(void)
struct var_string *ret_struct;
char *prefix = "abcdefg";
char *var = "boogie";
char *var2 = "V4rW1thNum5";
char *var3 = "boogie_board";
char *suffix = "suffixication";
/* simple case */
@@ -394,6 +402,34 @@ int test_split_out_var(void)
MY_TEST(strcmp(ret_struct->suffix, suffix) == 0, "split out var 7 suffix");
free_var_string(ret_struct);
/* numeric char in var, should succeed */
asprintf(&tst_string, "%s@{%s}%s", prefix, var2, suffix);
ret_struct = split_out_var(tst_string);
MY_TEST(ret_struct && strcmp(ret_struct->prefix, prefix) == 0, "split out numeric var prefix");
MY_TEST(ret_struct && strcmp(ret_struct->var, var2) == 0, "split numeric var var");
MY_TEST(ret_struct && strcmp(ret_struct->suffix, suffix) == 0, "split out numeric var suffix");
free_var_string(ret_struct);
/* numeric first char in var, should fail */
asprintf(&tst_string, "%s@{6%s}%s", prefix, var2, suffix);
ret_struct = split_out_var(tst_string);
MY_TEST(ret_struct == NULL, "split out var - numeric first char in var");
free_var_string(ret_struct);
/* underscore char in var, should succeed */
asprintf(&tst_string, "%s@{%s}%s", prefix, var3, suffix);
ret_struct = split_out_var(tst_string);
MY_TEST(ret_struct && strcmp(ret_struct->prefix, prefix) == 0, "split out underscore var prefix");
MY_TEST(ret_struct && strcmp(ret_struct->var, var3) == 0, "split out underscore var");
MY_TEST(ret_struct && strcmp(ret_struct->suffix, suffix) == 0, "split out underscore var suffix");
free_var_string(ret_struct);
/* underscore first char in var, should fail */
asprintf(&tst_string, "%s@{_%s%s}%s", prefix, var2, var3, suffix);
ret_struct = split_out_var(tst_string);
MY_TEST(ret_struct == NULL, "split out var - underscore first char in var");
free_var_string(ret_struct);
return rc;
}
int main(void)

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
@@ -170,7 +161,7 @@ parse_profiles() {
exit 1
;;
esac
aa_log_action_begin "$PARSER_MSG"
aa_log_action_start "$PARSER_MSG"
# run the parser on all of the apparmor profiles
if [ ! -f "$PARSER" ]; then
aa_log_failure_msg "AppArmor parser not found"
@@ -198,6 +189,7 @@ parse_profiles() {
aa_log_skipped_msg "$profile"
logger -t "AppArmor(init)" -p daemon.warn "Skipping profile $profile"
STATUS=2
continue
elif [ "$skip" -ne 0 ]; then
continue
fi
@@ -222,7 +214,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
@@ -235,9 +226,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 +399,16 @@ remove_profiles() {
fi
retval=0
#the list of profiles isn't stable once we start adding or removing
#them so stor to tmp first
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort >"$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}
}
@@ -427,7 +416,7 @@ apparmor_stop() {
aa_log_daemon_msg "Unloading AppArmor profiles "
remove_profiles
rc=$?
log_end_msg $rc
aa_log_end_msg $rc
return $rc
}
@@ -461,17 +450,33 @@ __apparmor_restart() {
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
}

View File

@@ -94,3 +94,13 @@ sleep $timeout
touch $basedir/cache/$profile
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when parser is newer: "
mkdir $basedir/parser
cp ../apparmor_parser $basedir/parser/
$basedir/parser/apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when parser in \$PATH is newer: "
(PATH=$basedir/parser/ /bin/sh -c "apparmor_parser $ARGS -v -r $basedir/$profile") | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"

View File

@@ -0,0 +1,9 @@
#=DESCRIPTION reference variables in rules that also have alternations
#=EXRESULT
@{FOO}=bar baz
@{BAR}=@{FOO} blort
/does/not/exist {
/does/not/{exist,notexist}/blah/@{BAR} r,
}

View File

@@ -0,0 +1,9 @@
#=DESCRIPTION reference variables in rules that also have alternations
#=EXRESULT
@{FOO}=bar baz
@{BAR}=@{FOO} blort
/does/not/exist {
/does/not/@{BAR}/blah/{exist,notexist} r,
}

View File

@@ -0,0 +1,7 @@
#=DESCRIPTION don't accept variables with leading underscores
#=EXRESULT FAIL
@{_FOO} = /foo /bar /baz /biff
/usr/bin/foo {
/@{_FOO}/.foo/* r,
}

View File

@@ -0,0 +1,7 @@
#=DESCRIPTION don't accept variables with leading numeric
#=EXRESULT FAIL
@{4FOO} = /foo /bar /baz /biff
/usr/bin/foo {
/@{4FOO}/.foo/* r,
}

View File

@@ -0,0 +1,9 @@
#=DESCRIPTION simple expansions within file rules with numeric variable
#=EXRESULT PASS
@{FOO1} = /foo /bar /baz /biff
@{B1A1R1} = @{FOO1}
/usr/bin/foo {
/@{FOO1}/.foo/* r,
/foo/@{B1A1R1}/.foo/* r,
}

View File

@@ -0,0 +1,7 @@
#=DESCRIPTION simple expansions within file rules with underscore variable
#=EXRESULT PASS
@{F_OO} = /foo /bar /baz /biff
/usr/bin/foo {
/@{F_OO}/.foo/* r,
}

View File

@@ -20,7 +20,7 @@
# Makefile for LSM-based AppArmor profiles
NAME=apparmor-profiles
ALL:
ALL: local
COMMONDIR=../common/
include common/Make.rules
@@ -38,7 +38,7 @@ PROFILES_SOURCE=./apparmor.d
EXTRAS_SOURCE=./apparmor/profiles/extras/
SUBDIRS_MUST_BE_SKIPPED=${PROFILES_SOURCE}/abstractions ${PROFILES_SOURCE}/apache2.d ${PROFILES_SOURCE}/program-chunks ${PROFILES_SOURCE}/tunables ${PROFILES_SOURCE}/local
PROFILES_TO_COPY=$(filter-out ${SUBDIRS_MUST_BE_SKIPPED}, $(wildcard ${PROFILES_SOURCE}/*))
TUNABLES_TO_COPY=$(filter-out ${PROFILES_SOURCE}/tunables/home.d, $(wildcard ${PROFILES_SOURCE}/tunables/*))
TUNABLES_TO_COPY=$(filter-out ${PROFILES_SOURCE}/tunables/home.d ${PROFILES_SOURCE}/tunables/multiarch.d, $(wildcard ${PROFILES_SOURCE}/tunables/*))
ABSTRACTIONS_TO_COPY=$(filter-out ${PROFILES_SOURCE}/abstractions/ubuntu-browsers.d, $(wildcard ${PROFILES_SOURCE}/abstractions/*))
local:
@@ -64,6 +64,7 @@ install: local
install -m 644 ${PROFILES_SOURCE}/program-chunks/* ${PROFILES_DEST}/program-chunks
install -m 644 ${TUNABLES_TO_COPY} ${PROFILES_DEST}/tunables
install -m 644 ${PROFILES_SOURCE}/tunables/home.d/* ${PROFILES_DEST}/tunables/home.d
install -m 644 ${PROFILES_SOURCE}/tunables/multiarch.d/* ${PROFILES_DEST}/tunables/multiarch.d
install -m 755 -d ${EXTRAS_DEST}
install -m 644 ${EXTRAS_SOURCE}/* ${EXTRAS_DEST}
install -m 644 ${PROFILES_SOURCE}/local/* ${PROFILES_DEST}/local
@@ -81,23 +82,22 @@ endif
ifndef PARSER
# use system parser
PARSER=/sbin/apparmor_parser
PARSER=../parser/apparmor_parser
endif
ifndef LOGPROF
# use system logprof
LOGPROF=/usr/sbin/aa-logprof
# use ../utils logprof
LOGPROF=perl -I../utils/ ../utils/aa-logprof
endif
EXTRAS_PATH=${EXTRAS_SOURCE}/profiles/extras
IGNORE_FILES=${EXTRAS_PATH}/README
CHECK_PROFILES=$(filter-out ${IGNORE_FILES}, $(wildcard ${PROFILES_SOURCE}/*) $(wildcard ${EXTRAS_PATH}/*))
IGNORE_FILES=${EXTRAS_SOURCE}/README
CHECK_PROFILES=$(filter-out ${IGNORE_FILES} ${SUBDIRS_MUST_BE_SKIPPED}, $(wildcard ${PROFILES_SOURCE}/*) $(wildcard ${EXTRAS_SOURCE}/*))
.PHONY: check
check:
@echo "*** Checking profiles from ${PROFILES_SOURCE} and ${EXTRAS_PATH} against apparmor_parser"
@echo "*** Checking profiles from ${PROFILES_SOURCE} and ${EXTRAS_SOURCE} against apparmor_parser"
$(Q)for profile in ${CHECK_PROFILES} ; do \
${PARSER} -S -I ${PWD}/apparmor.d $${profile} > /dev/null ; \
${PARSER} -S -b ${PWD}/apparmor.d $${profile} > /dev/null || exit 1; \
done
@echo "*** Checking profiles from ${PROFILES_SOURCE} against logprof"
$(Q)${LOGPROF} -d ${PROFILES_SOURCE} -f /dev/null
$(Q)${LOGPROF} -d ${PROFILES_SOURCE} -f /dev/null || exit 1

View File

@@ -2,7 +2,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -18,6 +18,7 @@
# .Xauthority files required for X connections, per user
@{HOME}/.Xauthority r,
owner /var/run/gdm/*/database r,
owner /var/run/lightdm/authority/[0-9]* r,
# the unix socket to use to connect to the display
/tmp/.X11-unix/* w,

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009 Canonical Ltd
# Copyright (C) 2009-2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -25,6 +25,9 @@
/lib{,32,64}/security/pam_filter/* mr,
/lib{,32,64}/security/pam_*.so mr,
/lib{,32,64}/security/ r,
/lib/@{multiarch}/security/pam_filter/* mr,
/lib/@{multiarch}/security/pam_*.so mr,
/lib/@{multiarch}/security/ r,
# kerberos
#include <abstractions/kerberosclient>

View File

@@ -2,7 +2,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -36,6 +36,8 @@
/usr/lib{,32,64}/locale/** mr,
/usr/lib{,32,64}/gconv/*.so mr,
/usr/lib{,32,64}/gconv/gconv-modules* mr,
/usr/lib/@{multiarch}/gconv/*.so mr,
/usr/lib/@{multiarch}/gconv/gconv-modules mr,
# used by glibc when binding to ephemeral ports
/etc/bindresvport.blacklist r,
@@ -45,17 +47,26 @@
/etc/ld.so.cache mr,
/lib{,32,64}/ld{,32,64}-*.so mrix,
/lib{,32,64}/**/ld{,32,64}-*.so mrix,
/lib/@{multiarch}/ld{,32,64}-*.so mrix,
/lib/tls/i686/{cmov,nosegneg}/ld-*.so mrix,
/lib/i386-linux-gnu/tls/i686/{cmov,nosegneg}/ld-*.so mrix,
/opt/*-linux-uclibc/lib/ld-uClibc*so* mrix,
# we might as well allow everything to use common libraries
/lib{,32,64}/** r,
/lib{,32,64}/lib*.so* mr,
/lib{,32,64}/**/lib*.so* mr,
/lib/@{multiarch}/** r,
/lib/@{multiarch}/lib*.so* mr,
/lib/@{multiarch}/**/lib*.so* mr,
/usr/lib{,32,64}/** r,
/usr/lib{,32,64}/*.so* mr,
/usr/lib{,32,64}/**/lib*.so* mr,
/usr/lib/@{multiarch}/** r,
/usr/lib/@{multiarch}/lib*.so* mr,
/usr/lib/@{multiarch}/**/lib*.so* mr,
/lib/tls/i686/{cmov,nosegneg}/lib*.so* mr,
/lib/i386-linux-gnu/tls/i686/{cmov,nosegneg}/lib*.so* mr,
# /dev/null is pretty harmless and frequently used
/dev/null rw,

View File

@@ -2,7 +2,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009-2010 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -19,6 +19,7 @@
/etc/gnome/gtkrc* r,
/etc/gtk/* r,
/usr/lib{,32,64}/gtk/** mr,
/usr/lib/@{multiarch}/gtk/** mr,
/usr/share/themes/** r,
# for gnome 1 applications
@@ -31,6 +32,9 @@
/usr/lib{,32,64}/pango/** mr,
/usr/lib{,32,64}/gtk-*/** mr,
/usr/lib{,32,64}/gdk-pixbuf-*/** mr,
/usr/lib/@{multiarch}/pango/** mr,
/usr/lib/@{multiarch}/gtk-*/** mr,
/usr/lib/@{multiarch}/gdk-pixbuf-*/** mr,
# per-user gtk configuration
@{HOME}/.gnome/Gnome r,
@@ -60,6 +64,7 @@
/etc/gnome-vfs-2.0/modules/ r,
/etc/gnome-vfs-2.0/modules/* r,
/usr/lib/gnome-vfs-2.0/modules/*.so mr,
/usr/lib/@{multiarch}/gnome-vfs-2.0/modules/*.so mr,
# gvfs
/usr/share/gvfs/remote-volume-monitors/ r,
@@ -76,3 +81,4 @@
# mime-types
/etc/gnome/defaults.list r,
/usr/share/gnome/applications/mimeinfo.cache r,

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2006 Novell/SUSE
# Copyright (C) 2009-2010 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -38,10 +38,17 @@
/usr/lib*/kde3/plugins/styles/ r,
/usr/lib*/kde3/plugins/styles/* mr,
/usr/lib*/kde3/lib*so* mr,
/usr/lib/@{multiarch}/kde3/plugins/styles/ r,
/usr/lib/@{multiarch}/kde3/plugins/styles/* mr,
/usr/lib/@{multiarch}/kde3/lib*so* mr,
/usr/lib*/qt3/lib*/lib*so* mr,
/usr/lib*/qt3/plugins/** mr,
/usr/lib/@{multiarch}/qt3/lib*/lib*so* mr,
/usr/lib/@{multiarch}/qt3/plugins/** mr,
/usr/lib*/libqt-mt*so* mr,
/usr/lib*/libqui*so* mr,
/usr/lib/@{multiarch}/libqt-mt*so* mr,
/usr/lib/@{multiarch}/libqui*so* mr,
/usr/share/qt3/lib*/libqt-mt*so* mr,
/usr/share/qt3/lib*/libqui*so* mr,
@@ -49,6 +56,11 @@
/usr/lib*/kde4/plugins/*/*.so mr,
/usr/lib*/kde4/plugins/*/ r,
/usr/lib*/kde4/lib*so* mr,
/usr/lib/@{multiarch}/kde4/plugins/*/*.so mr,
/usr/lib/@{multiarch}/kde4/plugins/*/ r,
/usr/lib/@{multiarch}/kde4/lib*so* mr,
/usr/lib*/qt4/lib*/lib*so* mr,
/usr/lib*/qt4/plugins/** mr,
/usr/lib/@{multiarch}/qt4/lib*/lib*so* mr,
/usr/lib/@{multiarch}/qt4/plugins/** mr,
/usr/share/qt4/** r,

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -12,9 +12,13 @@
# files required by kerberos client programs
/usr/lib{,32,64}/krb5/plugins/libkrb5/ r,
/usr/lib{,32,64}/krb5/plugins/libkrb5/* mr,
/usr/lib/@{multiarch}/krb5/plugins/libkrb5/ r,
/usr/lib/@{multiarch}/krb5/plugins/libkrb5/* mr,
/usr/lib{,32,64}/krb5/plugins/preauth/ r,
/usr/lib{,32,64}/krb5/plugins/preauth/* mr,
/usr/lib/@{multiarch}/krb5/plugins/preauth/ r,
/usr/lib/@{multiarch}/krb5/plugins/preauth/* mr,
/etc/krb5.keytab r,
/etc/krb5.conf r,

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2009 Novell/SUSE
# Copyright (C) 2009 Canonical Ltd.
# Copyright (C) 2009-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -50,6 +50,8 @@
# they are available
/lib{,32,64}/libnss_*.so* mr,
/usr/lib{,32,64}/libnss_*.so* mr,
/lib/@{multiarch}/libnss_*.so* mr,
/usr/lib/@{multiarch}/libnss_*.so* mr,
/etc/default/nss r,
# avahi-daemon is used for mdns4 resolution

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2006-2009 Novell/SUSE
# Copyright (C) 2010 Canonical Ltd.
# Copyright (C) 2010-2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -13,5 +13,6 @@
# should be included here
#include <tunables/home>
#include <tunables/multiarch>
#include <tunables/proc>
#include <tunables/alias>

View File

@@ -0,0 +1,17 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2010 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# @{multiarch} is the set of patterns matching multi-arch library
# install prefixes.
@{multiarch}=*-linux-gnu*
# Also, include files in tunables/multiarch.d for site and packaging
# specific adjustments to @{multiarch}.
#include <tunables/multiarch.d>

View File

@@ -0,0 +1,14 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2011 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# The following is a space-separated list of where additional multipath
# prefixes are stored, each should not have a trailing '/'. Directories
# added here are appended to @{multiarch}. See tunables/mutliarch for details. Eg:
#@{multiarch}+=*-freebsd* s390-hurd-zomg

View File

@@ -34,6 +34,9 @@
/var/lib/misc/dnsmasq.leases rw, # Required only for DHCP server usage
# libvirt lease files for dnsmasq
/var/lib/libvirt/dnsmasq/*.leases rw,
# libvirt pid files for dnsmasq
/var/run/libvirt/network/ r,
/var/run/libvirt/network/*.pid rw,

View File

@@ -122,5 +122,7 @@
deny /usr/share/mozilla/ w,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.bin.firefox>
# Local path is disabled, we only enable them for profiles we promote
# out of extras.
## include <local/usr.bin.firefox>
}

View File

@@ -143,6 +143,7 @@ TESTS=access \
setattr \
symlink \
syscall \
tcp \
unix_fd_server \
unlink\
xattrs\

View File

@@ -21,18 +21,37 @@ ip="127.0.0.1"
#badperm1=r
#badperm2=w
# PASS TEST - no netdomain rules
genprofile
runchecktest "TCP" pass $port
# PASS TEST - no apparmor rules
runchecktest "TCP (no apparmor)" pass $port
# PASS TEST - simple
genprofile tcp_accept: tcp_connect:
runchecktest "TCP (accept, connect)" pass $port
# FAIL TEST - no network rules
genprofile
runchecktest "TCP (accept, connect) no network rules" fail $port
# PASS TEST - allow tcp
genprofile network:tcp
runchecktest "TCP (accept, connect) allow tcp" pass $port
# PASS TEST - allow inet
genprofile network:inet
runchecktest "TCP (accept, connect) allow inet" pass $port
# PASS TEST - allow inet stream
genprofile "network:inet stream"
runchecktest "TCP (accept, connect) allow inet stream" pass $port
# PASS TEST - simple / low-numbered port
# you damn well better not be running telnet
genprofile tcp_accept: tcp_connect: cap:net_bind_service
runchecktest "TCP (accept, connect)" pass 23
genprofile network:inet cap:net_bind_service
runchecktest "TCP (accept, connect) low numbered port/bind cap" pass 23
# FAIL TEST - simple / low-numbered port
# will always fail unless process has net_bind_service capability.
# you damn well better not be running telnetd.
genprofile network:inet
runchecktest "TCP (accept, connect) low numbered port/no bind cap" fail 23
exit 0
# PASS TEST - accept via interface
genprofile tcp_accept:via:lo tcp_connect:
@@ -62,12 +81,6 @@ runchecktest "TCP (accept, connect)" pass $port
genprofile tcp_accept:to:127.0.0.0/255.255.192.0::${port} tcp_connect:
runchecktest "TCP (accept, connect)" pass $port
# FAIL TEST - simple / low-numbered port
# will always fail unless process has net_bind_service capability.
# you damn well better not be running telnetd.
genprofile tcp_accept: tcp_connect:
runchecktest "TCP (accept, connect, port 23)" fail 23
# PASS TEST - simple / low-numbered port
# will always fail unless process has net_bind_service capability.
# you damn well better not be running telnetd.

View File

@@ -2257,7 +2257,7 @@ sub handlechildren($$$) {
my $ynans = UI_YesNo($px_mesg, $px_default);
$ans = "CMD_$match";
if ($ynans eq "y") {
$exec_mode &= ~$AA_EXEC_UNSAFE;
$exec_mode &= ~($AA_EXEC_UNSAFE | ($AA_EXEC_UNSAFE << $AA_OTHER_SHIFT));
}
} elsif ($ans eq "CMD_ux") {
$exec_mode = str_to_mode("ux");

View File

@@ -1,6 +1,7 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -116,7 +117,7 @@ for my $profiling (@profiling) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}

View File

@@ -1,6 +1,7 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -106,7 +107,7 @@ for my $profiling (@profiling) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}

View File

@@ -1,6 +1,7 @@
#!/usr/bin/perl
# ----------------------------------------------------------------------
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
# Copyright (c) 2011 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -126,7 +127,7 @@ for my $profiling (@profiling) {
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
exit 1;
} else {
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
exit 1;
}
}

View File

@@ -113,7 +113,7 @@ syn match sdError /^.*$/ contains=sdComment "highlight all non-valid lines as er
" This allows incorrect lines also and should be checked better.
" This also (accidently ;-) includes variable definitions (@{FOO}=/bar)
" TODO: make a separate pattern for variable definitions, then mark sdGlob as contained
syn match sdGlob /\v\?|\*|\{.*,.*\}|[[^\]]\+\]|\@\{[a-zA-Z_]*\}/
syn match sdGlob /\v\?|\*|\{.*,.*\}|[[^\]]\+\]|\@\{[a-zA-Z][a-zA-Z0-9_]*\}/
syn match sdAlias /\v^alias\s+(\/|\@\{\S*\})\S*\s+-\>\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob