mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-03 07:45:50 +00:00
Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b576c1f0d9 | ||
|
11bfb9a737 | ||
|
d8b5dba829 | ||
|
04b428bc32 | ||
|
03b8aee481 | ||
|
0c52d5219a | ||
|
87d4ab1fa5 | ||
|
74ae28012f | ||
|
8cb6fa9dcd | ||
|
6f82124e52 | ||
|
d3989823ca | ||
|
81dac29f52 | ||
|
aeff455da5 | ||
|
01b7969eee | ||
|
8db18e6eb7 | ||
|
5e5d91ba76 | ||
|
1d43cdae44 | ||
|
bd6e9dcb9e | ||
|
955404ca00 | ||
|
5425aadb6d | ||
|
08df8d93ce | ||
|
34c013f036 | ||
|
ab927317e5 | ||
|
c1dacca6c7 | ||
|
aa024ec29c | ||
|
829e75b2e2 | ||
|
b5754812f0 | ||
|
3cb964c5ee | ||
|
05450ac38a | ||
|
d788ceb928 | ||
|
c1a11fb8b6 | ||
|
d7e06b79bb | ||
|
7714b62889 | ||
|
bdb6eb82b6 | ||
|
9142fc482a | ||
|
1c55cf035c | ||
|
05dfb21b32 | ||
|
4f856a0510 | ||
|
0a14cf2849 | ||
|
fcd150c239 | ||
|
b33ff8be7f | ||
|
27257d564b | ||
|
793bc2cc01 | ||
|
4edf5a5a06 | ||
|
0a3c61b75f | ||
|
ddf1e922d0 | ||
|
2cc5b3ae70 | ||
|
e66c163042 | ||
|
d34b3d0d7f | ||
|
e638a8b3f4 | ||
|
5bde5e2fae | ||
|
0fb25b57e3 | ||
|
93a49944d4 | ||
|
2207e0b264 | ||
|
9c3f87c34b | ||
|
94e2e19f02 | ||
|
59e4883b63 | ||
|
9fa6814900 | ||
|
a611a0c207 | ||
|
07431af673 | ||
|
513864845e | ||
|
9c183302b5 | ||
|
283f83aafb | ||
|
aedac26b32 |
1
.bzrignore
Normal file
1
.bzrignore
Normal file
@@ -0,0 +1 @@
|
||||
parser/tst/simple_tests/generated_x/*.sd
|
11
Makefile
11
Makefile
@@ -17,11 +17,12 @@ DIRS=parser \
|
||||
common \
|
||||
tests
|
||||
|
||||
REPO_URL=lp:apparmor/2.5
|
||||
REPO_URL?=lp:apparmor/2.5
|
||||
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/apparmor/apparmor-2.5.1-nominations/"
|
||||
|
||||
RELEASE_DIR=apparmor-${VERSION}
|
||||
SNAPSHOT_DIR=apparmor-${VERSION}-${REPO_VERSION}
|
||||
SNAPSHOT_DIR=apparmor-${VERSION}~${REPO_VERSION}
|
||||
__SETUP_DIR?=.
|
||||
|
||||
.PHONY: tarball
|
||||
tarball: clean
|
||||
@@ -45,7 +46,11 @@ export_dir:
|
||||
echo "$(REPO_URL) $(REPO_VERSION)" > $(__EXPORT_DIR)/.stamp_rev
|
||||
|
||||
clean:
|
||||
-rm -rf ${RELEASE_DIR}
|
||||
-rm -rf ./${RELEASE_DIR} ./apparmor-${VERSION}~*
|
||||
|
||||
setup:
|
||||
cd $(__SETUP_DIR)/libraries/libapparmor && ./autogen.sh
|
||||
|
||||
.PHONY: tag
|
||||
tag:
|
||||
bzr tag apparmor_${VERSION}
|
||||
|
@@ -1,96 +1,126 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
mod_apparmor - fine-grained AppArmor confinement for apache
|
||||
mod_apparmor - fine-grained AppArmor confinement for Apache
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
An AppArmor profile applies to an executable program; if a portion of
|
||||
the program needs different access permissions than other portions,
|
||||
the program can "change hats" via change_hat(2) to a different role,
|
||||
also known as a subprofile. The mod_apparmor apache module uses the
|
||||
change_hat(2) mechanism to offer more fine-grained confinement of dynamic
|
||||
elements within apache such as individual php and perl scripts, while
|
||||
the program can "change hats" via aa_change_hat(2) to a different role,
|
||||
also known as a subprofile. The mod_apparmor Apache module uses the
|
||||
aa_change_hat(2) mechanism to offer more fine-grained confinement of dynamic
|
||||
elements within Apache such as individual php and perl scripts, while
|
||||
still allowing the performance benefits of using mod_php and mod_perl.
|
||||
|
||||
To use mod_apparmor with apache, ensure that mod_apparmor is configured to
|
||||
be loaded into apache, either via yast or manual editing of the httpd(8)
|
||||
configuration files, and restart apache. Make sure that apparmor is also
|
||||
functioning.
|
||||
To use mod_apparmor with Apache, ensure that mod_apparmor is configured to
|
||||
be loaded into Apache, either via a2enmod, yast or manual editing of the
|
||||
apache2(8)/httpd(8) configuration files, and restart Apache. Make sure that
|
||||
apparmor is also functioning.
|
||||
|
||||
Once mod_apparmor is loaded within apache, all requests to apache will
|
||||
Once mod_apparmor is loaded within Apache, all requests to Apache will
|
||||
cause mod_apparmor to attempt to change into a hat named by the URI
|
||||
(e.g. /app/some.cgi). If no such hat is found, it will fall back to
|
||||
attempting to use the hat DEFAULT_URI; if that also does not exist,
|
||||
it will fall back to using the global apache profile. Most static web
|
||||
it will fall back to using the global Apache profile. Most static web
|
||||
pages can simply make use of the DEFAULT_URI hat.
|
||||
|
||||
However, defining hats for every URI/URL would become tedious, so there
|
||||
are a couple of configuration options that mod_apparmor supports:
|
||||
Additionally, before any requests come in to Apache, mod_apparmor
|
||||
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
|
||||
mod_apparmor will attempt to use this hat while Apache is doing the
|
||||
initial parsing of a given http request, before its given to a specific
|
||||
handler (like mod_php) for processing.
|
||||
|
||||
Because defining hats for every URI/URL often becomes tedious, mod_apparmor
|
||||
provides the AAHatName and AADefaultHatName Apache configuration options.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<AAHatName>
|
||||
|
||||
AAHatName allows you to specify a hat to be used for a given apache
|
||||
directory or location directive (see the apache documenation for more
|
||||
AAHatName allows you to specify a hat to be used for a given Apache
|
||||
E<lt>DirectoryE<gt>, E<lt>DirectoryMatch>, E<lt>LocationE<gt> or
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
|
||||
details). Note that mod_apparmor behavior can become confused if
|
||||
directory and location directives are intermingled; it's preferred to
|
||||
stick to one type of directive. If the hat specified by AAHatName does
|
||||
not exist in the apache profile, then it falls back to the behavior
|
||||
above.
|
||||
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
|
||||
and it is recommended to use one type of directive. If the hat specified by
|
||||
AAHatName does not exist in the Apache profile, then it falls back to the
|
||||
behavior described above.
|
||||
|
||||
=item B<AADefaultHatName>
|
||||
|
||||
AADefaultHatName allows you to specify a default hat to be used for
|
||||
vhosts and other apache server directives, so that you can have
|
||||
different defaults for different virtual hosts. This can be overridden
|
||||
by an AAHatName directive. If the AADefaultHatName hat does not exist,
|
||||
it falls back to the behavior described above.
|
||||
virtual hosts and other Apache server directives, so that you can have
|
||||
different defaults for different virtual hosts. This can be overridden by
|
||||
the AAHatName directive and is checked for only if there isn't a matching
|
||||
AAHatName or hat named by the URI. If the AADefaultHatName hat does not
|
||||
exist, it falls back to the DEFAULT_URI hat if it exists (as described
|
||||
above).
|
||||
|
||||
=back
|
||||
|
||||
Additionally, before any requests come in to apache, mod_apparmor
|
||||
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
|
||||
mod_apparmor will attempt to use this hat while apache is doing the
|
||||
initial parsing of a given http request, before its given to a specific
|
||||
handler (like mod_php) for processing.
|
||||
=head1 URI REQUEST SUMMARY
|
||||
|
||||
When profiling with mod_apparmor, it is helpful to keep the following order
|
||||
of operations in mind:
|
||||
|
||||
On each URI request, mod_apparmor will first aa_change_hat(2) into
|
||||
^HANDLING_UNTRUSTED_INPUT, if it exists.
|
||||
|
||||
Then, after performing the initial parsing of the request, mod_apparmor
|
||||
will:
|
||||
|
||||
=over 2
|
||||
|
||||
1. try to aa_change_hat(2) into a matching AAHatName hat if it exists and
|
||||
applies, otherwise it will
|
||||
|
||||
2. try to aa_change_hat(2) into the URI itself, otherwise it will
|
||||
|
||||
3. try to aa_change_hat(2) into an AADefaultHatName hat if it has been defined
|
||||
for the server/vhost, otherwise it will
|
||||
|
||||
4. try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
|
||||
will
|
||||
|
||||
5. fall back to the global Apache policy
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
mod_apparmor() currently only supports apache2, and has only been tested
|
||||
with the prefork MPM configuration -- threaded configurations of apache
|
||||
with the prefork MPM configuration -- threaded configurations of Apache
|
||||
may not work correctly.
|
||||
|
||||
There are likely other bugs lurking about; if you find any, please report
|
||||
them to bugzilla at L<http://bugzilla.novell.com>.
|
||||
them at L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -25,7 +25,7 @@
|
||||
# directories
|
||||
|
||||
DISTRIBUTION=AppArmor
|
||||
VERSION=2.5.1
|
||||
VERSION=2.5.2
|
||||
|
||||
# OVERRIDABLE variables
|
||||
# Set these variables before including Make.rules to change its behavior
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <libgnome/gnome-program.h>
|
||||
#include "preferences_dialog.h"
|
||||
#include "reject_list.h"
|
||||
#include "apparmor-applet.h"
|
||||
|
@@ -0,0 +1,538 @@
|
||||
From 729ccc6e522199ace96d9344b941e4530b7a0e64 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 | 6 +-
|
||||
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, 382 insertions(+), 2 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 f204869..a9a1db0 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -4,17 +4,21 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
+
|
||||
quiet_cmd_make-rlim = GEN $@
|
||||
cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
|
||||
|
||||
$(obj)/capability.o : $(obj)/capability_names.h
|
||||
+$(obj)/net.o : $(obj)/af_names.h
|
||||
$(obj)/resource.o : $(obj)/rlim_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
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 cf1de44..324ab91 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -31,6 +31,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"
|
||||
@@ -619,6 +620,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",
|
||||
|
||||
@@ -650,6 +749,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 52cc865..3b5da44 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 eb3700e..c2b6225 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.1
|
||||
|
@@ -0,0 +1,392 @@
|
||||
From 287eaf29269e7692c0fe510fe3838f286a2984e1 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 | 2 +
|
||||
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
|
||||
security/apparmor/apparmorfs.c | 18 ++-
|
||||
security/apparmor/include/apparmorfs.h | 6 +
|
||||
5 files changed, 320 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 a9a1db0..e5e8968 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -6,6 +6,8 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
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 7320331..0e27449 100644
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -182,7 +182,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;
|
||||
}
|
||||
@@ -213,7 +217,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.1
|
||||
|
@@ -0,0 +1,68 @@
|
||||
From 484d99eaaa89c3bfd707128b4c508d4a70a18eea 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 5cb4dc1..0248bb3 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.1
|
||||
|
@@ -0,0 +1,538 @@
|
||||
From 6ab924a333c81d552eb92900509113bdf2fccb2e 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 | 6 +-
|
||||
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, 382 insertions(+), 2 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 f204869..a9a1db0 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -4,17 +4,21 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
+
|
||||
quiet_cmd_make-rlim = GEN $@
|
||||
cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
|
||||
|
||||
$(obj)/capability.o : $(obj)/capability_names.h
|
||||
+$(obj)/net.o : $(obj)/af_names.h
|
||||
$(obj)/resource.o : $(obj)/rlim_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
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 cf1de44..324ab91 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -31,6 +31,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"
|
||||
@@ -619,6 +620,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",
|
||||
|
||||
@@ -650,6 +749,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 52cc865..3b5da44 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 eb3700e..c2b6225 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.1
|
||||
|
@@ -0,0 +1,392 @@
|
||||
From 5f034900aa447abea213c434d6d262d28fd168e7 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 | 2 +
|
||||
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
|
||||
security/apparmor/apparmorfs.c | 18 ++-
|
||||
security/apparmor/include/apparmorfs.h | 6 +
|
||||
5 files changed, 320 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 a9a1db0..e5e8968 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -6,6 +6,8 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
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 7320331..0e27449 100644
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -182,7 +182,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;
|
||||
}
|
||||
@@ -213,7 +217,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.1
|
||||
|
@@ -0,0 +1,68 @@
|
||||
From 5d5b58edb77c2e2746395a3818239c6b7d17315d 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 5cb4dc1..0248bb3 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.1
|
||||
|
@@ -0,0 +1,538 @@
|
||||
From 333f21a5004bc386f217801549514b689f3430cd 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 | 6 +-
|
||||
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, 382 insertions(+), 2 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 f204869..a9a1db0 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -4,17 +4,21 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
|
||||
+
|
||||
quiet_cmd_make-rlim = GEN $@
|
||||
cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
|
||||
|
||||
$(obj)/capability.o : $(obj)/capability_names.h
|
||||
+$(obj)/net.o : $(obj)/af_names.h
|
||||
$(obj)/resource.o : $(obj)/rlim_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
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 b7106f1..fa778a7 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -31,6 +31,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"
|
||||
@@ -619,6 +620,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",
|
||||
|
||||
@@ -650,6 +749,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 eb3700e..c2b6225 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.1
|
||||
|
@@ -0,0 +1,392 @@
|
||||
From a89f0bb2dfd82445e58f5f6bfceb40ab8bee543f 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 | 2 +
|
||||
security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
|
||||
security/apparmor/apparmorfs.c | 18 ++-
|
||||
security/apparmor/include/apparmorfs.h | 6 +
|
||||
5 files changed, 320 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 a9a1db0..e5e8968 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -6,6 +6,8 @@ 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 af_names.h
|
||||
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
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.1
|
||||
|
@@ -0,0 +1,68 @@
|
||||
From dd6eaf697f4deb510ecbfba12ac0d5221e4c6829 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 5cb4dc1..0248bb3 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.1
|
||||
|
@@ -1,6 +1,9 @@
|
||||
Rather than keep around a set of kernel patches that continually go
|
||||
stale, this release of AppArmor contains the user space elements only.
|
||||
Links to current patch sets will be posted to the AppArmor wiki at:
|
||||
While we've tried to avoid keeping around a set of kernel patches
|
||||
that continually go stale, this release of AppArmor does contain the
|
||||
AppArmor backwards compatibility patches to maintain full compatibility
|
||||
with prior versions of the kernel portion of AppArmor.
|
||||
|
||||
Links to current patch sets will also be posted to the AppArmor wiki at:
|
||||
|
||||
https://apparmor.wiki.kernel.org/
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
Steve Beattie <sbeattie@suse.de>
|
||||
Steve Beattie <sbeattie@ubuntu.com>
|
||||
Matt Barringer <mbarringer@suse.de>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
POD2MAN = pod2man
|
||||
|
||||
man_MANS = aa_change_hat.2
|
||||
man_MANS = aa_change_hat.2 aa_change_profile.2
|
||||
|
||||
PODS = $(subst .2,.pod,$(man_MANS))
|
||||
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -220,14 +219,15 @@ The output when run:
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them to bugzilla at
|
||||
L<http://bugzilla.novell.com>. Note that aa_change_hat(2) provides no
|
||||
memory barriers between different areas of a program; if address space
|
||||
separation is required, then separate processes should be used.
|
||||
None known. If you find any, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>. Note that
|
||||
aa_change_hat(2) provides no memory barriers between different areas of a
|
||||
program; if address space separation is required, then separate processes
|
||||
should be used.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
198
libraries/libapparmor/doc/aa_change_profile.pod
Normal file
198
libraries/libapparmor/doc/aa_change_profile.pod
Normal file
@@ -0,0 +1,198 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. Canonical Ltd.
|
||||
# essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa_change_profile - change to another profile within an AppArmor profile
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<int aa_change_profile(const char *profile);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
An AppArmor profile applies to an executable program; if a portion of
|
||||
the program needs different access permissions than other portions,
|
||||
the program can "change profile" to a different profile. To change into a
|
||||
new profile, it can use the aa_change_profile() function to do so. It passes
|
||||
in a pointer to the I<profile> to transition to. Transitioning to another
|
||||
profile via aa_change_profile() is permanent and the process is not
|
||||
permitted to transition back to the original profile. Confined programs
|
||||
wanting to use aa_change_profile() need to have rules permitting changing
|
||||
to the named profile. See apparmor.d(8) for details.
|
||||
|
||||
If a program wants to return out of the current profile to the
|
||||
original profile, it should use aa_change_hat(2) instead.
|
||||
|
||||
Open file descriptors are not remediated after a call to aa_change_profile()
|
||||
so the calling program must close(2) open file descriptors to ensure they
|
||||
are not available after calling aa_change_profile(). As aa_change_profile()
|
||||
is typically used just before execve(2), you may want to use open(2) or
|
||||
fcntl(2) with close-on-exec.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
On success zero is returned. On error, -1 is returned, and
|
||||
errno(3) is set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<EINVAL>
|
||||
|
||||
The apparmor kernel module is not loaded or the communication via the
|
||||
F</proc/*/attr/current> file did not conform to protocol.
|
||||
|
||||
=item B<ENOMEM>
|
||||
|
||||
Insufficient kernel memory was available.
|
||||
|
||||
=item B<EPERM>
|
||||
|
||||
The calling application is not confined by apparmor.
|
||||
|
||||
=item B<ECHILD>
|
||||
|
||||
The application's profile has no hats defined for it.
|
||||
|
||||
=item B<EACCES>
|
||||
|
||||
The specified I<profile> does not exist in this profile or the
|
||||
process tried to change another process's domain.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLE
|
||||
|
||||
The following example shows a simple, if contrived, use of
|
||||
aa_change_profile(); a typical use of aa_change_profile() will
|
||||
aa_change_profile() just before an execve(2) so that the new
|
||||
child process is permanently confined.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/apparmor.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int fd;
|
||||
char buf[10];
|
||||
char *execve_args[4];
|
||||
|
||||
printf("Before aa_change_profile():\n");
|
||||
if ((fd=open("/etc/passwd", O_RDONLY)) < 0) {
|
||||
perror("Failure opening /etc/passwd");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Confirm for ourselves that we can really read /etc/passwd */
|
||||
memset(&buf, 0, 10);
|
||||
if (read(fd, &buf, 10) == -1) {
|
||||
perror("Failure reading /etc/passwd");
|
||||
return 1;
|
||||
}
|
||||
buf[9] = '\0';
|
||||
printf("/etc/passwd: %s\n", buf);
|
||||
close(fd);
|
||||
|
||||
printf("After aa_change_profile():\n");
|
||||
|
||||
/* change profile to the "i_cant_be_trusted_anymore" profile, which
|
||||
* should not have read access to /etc/passwd. */
|
||||
if (aa_change_profile("i_cant_be_trusted_anymore") < 0) {
|
||||
perror("Failure changing profile -- aborting");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
/* confirm that we cannot read /etc/passwd */
|
||||
execve_args[0] = "/usr/bin/head";
|
||||
execve_args[1] = "-1";
|
||||
execve_args[2] = "/etc/passwd";
|
||||
execve_args[3] = NULL;
|
||||
execve("/usr/bin/head", execve_args, NULL);
|
||||
perror("execve");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
This code example requires a profile similar to the following to be loaded
|
||||
with apparmor_parser(8):
|
||||
|
||||
profile i_cant_be_trusted_anymore {
|
||||
/etc/ld.so.cache mr,
|
||||
/lib/ld-*.so* mrix,
|
||||
/lib/libc*.so* mr,
|
||||
|
||||
/usr/bin/head ix,
|
||||
}
|
||||
|
||||
The output when run:
|
||||
|
||||
$ /tmp/change_p
|
||||
Before aa_change_profile():
|
||||
/etc/passwd: root:x:0:
|
||||
After aa_change_profile():
|
||||
/usr/bin/head: cannot open `/etc/passwd' for reading: Permission denied
|
||||
$
|
||||
|
||||
If /tmp/change_p is to be confined as well, then the following profile can be
|
||||
used (in addition to the one for 'i_cant_be_trusted_anymore', above):
|
||||
# Confine change_p to be able to read /etc/passwd and aa_change_profile()
|
||||
# to the 'i_cant_be_trusted_anymore' profile.
|
||||
/tmp/change_p {
|
||||
/etc/ld.so.cache mr,
|
||||
/lib/ld-*.so* mrix,
|
||||
/lib/libc*.so* mr,
|
||||
|
||||
/etc/passwd r,
|
||||
|
||||
# Needed for aa_change_profile()
|
||||
/usr/lib/libapparmor*.so* mr,
|
||||
/proc/[0-9]*/attr/current w,
|
||||
change_profile -> i_cant_be_trusted_anymore,
|
||||
}
|
||||
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>. Note that using
|
||||
aa_change_profile(2) without execve(2) provides no memory barriers between
|
||||
different areas of a program; if address space separation is required, then
|
||||
separate processes should be used.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
* Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General
|
||||
* Public License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
@@ -1,20 +1,29 @@
|
||||
/* $Id$
|
||||
|
||||
Copyright (c) 2003-2007 Novell, Inc. (All rights reserved)
|
||||
|
||||
The libapparmor library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_APPARMOR_H_
|
||||
#define _SYS_APPARMOR_H 1
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Prototype for change_hat as defined by the AppArmor project
|
||||
<http://forge.novell.com/modules/xfmod/project/?apparmor>
|
||||
Please see the change_hat(2) manpage for information. */
|
||||
/* Prototypes for self directed domain transitions
|
||||
* see <http://apparmor.net>
|
||||
* Please see the change_hat(2) manpage for information.
|
||||
*/
|
||||
|
||||
#define change_hat(X, Y) aa_change_hat((X), (Y))
|
||||
extern int (change_hat)(const char *subprofile, unsigned int magic_token);
|
||||
@@ -22,8 +31,8 @@ extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile);
|
||||
extern int aa_change_onexec(const char *profile);
|
||||
|
||||
extern int aa_change_hatv(const char *subprofiles[], unsigned int token);
|
||||
extern int (aa_change_hat_vargs)(unsigned int token, int count, ...);
|
||||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||
extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
|
||||
|
||||
#define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
|
||||
#define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
|
@@ -1,12 +1,19 @@
|
||||
/* $Id$
|
||||
|
||||
Copyright (c) 2003-2007 Novell, Inc. (All rights reserved)
|
||||
|
||||
The libapparmor library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
* Copyright (c) 2010, Canonical, Ltd.
|
||||
* Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
* 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.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General
|
||||
* Public License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
* Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General
|
||||
* Public License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@@ -1,11 +1,18 @@
|
||||
/* $Id$
|
||||
|
||||
Copyright (c) 2006 Novell, Inc. (All rights reserved)
|
||||
The libimmunix library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2006 Novell, Inc. (All rights reserved)
|
||||
*
|
||||
* The libimmunix library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General
|
||||
* Public License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
* Copyright (c) 2010, Canonical, Ltd.
|
||||
* Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
* 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.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
%option noyywrap
|
||||
|
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General
|
||||
* Public License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@@ -2,13 +2,20 @@
|
||||
|
||||
%{
|
||||
#include "aalogparse.h"
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile, unsigned long magic_token);
|
||||
#include "apparmor.h"
|
||||
|
||||
%}
|
||||
|
||||
%include "typemaps.i"
|
||||
%include "aalogparse.h"
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile, unsigned long magic_token);
|
||||
|
||||
/* swig doesn't like the macro magic we do in apparmor.h so the fn prototypes
|
||||
* are manually inserted here
|
||||
*/
|
||||
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile);
|
||||
extern int aa_change_onexec(const char *profile);
|
||||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||
extern int aa_change_hat_vargs(unsigned long token, int count, ...);
|
||||
|
||||
|
@@ -10,6 +10,7 @@ MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.pm
|
||||
|
||||
Makefile.perl: Makefile.PL
|
||||
$(PERL) $< PREFIX=$(prefix) MAKEFILE=$@
|
||||
sed -ie 's/^LD_RUN_PATH.*//g' Makefile.perl
|
||||
|
||||
LibAppArmor.so: libapparmor_wrap.c Makefile.perl
|
||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||
|
@@ -4,14 +4,14 @@ import string
|
||||
setup(name = 'LibAppArmor',
|
||||
version = '@VERSION@',
|
||||
author = 'AppArmor Dev Team',
|
||||
author_email = 'Apparmor-dev@forge.novell.com',
|
||||
url = 'http://developer.novell.com/wiki/index.php/Apparmor',
|
||||
author_email = 'apparmor@lists.ubuntu.com',
|
||||
url = 'http://apparmor.wiki.kernel.org',
|
||||
description = 'AppArmor python bindings',
|
||||
download_url = 'http://developer.novell.com/wiki/index.php/Special:Downloads/apparmor',
|
||||
package_dir = {'libapparmor1': '@srcdir@'},
|
||||
packages = [ 'libapparmor1' ],
|
||||
ext_package = 'libapparmor1',
|
||||
ext_modules = [Extension('_libapparmor', ['libapparmor_wrap.c'],
|
||||
download_url = 'https://launchpad.net/apparmor/+download',
|
||||
package_dir = {'LibAppArmor': '@srcdir@'},
|
||||
packages = [ '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'),
|
||||
|
@@ -12,7 +12,7 @@ noinst_PROGRAMS = test_multi.multi
|
||||
test_multi_multi_SOURCES = test_multi.c
|
||||
test_multi_multi_CFLAGS = $(CFLAGS) -Wall
|
||||
test_multi_multi_LDFLAGS = $(LDFLAGS)
|
||||
test_multi_multi_LDADD = ../src/.libs/libapparmor.a
|
||||
test_multi_multi_LDADD = -L../src/.libs -lapparmor
|
||||
|
||||
clean-local:
|
||||
rm -f tmp.err.* tmp.out.* site.exp site.bak
|
||||
|
@@ -45,11 +45,14 @@ WARNINGS += $(shell for warning in ${EXTRA_WARNINGS} ; do \
|
||||
echo "$${warning}"; \
|
||||
fi ; \
|
||||
done)
|
||||
CFLAGS = -O2 -pipe
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -g -O2 -pipe
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS = -g
|
||||
endif
|
||||
endif #CFLAGS
|
||||
|
||||
EXTRA_CFLAGS = ${CFLAGS} ${WARNINGS} -D_GNU_SOURCE
|
||||
|
||||
#LEXLIB := -lfl
|
||||
@@ -125,9 +128,20 @@ techdoc/index.html: techdoc.pdf
|
||||
techdoc.txt: techdoc/index.html
|
||||
w3m -dump $< > $@
|
||||
|
||||
all: $(TOOLS) $(MANPAGES) ${HTMLMANPAGES} techdoc.pdf
|
||||
# targets arranged this way so that people who don't want full docs can
|
||||
# pick specific targets they want.
|
||||
main: $(TOOLS)
|
||||
$(Q)make -C po all
|
||||
$(Q)make -s tests
|
||||
|
||||
manpages: $(MANPAGES)
|
||||
|
||||
htmlmanpages: $(HTMLMANPAGES)
|
||||
|
||||
pdf: techdoc.pdf
|
||||
|
||||
docs: manpages htmlmanpages pdf
|
||||
|
||||
all: main docs tests
|
||||
|
||||
apparmor_parser: $(OBJECTS) $(PCREOBJECTS) $(AAREOBJECTS)
|
||||
rm -f ./libstdc++.a
|
||||
@@ -191,7 +205,7 @@ __FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
|
||||
af_names.h: /usr/include/bits/socket.h
|
||||
LC_ALL=C sed -n -e '/$(__FILTER)/d' -e "s/^\#define[ \\t]\\+PF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/#ifndef AF_\\1\\n# define AF_\\1 \\2\\n#endif\\nAA_GEN_NET_ENT(\"\\L\\1\", \\UAF_\\1)\\n/p" $< > $@
|
||||
LC_ALL=C sed -n -e "s/^\#define[ \\t]\\+PF_MAX[ \\t]\\+\\([0-9]\\+\\)[ \\t]\\+.*/#define AA_AF_MAX \\1\n/p" $< >> $@
|
||||
cat $@
|
||||
# cat $@
|
||||
|
||||
cap_names.h: /usr/include/linux/capability.h
|
||||
LC_ALL=C sed -n -e "/CAP_EMPTY_SET/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9xa-f]\\+\\)\\(.*\\)\$$/\{\"\\L\\1\", \\UCAP_\\1\},/p" $< > $@
|
||||
@@ -224,7 +238,7 @@ check: tests
|
||||
.SILENT: $(AAREOBJECTS)
|
||||
.PHONY: $(AAREOBJECTS)
|
||||
$(AAREOBJECTS):
|
||||
make -C $(AAREDIR)
|
||||
make -C $(AAREDIR) CFLAGS="$(CFLAGS)"
|
||||
|
||||
.SILENT: $(PCREOBJECTS)
|
||||
.PHONY: $(PCREOBJECTS)
|
||||
@@ -295,6 +309,7 @@ clean: _clean
|
||||
-rm -rf techdoc.{aux,log,pdf,toc,txt} techdoc/
|
||||
make -s -C $(PCREDIR) clean
|
||||
make -s -C $(AAREDIR) clean
|
||||
make -s -C tst clean
|
||||
make -s -C po clean
|
||||
|
||||
.SILENT: dist_clean
|
||||
|
@@ -55,9 +55,9 @@ B<COMMENT> = '#' I<TEXT>
|
||||
|
||||
B<TEXT> = any characters
|
||||
|
||||
B<PROFILE> = [ I<COMMENT> ... ] [ I<VARIABLE ASSIGNMENT> ... ] ( '"' I<PROGRAM> '"' | I<PROGRAM> ) [ 'flags=(complain)' ]'{' [ ( I<RESOURCE RULE> | I<COMMENT> | I<INCLUDE> | I<SUBPROFILE> | 'capability ' I<CAPABILITY> | I<NETWORK RULE> ) ... ] '}'
|
||||
B<PROFILE> = [ I<COMMENT> ... ] [ I<VARIABLE ASSIGNMENT> ... ] ( '"' I<PROGRAM> '"' | I<PROGRAM> ) [ 'flags=(complain)' ]'{' [ ( I<RESOURCE RULE> | I<COMMENT> | I<INCLUDE> | I<SUBPROFILE> | 'capability ' I<CAPABILITY> | I<NETWORK RULE> | 'change_profile -> ' I<PROGRAMCHILD> ) ... ] '}'
|
||||
|
||||
B<SUBPROFILE> = [ I<COMMENT> ... ] I<PROGRAMHAT> '{' [ ( I<FILE RULE> | I<COMMENT> | I<INCLUDE> ) ... ] '}'
|
||||
B<SUBPROFILE> = [ I<COMMENT> ... ] ( I<PROGRAMHAT> | 'profile ' I<PROGRAMCHILD> ) '{' [ ( I<FILE RULE> | I<COMMENT> | I<INCLUDE> ) ... ] '}'
|
||||
|
||||
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
|
||||
capabilities(7))
|
||||
@@ -72,13 +72,17 @@ B<PROTOCOL> = ( 'tcp' | 'udp' | 'icmp' )
|
||||
|
||||
B<PROGRAM> = (non-whitespace characters except for '^', must start with '/'. Embedded spaces or tabs must be quoted.)
|
||||
|
||||
B<PROGRAMHAT> = '^' (non-whitespace characters; see change_hat(2) for a description of how this "hat" is used.)
|
||||
B<PROGRAMHAT> = '^' (non-whitespace characters; see aa_change_hat(2) for a description of how this "hat" is used.)
|
||||
|
||||
B<FILE RULE> = ( '"' I<FILEGLOB> '"' | I<FILEGLOB> ) I<ACCESS> ','
|
||||
B<PROGRAMCHILD> = I<SUBPROFILE> name
|
||||
|
||||
B<FILE RULE> = I<RULE QUALIFIER> ( '"' I<FILEGLOB> '"' | I<FILEGLOB> ) I<ACCESS> ','
|
||||
|
||||
B<RULE QUALIFIER> = [ 'audit' ] [ 'deny' ] [ 'owner' ]
|
||||
|
||||
B<FILEGLOB> = (must start with '/' (after variable expansion), B<?*[]{}^> have special meanings; see below. May include I<VARIABLE>. Rules with embedded spaces or tabs must be quoted. Rules must end with '/' to apply to directories.)
|
||||
|
||||
B<ACCESS> = ( 'r' | 'w' | 'l' | 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'm' ) [ I<ACCESS> ... ] (not all combinations are allowed; see below.)
|
||||
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> ... ] '}'
|
||||
|
||||
@@ -92,14 +96,19 @@ B<ALPHANUMERIC> = ('1', '2', '3', ... '9', 'a', 'b', 'c', ... 'z', 'A', 'B', ...
|
||||
|
||||
=back
|
||||
|
||||
All resources and programs need a full path. There may be any number
|
||||
of subprofiles ("hats") in a profile, limited only by kernel memory.
|
||||
Subprofile names are limited to 974 characters.
|
||||
Not all profiles benefit from subprofiles
|
||||
--- applications must either be written or modified to use change_hat(2)
|
||||
to take advantage of subprofiles. Several change_hat(2)-aware
|
||||
All resources and programs need a full path. There may be any number of
|
||||
subprofiles (aka child profiles) in a profile, limited only by kernel
|
||||
memory. Subprofile names are limited to 974 characters. Child profiles can
|
||||
be used to confine an application in a special way, or when you want the
|
||||
child to be unconfined on the system, but confined when called from the
|
||||
parent. Hats are a special child profile that can be used with the
|
||||
aa_change_hat(2) API call. Applications written or modified to use
|
||||
aa_change_hat(2) can take advantage of subprofiles to run under different
|
||||
confinements, dependent on program logic. Several aa_change_hat(2)-aware
|
||||
applications exist, including an Apache module, mod_apparmor(5); a PAM
|
||||
module, pam_apparmor; and a Tomcat valve, tomcat_apparmor.
|
||||
module, pam_apparmor; and a Tomcat valve, tomcat_apparmor. Applications
|
||||
written or modified to use change_profile(2) transition permanently to the
|
||||
specified profile. libvirt is one such application.
|
||||
|
||||
=head2 Access Modes
|
||||
|
||||
@@ -122,6 +131,10 @@ modes:
|
||||
|
||||
=item B<Px> - discrete profile execute -- scrub the environment
|
||||
|
||||
=item B<cx> - transition to subprofile on execute
|
||||
|
||||
=item B<Cx> - transition to subprofile on execute -- scrub the environment
|
||||
|
||||
=item B<ix> - inherit execute
|
||||
|
||||
=item B<m> - allow PROT_EXEC with mmap(2) calls
|
||||
@@ -177,7 +190,7 @@ over the callee. Use this mode only if the child absolutely must be
|
||||
run unconfined and LD_PRELOAD must be used. Any profile using this mode
|
||||
provides negligible security. Use at your own risk.
|
||||
|
||||
Incompatible with 'Ux', 'px', 'Px', 'ix'.
|
||||
Incompatible with 'Ux', 'px', 'Px', 'cx', 'Cx', 'ix'.
|
||||
|
||||
=item B<Ux - unconfined execute -- scrub the environment>
|
||||
|
||||
@@ -191,7 +204,7 @@ designated child processes to be run without any AppArmor protection.
|
||||
Use this mode only if the child absolutely must be run unconfined. Use
|
||||
at your own risk.
|
||||
|
||||
Incompatible with 'ux', 'px', 'Px', 'ix'.
|
||||
Incompatible with 'ux', 'px', 'Px', 'cx', 'Cx', 'ix'.
|
||||
|
||||
=item B<px - Discrete Profile execute mode>
|
||||
|
||||
@@ -203,7 +216,7 @@ B<WARNING> 'px' does not scrub the environment of variables such as
|
||||
LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
||||
influence over the callee.
|
||||
|
||||
Incompatible with 'Ux', 'ux', 'Px', 'ix'.
|
||||
Incompatible with 'Ux', 'ux', 'Px', 'cx', 'Cx', 'ix'.
|
||||
|
||||
=item B<Px - Discrete Profile execute mode -- scrub the environment>
|
||||
|
||||
@@ -212,7 +225,28 @@ will invoke the Linux Kernel's B<unsafe_exec> routines to scrub
|
||||
the environment, similar to setuid programs. (See ld.so(8) for some
|
||||
information on setuid/setgid environment scrubbing.)
|
||||
|
||||
Incompatible with 'Ux', 'ux', 'px', 'ix'.
|
||||
Incompatible with 'Ux', 'ux', 'px', 'cx', 'Cx', 'ix'.
|
||||
|
||||
=item B<cx - Transition to Subprofile execute mode>
|
||||
|
||||
This mode requires that a local security profile is defined and forces an
|
||||
AppArmor domain transition to the named profile. If there is no profile
|
||||
defined then the access will be denied.
|
||||
|
||||
B<WARNING> 'cx' does not scrub the environment of variables such as
|
||||
LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
||||
influence over the callee.
|
||||
|
||||
Incompatible with 'Ux', 'ux', 'px', 'Px', 'Cx', 'ix'.
|
||||
|
||||
=item B<Cx - Transition to Subprofile execute mode -- scrub the environment>
|
||||
|
||||
'Cx' allows the named program to run in 'cx' mode, but AppArmor
|
||||
will invoke the Linux Kernel's B<unsafe_exec> routines to scrub
|
||||
the environment, similar to setuid programs. (See ld.so(8) for some
|
||||
information on setuid/setgid environment scrubbing.)
|
||||
|
||||
Incompatible with 'Ux', 'ux', 'px', 'Px', 'cx', 'ix'.
|
||||
|
||||
=item B<ix - Inherit execute mode>
|
||||
|
||||
@@ -226,7 +260,7 @@ profile, or losing the permissions of the current profile. There is no
|
||||
version to scrub the environment because 'ix' executions don't change
|
||||
privileges.
|
||||
|
||||
Incompatible with 'Ux', 'ux', 'Px', 'px'. Implies 'm'.
|
||||
Incompatible with 'Ux', 'ux', 'Px', 'px', 'cx', 'Cx'. Implies 'm'.
|
||||
|
||||
=item B<m - Allow executable mapping>
|
||||
|
||||
@@ -316,7 +350,11 @@ site-specific customization of B<@{HOMEDIRS}>.
|
||||
|
||||
AppArmor also provides alias rules for remapping paths for site-specific
|
||||
layouts. They are an alternative form of path rewriting to using variables,
|
||||
and are done after variable resolution.
|
||||
and are done after variable resolution. Alias rules must occur within the
|
||||
preamble of the profile. System-wide aliases are found in
|
||||
F</etc/apparmor.d/tunables/alias>, which is included by
|
||||
F</etc/apparmor.d/tunables/global>. F</etc/apparmor.d/tunables/global> is
|
||||
typically included at the beginning of an AppArmor profile.
|
||||
|
||||
=head2 Globbing
|
||||
|
||||
@@ -345,6 +383,10 @@ will substitute for the single character a, b, or c
|
||||
|
||||
will substitute for the single character a, b, or c
|
||||
|
||||
=item B<[^a-c]>
|
||||
|
||||
will substitute for any single character not matching a, b or c
|
||||
|
||||
=item B<{ab,cd}>
|
||||
|
||||
will expand to one rule to match ab, one rule to match cd
|
||||
@@ -376,6 +418,30 @@ Directories anywhere underneath F</tmp>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Rule Qualifiers
|
||||
|
||||
There are several rule qualifiers that can be applied to permission rules.
|
||||
Rule qualifiers can modify the rule and/or permissions within the rule.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<audit>
|
||||
|
||||
Specifies that permissions requests that match the rule should be recorded
|
||||
to the audit log.
|
||||
|
||||
=item B<deny>
|
||||
|
||||
Specifies that permissions requests that match the rule should be denied
|
||||
without logging. Can be combined with 'audit' to enable logging.
|
||||
|
||||
=item B<owner>
|
||||
|
||||
Specifies that the task must have the same euid/fsuid as the object being
|
||||
referenced by the permission check.
|
||||
|
||||
=back
|
||||
|
||||
=head2 #include mechanism
|
||||
|
||||
AppArmor provides an easy abstraction mechanism to group common file
|
||||
@@ -486,7 +552,7 @@ B<@{HOME}> and B<@{HOMEDIRS}>. Variables cannot be set in profile scope;
|
||||
they can only be set before the profile. Therefore, any profiles that
|
||||
use abstractions should either B<#include E<lt>tunables/globalE<gt>> or
|
||||
otherwise ensure that B<@{HOME}> and B<@{HOMEDIRS}> are set before
|
||||
starting the profile definition. The autodep(8) and genprof(8) utilities
|
||||
starting the profile definition. The aa-autodep(8) and aa-genprof(8) utilities
|
||||
will automatically emit B<#include E<lt>tunables/globalE<gt>> in
|
||||
generated profiles.
|
||||
|
||||
@@ -494,7 +560,7 @@ generated profiles.
|
||||
|
||||
An example AppArmor profile:
|
||||
|
||||
# a variable definition
|
||||
# a variable definition in the preamble
|
||||
@{HOME} = /home/*/ /root/
|
||||
|
||||
# a comment about foo.
|
||||
@@ -511,13 +577,23 @@ An example AppArmor profile:
|
||||
/tmp/foo.pid wr,
|
||||
/tmp/foo.* lrw,
|
||||
/@{HOME}/.foo_file rw,
|
||||
/usr/bin/baz Cx -> baz,
|
||||
|
||||
# a comment about foo's subprofile, bar.
|
||||
# a comment about foo's hat (subprofile), bar.
|
||||
^bar {
|
||||
/lib/ld-*.so* rmix,
|
||||
/usr/bin/bar rmix,
|
||||
/var/spool/* rwl,
|
||||
}
|
||||
|
||||
# a comment about foo's subprofile, baz.
|
||||
profile baz {
|
||||
#include <abstractions/bash>
|
||||
owner /proc/[0-9]*/stat r,
|
||||
/bin/bash ixr,
|
||||
/var/lib/baz/ r,
|
||||
owner /var/lib/baz/* rw,
|
||||
}
|
||||
}
|
||||
|
||||
=head1 FILES
|
||||
@@ -532,8 +608,8 @@ An example AppArmor profile:
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor_parser(8), complain(1),
|
||||
enforce(1), change_hat(2), mod_apparmor(5), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor_parser(8), aa-complain(1),
|
||||
aa-enforce(1), aa_change_hat(2), mod_apparmor(5), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,8 +1,12 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) 2010
|
||||
# Canonical Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
@@ -111,7 +115,7 @@ REJECTING. The "name" and process id of the running program are reported,
|
||||
as well as the profile name and any "hat" that may be active. ("Name"
|
||||
is in quotes, because the process name is limited to 15 bytes; it is the
|
||||
same as reported through the Berkeley process accounting.) If no hat is
|
||||
active (see change_hat(2)) then the profile name is printed for "active".
|
||||
active (see aa_change_hat(2)) then the profile name is printed for "active".
|
||||
|
||||
For confined processes running under a profile that has been loaded in
|
||||
complain mode, enforcement will not take place and the log messages
|
||||
@@ -149,10 +153,10 @@ depending upon local configuration.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor_parser(8), change_hat(2), apparmor.d(5),
|
||||
subdomain.conf(5), autodep(1), clean(1),
|
||||
apparmor_parser(8), aa_change_hat(2), apparmor.d(5),
|
||||
subdomain.conf(5), aa-autodep(1), clean(1),
|
||||
auditd(8),
|
||||
unconfined(8), enforce(1), complain(1), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
aa-unconfined(8), aa-enforce(1), aa-complain(1), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,8 +1,12 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) 2010
|
||||
# Canonical Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
@@ -46,12 +50,12 @@ but it may help you understand your profiles better.
|
||||
=head1 BUGS
|
||||
|
||||
B<apparmor.vim> does not properly detect dark versus light backgrounds.
|
||||
Patches accepted. If you find any bugs, please report them to bugzilla
|
||||
at L<http://bugzilla.novell.com>.
|
||||
Patches accepted. If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
vim(1), apparmor(7), apparmor.d(5), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>
|
||||
vim(1), apparmor(7), apparmor.d(5), aa_change_hat(2), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,8 +1,12 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) 2010
|
||||
# Canonical Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
@@ -167,12 +171,12 @@ Give a quick reference guide.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), subdomain.conf(5), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), subdomain.conf(5), aa_change_hat(2), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -148,12 +148,12 @@ enum pattern_t {
|
||||
#include <stdio.h>
|
||||
static inline int is_merged_x_consistent(int a, int b)
|
||||
{
|
||||
if ((a & AA_USER_EXEC_TYPE) && (b & AA_USER_EXEC_TYPE) &&
|
||||
if ((a & AA_USER_EXEC) && (b & AA_USER_EXEC) &&
|
||||
((a & AA_USER_EXEC_TYPE) != (b & AA_USER_EXEC_TYPE)))
|
||||
{ fprintf(stderr, "failed user merge 0x%x 0x%x\n", a, b);
|
||||
return 0;
|
||||
}
|
||||
if ((a & AA_OTHER_EXEC_TYPE) && (b & AA_OTHER_EXEC_TYPE) &&
|
||||
if ((a & AA_OTHER_EXEC) && (b & AA_OTHER_EXEC) &&
|
||||
((a & AA_OTHER_EXEC_TYPE) != (b & AA_OTHER_EXEC_TYPE)))
|
||||
{ fprintf(stderr, "failed other merge 0x%x 0x%x\n", a, b);
|
||||
return 0;
|
||||
|
@@ -720,17 +720,19 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||
Node *i = t->child[!dir];
|
||||
for (;dynamic_cast<AltNode *>(i); p = i, i = i->child[!dir]) {
|
||||
if (t->child[dir]->eq(i->child[dir])) {
|
||||
Node *old = t;
|
||||
t->child[!dir]->dup();
|
||||
t->release();
|
||||
t = t->child[!dir];
|
||||
old->release();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// last altnode of chain check other dir as well
|
||||
if (t->child[dir]->eq(p->child[!dir])) {
|
||||
Node *old = t;
|
||||
t->child[!dir]->dup();
|
||||
t->release();
|
||||
t = t->child[!dir];
|
||||
old->release();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2581,9 +2583,9 @@ extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny,
|
||||
#define MATCH_FLAGS_SIZE (sizeof(uint32_t) * 8 - 1)
|
||||
MatchFlag *match_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
|
||||
DenyMatchFlag *deny_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
|
||||
#define EXEC_MATCH_FLAGS_SIZE ((AA_EXEC_COUNT << 2) * 2)
|
||||
MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix *u::o*/
|
||||
ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE];/* mods + unsafe +ix *u::o*/
|
||||
#define EXEC_MATCH_FLAGS_SIZE (AA_EXEC_COUNT *2 * 2 * 2) /* double for each of ix pux, unsafe x bits * u::o */
|
||||
MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix + pux * u::o*/
|
||||
ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE];/* mods + unsafe + ix + pux *u::o*/
|
||||
|
||||
extern "C" void aare_reset_matchflags(void)
|
||||
{
|
||||
@@ -2644,8 +2646,8 @@ extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
|
||||
flip_tree(tree);
|
||||
|
||||
|
||||
/* 0x3f == 4 bits x mods + 1 bit unsafe mask + 1 bit ix, after shift */
|
||||
#define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 8)) & 0x3f)
|
||||
/* 0x7f == 4 bits x mods + 1 bit unsafe mask + 1 bit ix, + 1 pux after shift */
|
||||
#define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 7)) & 0x7f)
|
||||
|
||||
//if (perms & ALL_AA_EXEC_TYPE && (!perms & AA_EXEC_BITS))
|
||||
// fprintf(stderr, "adding X rule without MAY_EXEC: 0x%x %s\n", perms, rulev[0]);
|
||||
|
@@ -176,6 +176,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;
|
||||
|
@@ -77,7 +77,7 @@ static void print_error(int error)
|
||||
PERROR(_("Out of memory\n"));
|
||||
break;
|
||||
case -EFAULT:
|
||||
PERROR(_("Couldn't copy profile Bad memory address\n"));
|
||||
PERROR(_("Couldn't copy profile: Bad memory address\n"));
|
||||
break;
|
||||
case -EPROTO:
|
||||
PERROR(_("Profile doesn't conform to protocol\n"));
|
||||
|
@@ -377,6 +377,12 @@ LT_EQUAL <=
|
||||
return TOK_VALUE;
|
||||
}
|
||||
|
||||
{END_OF_RULE} {
|
||||
DUMP_PREPROCESS;
|
||||
yylval.id = strdup(yytext);
|
||||
yyerror(_("Variable declarations do not accept trailing commas"));
|
||||
}
|
||||
|
||||
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
|
||||
|
||||
\r?\n {
|
||||
@@ -384,6 +390,11 @@ LT_EQUAL <=
|
||||
current_lineno++;
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
[^\n] {
|
||||
DUMP_PREPROCESS;
|
||||
/* Something we didn't expect */
|
||||
yyerror(_("Found unexpected character: '%s'"), yytext);
|
||||
}
|
||||
}
|
||||
|
||||
<NETWORK_MODE>{
|
||||
|
@@ -55,8 +55,8 @@
|
||||
#define PRIVILEGED_OPS (kernel_load)
|
||||
#define UNPRIVILEGED_OPS (!(PRIVILEGED_OPS))
|
||||
|
||||
const char *parser_title = "Novell/SUSE AppArmor parser";
|
||||
const char *parser_copyright = "Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Novell Inc.";
|
||||
const char *parser_title = "AppArmor parser";
|
||||
const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2010 Canonical Ltd.";
|
||||
|
||||
char *progname;
|
||||
int option = OPTION_ADD;
|
||||
@@ -87,6 +87,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;
|
||||
|
||||
|
@@ -29,6 +29,10 @@
|
||||
#include <linux/socket.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"
|
||||
@@ -236,6 +240,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,
|
||||
@@ -246,13 +313,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,
|
||||
|
@@ -1,8 +1,12 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) 2010
|
||||
# Canonical Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
@@ -92,10 +96,10 @@ Setting the initscript to recompile the module will fail on SUSE, as the
|
||||
module source is no longer installed by default. However, the module has
|
||||
been included with the SUSE kernel, so no rebuilding should be necessary.
|
||||
|
||||
If you find any additional bugs, please report them to
|
||||
bugzilla at L<http://bugzilla.novell.com>.
|
||||
If you find any additional bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor_parser(8), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
@@ -11,8 +11,11 @@ endif
|
||||
|
||||
all: tests
|
||||
|
||||
.PHONY: tests error_output parser_sanity caching
|
||||
tests: error_output parser_sanity caching
|
||||
.PHONY: tests error_output gen_xtrans parser_sanity caching
|
||||
tests: error_output gen_xtrans parser_sanity caching
|
||||
|
||||
gen_xtrans:
|
||||
perl ./gen-xtrans.pl
|
||||
|
||||
error_output: $(PARSER)
|
||||
$(PARSER) -S -I errors >/dev/null errors/okay.sd
|
||||
@@ -34,3 +37,6 @@ caching: $(PARSER)
|
||||
|
||||
$(PARSER):
|
||||
make -C $(PARSER_DIR) $(PARSER_BIN)
|
||||
|
||||
clean:
|
||||
rm -f simple_tests/generated_x/*.sd
|
||||
|
@@ -3,6 +3,13 @@
|
||||
# on the actions and results of the prior tests.
|
||||
set -e
|
||||
|
||||
# This test requires introspection
|
||||
if [ ! -d /sys/kernel/security/apparmor ]; then
|
||||
echo "WARNING: /sys/kernel/security/apparmor does not exist. Skipping tests"
|
||||
echo "requiring introspection."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# fake base directory
|
||||
basedir=$(mktemp -d -t aa-cache-XXXXXX)
|
||||
trap "rm -rf $basedir" EXIT
|
||||
|
152
parser/tst/gen-xtrans.pl
Normal file
152
parser/tst/gen-xtrans.pl
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
|
||||
my $prefix="simple_tests/generated_x";
|
||||
|
||||
my @trans_types = ("p", "P", "c", "C", "u", "i");
|
||||
my @modifiers = ("i", "u");
|
||||
my %trans_modifiers = (
|
||||
"p" => \@modifiers,
|
||||
"P" => \@modifiers,
|
||||
"c" => \@modifiers,
|
||||
"C" => \@modifiers,
|
||||
);
|
||||
|
||||
my @targets = ("", "target", "target2");
|
||||
my @null_target = ("");
|
||||
|
||||
my %named_trans = (
|
||||
"p" => \@targets,
|
||||
"P" => \@targets,
|
||||
"c" => \@targets,
|
||||
"C" => \@targets,
|
||||
"u" => \@null_target,
|
||||
"i" => \@null_target,
|
||||
);
|
||||
|
||||
# audit qualifier disabled for now it really shouldn't affect the conflict
|
||||
# test but it may be worth checking every once in awhile
|
||||
#my @qualifiers = ("", "owner", "audit", "audit owner");
|
||||
my @qualifiers = ("", "owner");
|
||||
|
||||
my $count = 0;
|
||||
|
||||
gen_conflicting_x();
|
||||
gen_overlap_re_exact();
|
||||
gen_dominate_re_re();
|
||||
gen_ambiguous_re_re();
|
||||
|
||||
print "Generated $count xtransition interaction tests\n";
|
||||
|
||||
sub gen_list {
|
||||
my @output;
|
||||
foreach my $trans (@trans_types) {
|
||||
if ($trans_modifiers{$trans}) {
|
||||
foreach my $mod (@{$trans_modifiers{$trans}}) {
|
||||
push @output, "${trans}${mod}x";
|
||||
}
|
||||
}
|
||||
push @output, "${trans}x";
|
||||
}
|
||||
return @output;
|
||||
}
|
||||
|
||||
sub print_rule($$$$) {
|
||||
my ($file, $name, $perm, $target) = @_;
|
||||
print $file "\t${name} ${perm}";
|
||||
if ($target ne "") {
|
||||
print $file " -> $target";
|
||||
}
|
||||
print $file ",\n";
|
||||
}
|
||||
|
||||
sub gen_file($$$$$$$$) {
|
||||
my ($name, $xres, $rule1, $perm1, $target1, $rule2, $perm2, $target2) = @_;
|
||||
|
||||
# print "$xres $rule1 $perm1 $target1 $rule2 $perm2 $target2\n";
|
||||
|
||||
my $file;
|
||||
unless (open $file, ">$name") {
|
||||
print("couldn't open $name\n");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print $file "#\n";
|
||||
print $file "#=DESCRIPTION ${name}\n";
|
||||
print $file "#=EXRESULT ${xres}\n";
|
||||
print $file "#\n";
|
||||
print $file "/usr/bin/foo {\n";
|
||||
print_rule($file, $rule1, $perm1, $target1);
|
||||
print_rule($file, $rule2, $perm2, $target2);
|
||||
print $file "}";
|
||||
close($file);
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
#NOTE: currently we don't do px to cx, or cx to px conversion
|
||||
# so
|
||||
# /foo {
|
||||
# /* px -> /foo//bar,
|
||||
# /* cx -> bar,
|
||||
#
|
||||
# will conflict
|
||||
#
|
||||
#NOTE: conflict tests don't tests leading permissions or using unsafe keywords
|
||||
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
|
||||
sub gen_files($$$$) {
|
||||
my ($name, $rule1, $rule2, $default) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
# print "@perms\n";
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
foreach my $j (@perms) {
|
||||
foreach my $u (@{$named_trans{substr($j, 0, 1)}}) {
|
||||
foreach my $r (@qualifiers) {
|
||||
my $file="${prefix}/${name}-$q$i$t-$r$j$u.sd";
|
||||
# print "$file\n";
|
||||
|
||||
#override failures when transitions are the same
|
||||
my $xres = ${default};
|
||||
if ($i eq $j && $t eq $u) {
|
||||
$xres = "PASS";
|
||||
}
|
||||
|
||||
|
||||
# print "foo $xres $rule1 $i $t $rule2 $j $u\n";
|
||||
gen_file($file, $xres, "$q $rule1", $i, $t, "$r $rule2", $j, $u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub gen_conflicting_x {
|
||||
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL");
|
||||
}
|
||||
|
||||
sub gen_overlap_re_exact {
|
||||
|
||||
gen_files("exact", "/bin/cat", "/bin/*", "PASS");
|
||||
}
|
||||
|
||||
# we currently don't support this, once supported change to "PASS"
|
||||
sub gen_dominate_re_re {
|
||||
gen_files("dominate", "/bin/*", "/bin/**", "FAIL");
|
||||
}
|
||||
|
||||
sub gen_ambiguous_re_re {
|
||||
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL");
|
||||
}
|
2
parser/tst/simple_tests/generated_x/readme
Normal file
2
parser/tst/simple_tests/generated_x/readme
Normal file
@@ -0,0 +1,2 @@
|
||||
Directory for auto generated x-transition tests
|
||||
|
10
parser/tst/simple_tests/vars/vars_bad_1.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_1.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing garbage should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = "libvirt
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_2.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_2.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION garbage should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = lib"virt
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_3.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_3.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION garbage should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = lib!virt libfail
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_1.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_1.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing commas should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = libvirt,
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_2.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_2.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing commas should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = libvirt libtriv,
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_3.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_3.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing commas should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = libvirt, libtriv,
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_4.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_trailing_comma_4.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing commas should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = libvirt, libtriv
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_bad_trailing_garbage_1.sd
Normal file
10
parser/tst/simple_tests/vars/vars_bad_trailing_garbage_1.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION trailing garbage should trigger an error
|
||||
#=EXRESULT FAIL
|
||||
|
||||
@{LIBVIRT} = libvirt"
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_simple_assignment_13.sd
Normal file
10
parser/tst/simple_tests/vars/vars_simple_assignment_13.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION quoted commas should not trigger an error
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{LIBVIRT} = "libvirt,"
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_simple_assignment_14.sd
Normal file
10
parser/tst/simple_tests/vars/vars_simple_assignment_14.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#=DESCRIPTION quoted commas should not trigger an error
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{LIBVIRT} = "libvirt, libtriv"
|
||||
|
||||
/does/not/exist {
|
||||
|
||||
change_profile ->
|
||||
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
}
|
@@ -33,7 +33,7 @@
|
||||
/usr/X11R6/**.so* mr,
|
||||
|
||||
# DRI
|
||||
/usr/lib/dri/** mr,
|
||||
/usr/lib{,32,64}/dri/** mr,
|
||||
/dev/dri/** rw,
|
||||
|
||||
# mouse themes
|
||||
|
56
profiles/apparmor.d/abstractions/enchant
Normal file
56
profiles/apparmor.d/abstractions/enchant
Normal file
@@ -0,0 +1,56 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# abstraction for Enchant spellchecking frontend
|
||||
|
||||
/usr/share/enchant/ r,
|
||||
/usr/share/enchant/enchant.ordering r,
|
||||
|
||||
# aspell
|
||||
#include <abstractions/aspell>
|
||||
/var/lib/dictionaries-common/aspell/ r,
|
||||
/var/lib/dictionaries-common/aspell/* r,
|
||||
|
||||
# hspell
|
||||
/usr/share/hspell/ r,
|
||||
/usr/share/hspell/*.wgz.* r,
|
||||
|
||||
# hunspell
|
||||
/usr/share/hunspell/ r,
|
||||
/usr/share/hunspell/* r,
|
||||
|
||||
# ispell
|
||||
/usr/lib/ispell/ r,
|
||||
/usr/lib/ispell/*.hash r,
|
||||
/usr/share/dict/ r,
|
||||
/usr/share/dict/* r,
|
||||
/var/lib/dictionaries-common/ r,
|
||||
/var/lib/dictionaries-common/{ispell,wordlist}/ r,
|
||||
/var/lib/dictionaries-common/{ispell,wordlist}/* r,
|
||||
|
||||
# myspell
|
||||
/usr/share/myspell/ r,
|
||||
/usr/share/myspell/** r,
|
||||
|
||||
# voikko
|
||||
/usr/lib/voikko/ r,
|
||||
/usr/lib/voikko/2/ r,
|
||||
/usr/lib/voikko/2/mor-standard/ r,
|
||||
/usr/lib/voikko/2/mor-standard/voikko* r,
|
||||
|
||||
# zemberek
|
||||
/usr/share/java/ r,
|
||||
/usr/share/java/zemberek-[0-9]*.jar r,
|
||||
/usr/share/java/zemberek-tr-[0-9]*.jar r,
|
||||
|
||||
# per-user dictionaries
|
||||
owner @{HOME}/.config/enchant/ r,
|
||||
owner @{HOME}/.config/enchant/* rwk,
|
@@ -11,6 +11,9 @@
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# system configuration
|
||||
/usr/share/applications/ r,
|
||||
/usr/share/applications/mimeinfo.cache r,
|
||||
/usr/share/applications/*.desktop r,
|
||||
/usr/share/icons/ r,
|
||||
/usr/share/icons/** r,
|
||||
/usr/share/pixmaps/ r,
|
||||
@@ -24,10 +27,15 @@
|
||||
/usr/share/mime/** r,
|
||||
|
||||
# per-user configurations
|
||||
@{HOME}/.icons/ r,
|
||||
@{HOME}/.recently-used.xbel* rw,
|
||||
@{HOME}/.config/user-dirs.dirs r,
|
||||
@{HOME}/.local/share/icons/ r,
|
||||
@{HOME}/.local/share/icons/** r,
|
||||
@{HOME}/.local/share/mime/ r,
|
||||
@{HOME}/.local/share/mime/** r,
|
||||
owner @{HOME}/.icons/ r,
|
||||
owner @{HOME}/.recently-used.xbel* rw,
|
||||
owner @{HOME}/.local/share/recently-used.xbel* rw,
|
||||
owner @{HOME}/.config/user-dirs.dirs r,
|
||||
owner @{HOME}/.local/share/applications/*.desktop r,
|
||||
owner @{HOME}/.local/share/applications/defaults.list r,
|
||||
owner @{HOME}/.local/share/applications/mimeapps.list r,
|
||||
owner @{HOME}/.local/share/applications/mimeinfo.cache r,
|
||||
owner @{HOME}/.local/share/icons/ r,
|
||||
owner @{HOME}/.local/share/icons/** r,
|
||||
owner @{HOME}/.local/share/mime/ r,
|
||||
owner @{HOME}/.local/share/mime/** r,
|
||||
|
15
profiles/apparmor.d/abstractions/ibus
Normal file
15
profiles/apparmor.d/abstractions/ibus
Normal file
@@ -0,0 +1,15 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# abstraction for ibus input methods
|
||||
owner @{HOME}/.config/ibus/ r,
|
||||
owner @{HOME}/.config/ibus/bus/ rw,
|
||||
owner @{HOME}/.config/ibus/bus/* rw,
|
@@ -14,6 +14,8 @@
|
||||
|
||||
# special attention to (potentially) executable files
|
||||
audit deny @{HOME}/bin/** wl,
|
||||
audit deny @{HOME}/.config/autostart/** wl,
|
||||
audit deny @{HOME}/.kde/Autostart/** wl,
|
||||
|
||||
deny @{HOME}/.bash* mrk,
|
||||
audit deny @{HOME}/.bash* wl,
|
||||
|
@@ -9,4 +9,10 @@
|
||||
audit deny @{HOME}/.ssh/** mrwkl,
|
||||
audit deny @{HOME}/.gnome2_private/** mrwkl,
|
||||
audit deny @{HOME}/.mozilla/** mrwkl,
|
||||
audit deny @{HOME}/.config/chromium/** mrwkl,
|
||||
audit deny @{HOME}/.{,mozilla-}thunderbird/** mrwkl,
|
||||
audit deny @{HOME}/.evolution/** mrwkl,
|
||||
audit deny @{HOME}/.config/evolution/** mrwkl,
|
||||
audit deny @{HOME}/.kde/share/apps/kmail/** mrwkl,
|
||||
audit deny @{HOME}/.kde/share/apps/kwallet/** mrwkl,
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
/etc/samba/smb.conf r,
|
||||
/usr/share/samba/*.dat r,
|
||||
/var/lib/samba/**.tdb rwk,
|
||||
/var/log/samba/cores/ rw,
|
||||
/var/log/samba/cores/* w,
|
||||
/var/log/samba/log.* w,
|
||||
/var/run/samba/*.tdb rw,
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/usr/bin/prism PUx,
|
||||
/usr/bin/rekonq PUx,
|
||||
/usr/bin/seamonkey PUx,
|
||||
/usr/bin/sensible-browser PUxr,
|
||||
/usr/bin/sensible-browser Pixr,
|
||||
|
||||
/usr/bin/chromium-browser PUx,
|
||||
/usr/lib/chromium-browser/chromium-browser PUx,
|
||||
|
@@ -15,5 +15,5 @@
|
||||
/usr/bin/tkrat PUx,
|
||||
|
||||
/usr/lib/thunderbird/thunderbird PUx,
|
||||
/usr/lib/thunderbird-3*/thunderbird PUx,
|
||||
/usr/lib/thunderbird-3*/thunderbird{,.sh} PUx,
|
||||
|
||||
|
@@ -12,11 +12,11 @@
|
||||
# Description: Where common programs should allow users to download
|
||||
# files
|
||||
|
||||
@{HOME}/tmp/** rwl,
|
||||
@{HOME}/download/** rwl,
|
||||
@{HOME}/downloads/** rwl,
|
||||
@{HOME}/[a-zA-Z0-9]* rwl,
|
||||
@{HOME}/Desktop r,
|
||||
@{HOME}/Desktop/* rwl,
|
||||
"@{HOME}/My Downloads/" r,
|
||||
"@{HOME}/My Downloads/**" rwl,
|
||||
owner @{HOME}/tmp/** rwl,
|
||||
owner @{HOME}/[dD]ownload{,s}/ r,
|
||||
owner @{HOME}/[dD]ownload{,s}/** rwl,
|
||||
owner @{HOME}/[a-zA-Z0-9]* rwl,
|
||||
owner @{HOME}/Desktop/ r,
|
||||
owner @{HOME}/Desktop/* rwl,
|
||||
owner "@{HOME}/My Downloads/" r,
|
||||
owner "@{HOME}/My Downloads/**" rwl,
|
||||
|
@@ -10,16 +10,14 @@
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# location of user mail, spool and mboxes
|
||||
@{HOME}/Mail/ r,
|
||||
@{HOME}/mail/ r,
|
||||
@{HOME}/Mail/** rwl,
|
||||
@{HOME}/mail/** rwl,
|
||||
@{HOME}/postponed* rwl,
|
||||
owner @{HOME}/[mM]ail/ r,
|
||||
owner @{HOME}/[mM]ail/** rwl,
|
||||
owner @{HOME}/postponed* rwl,
|
||||
/var/spool/mail/ r,
|
||||
/var/spool/mail/* rwl,
|
||||
@{HOME}/mbox.lock* rwl,
|
||||
@{HOME}/mbox rw,
|
||||
@{HOME}/inbox rw,
|
||||
@{HOME}/.forward r,
|
||||
@{HOME}/Maildir/ r,
|
||||
@{HOME}/Maildir/** rwl,
|
||||
owner @{HOME}/mbox.lock* rwl,
|
||||
owner @{HOME}/mbox rw,
|
||||
owner @{HOME}/inbox rw,
|
||||
owner @{HOME}/.forward r,
|
||||
owner @{HOME}/Maildir/ r,
|
||||
owner @{HOME}/Maildir/** rwl,
|
||||
|
@@ -11,11 +11,11 @@
|
||||
|
||||
# perhaps your configuration has users elsewhere, or you don't wish
|
||||
# them to read their own manpages
|
||||
@{HOME}/man/** r,
|
||||
@{HOME}/tmp/groff* rwl,
|
||||
owner @{HOME}/man/** r,
|
||||
owner @{HOME}/tmp/groff* rwl,
|
||||
|
||||
# kindof required
|
||||
/tmp/groff* rwl,
|
||||
owner /tmp/groff* rwl,
|
||||
|
||||
# standard system manpages
|
||||
/usr/local/share/man/man?/ r,
|
||||
|
@@ -10,10 +10,12 @@
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# per-user write directories
|
||||
@{HOME}/ r,
|
||||
@{HOME}/Desktop/ r,
|
||||
@{HOME}/Documents/ r,
|
||||
@{HOME}/[a-zA-Z0-9]*/ rw,
|
||||
@{HOME}/[a-zA-Z0-9]* rwl,
|
||||
@{HOME}/Desktop/** rwl,
|
||||
@{HOME}/Documents/** rwl,
|
||||
owner @{HOME}/ r,
|
||||
owner @{HOME}/Desktop/ r,
|
||||
owner @{HOME}/Documents/ r,
|
||||
owner @{HOME}/Public/ r,
|
||||
owner @{HOME}/[a-zA-Z0-9]*/ rw,
|
||||
owner @{HOME}/[a-zA-Z0-9]* rwl,
|
||||
owner @{HOME}/Desktop/** rwl,
|
||||
owner @{HOME}/Documents/** rwl,
|
||||
owner @{HOME}/Public/** rwl,
|
||||
|
@@ -1,4 +1,14 @@
|
||||
# Author: John Dong <jdong@ubuntu.com>
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2009 John Dong <jdong@ubuntu.com>
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
#include <tunables/global>
|
||||
/usr/sbin/dnsmasq {
|
||||
#include <abstractions/base>
|
||||
@@ -8,6 +18,9 @@
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
capability dac_override,
|
||||
capability net_admin, # for DHCP server
|
||||
capability net_raw, # for DHCP server ping checks
|
||||
network inet raw,
|
||||
|
||||
/etc/dnsmasq.conf r,
|
||||
/etc/dnsmasq.d/ r,
|
||||
@@ -20,4 +33,9 @@
|
||||
/var/run/dnsmasq/* rw,
|
||||
|
||||
/var/lib/misc/dnsmasq.leases rw, # Required only for DHCP server usage
|
||||
|
||||
# libvirt pid files for dnsmasq
|
||||
/var/run/libvirt/network/ r,
|
||||
/var/run/libvirt/network/*.pid rw,
|
||||
|
||||
}
|
||||
|
@@ -59,11 +59,11 @@
|
||||
/var/run/ntpd.pid w,
|
||||
/var/tmp/ntp* rwl,
|
||||
@{PROC}/*/net/if_inet6 r,
|
||||
@{PROC}/*/sys/kernel/ngroups_max r,
|
||||
@{PROC}/sys/kernel/ngroups_max r,
|
||||
|
||||
# allow access for when chrooted
|
||||
/var/lib/ntp/@{PROC}/*/net/if_inet6 r,
|
||||
/var/lib/ntp/@{PROC}/*/sys/kernel/ngroups_max r,
|
||||
/var/lib/ntp/@{PROC}/sys/kernel/ngroups_max r,
|
||||
|
||||
@{NTPD_DEVICE} rw,
|
||||
}
|
||||
|
@@ -32,9 +32,9 @@
|
||||
/opt/kde3/share/applications/ r,
|
||||
/opt/kde3/share/applications/mimeinfo.cache r,
|
||||
|
||||
owner @{proc}/*/mounts r,
|
||||
@{proc}/meminfo r,
|
||||
@{proc}/sys/kernel/ngroups_max r,
|
||||
owner @{PROC}/*/mounts r,
|
||||
@{PROC}/meminfo r,
|
||||
@{PROC}/sys/kernel/ngroups_max r,
|
||||
|
||||
/usr/lib/**.so mr,
|
||||
|
||||
|
@@ -142,6 +142,7 @@ TESTS=access \
|
||||
setattr \
|
||||
symlink \
|
||||
syscall \
|
||||
tcp \
|
||||
unix_fd_server \
|
||||
unlink\
|
||||
xattrs\
|
||||
|
@@ -64,7 +64,7 @@ echo
|
||||
echo "*** A 'Killed' message from bash is expected for the following test"
|
||||
runchecktest "CHANGEHAT (subprofile->subprofile w/ bad magic)" signal9 $subtest $subtest2 badmagic $file
|
||||
|
||||
# 1. ATTEMPT TO CHANGEGAT TO AN INVALUD PROFILE, SHOULD PUT US INTO A NULL
|
||||
# 1. ATTEMPT TO CHANGEHAT TO AN INVALID PROFILE, SHOULD PUT US INTO A NULL
|
||||
# PROFILE
|
||||
# 2. ATTEMPT TO CHANGEHAT OUT WITH BAD TOKEN
|
||||
settest changehat_fail
|
||||
|
@@ -90,7 +90,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* test that we can create the file. Not necessarily a (deleted)
|
||||
* case but lets use flush out other combinations
|
||||
* case but lets us flush out other combinations.
|
||||
*/
|
||||
fd2=creat(argv[2], S_IRUSR | S_IWUSR);
|
||||
if (fd2 == -1){
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /bin/bash
|
||||
# $Id$
|
||||
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 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
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#=NAME deleted
|
||||
#=DESCRIPTION
|
||||
# Test subdomain is properly working around a kernel in which the kernel
|
||||
# Test AppArmor is properly working around a kernel in which the kernel
|
||||
# appends (deleted) to deleted files verifies that the d_path appending
|
||||
# (deleted) fix is working
|
||||
#=END
|
||||
@@ -24,6 +24,7 @@ bin=$pwd
|
||||
|
||||
file=$tmpdir/file
|
||||
file2="$tmpdir/file (deleted)"
|
||||
file3="$tmpdir/unavailable"
|
||||
okperm=rwl
|
||||
|
||||
subtest=sub
|
||||
@@ -40,8 +41,8 @@ runchecktest "NO PROFILE (access file (deleted))" pass nochange "$file2"
|
||||
# NO CHANGEHAT TEST - doesn't force revalidation
|
||||
|
||||
genprofile $file:$okperm
|
||||
|
||||
runchecktest "NO CHANGEHAT (access file)" pass nochange $file
|
||||
runchecktest "NO CHANGEHAT (cannot access unavailable)" fail nochange $file3
|
||||
|
||||
genprofile "$file2":$okperm
|
||||
runchecktest "NO CHANGEHAT (access file (delete))" pass nochange "$file2"
|
||||
@@ -49,6 +50,7 @@ runchecktest "NO CHANGEHAT (access file (delete))" pass nochange "$file2"
|
||||
# CHANGEHAT TEST - force revalidation using changehat
|
||||
genprofile $file:$okperm hat:$subtest $file:$okperm
|
||||
runchecktest "CHANGEHAT (access file)" pass $subtest $file
|
||||
runchecktest "CHANGEHAT (cannot access unavailable)" fail $subtest $file3
|
||||
|
||||
genprofile "$file2":$okperm hat:$subtest "$file2":$okperm
|
||||
runchecktest "CHANGEHAT (access file (deleted))" pass $subtest "$file2"
|
||||
@@ -115,7 +117,7 @@ rm -f ${socket}
|
||||
# FAIL - confined client, w access to the file
|
||||
|
||||
genprofile $file:$okperm $socket:rw $fd_client:px -- image=$fd_client $file:$badperm $socket:rw
|
||||
runchecktest "fd passing; confined client w/ w only" pass $file $socket $fd_client "delete_file"
|
||||
runchecktest "fd passing; confined client w/ w only" fail $file $socket $fd_client "delete_file"
|
||||
|
||||
sleep 1
|
||||
rm -f ${socket}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gawd, I hate writing perl. It shows, too.
|
||||
#
|
||||
my $__VERSION__='$Id$';
|
||||
my $__VERSION__=$0;
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
@@ -93,8 +93,10 @@ resolve_symlink()
|
||||
|
||||
while [ -h ${link} ]
|
||||
do
|
||||
if [ -x /usr/bin/readlink ] ; then
|
||||
target=$(/usr/bin/readlink ${link})
|
||||
if [ -x /usr/bin/readlink ] ; then
|
||||
target=$(/usr/bin/readlink -f ${link})
|
||||
elif [ -x /bin/readlink ] ; then
|
||||
target=$(/bin/readlink -f ${link})
|
||||
else
|
||||
# I'm sure there's a more perlish way to do this
|
||||
target=$( perl -e "printf (\"%s\n\", readlink(\"${link}\"));")
|
||||
|
@@ -27,7 +27,7 @@ badreadperm=w
|
||||
|
||||
genprofile $file:$okperm
|
||||
|
||||
runtestbg "PWRITE with w" pass $file
|
||||
runtestbg "PREAD/PWRITE with rw" pass $file
|
||||
|
||||
sleep 2
|
||||
|
||||
|
@@ -32,7 +32,7 @@ bin=$pwd
|
||||
swap_file=$tmpdir/swapfile
|
||||
|
||||
dd if=/dev/zero of=${swap_file} bs=1024 count=512 2> /dev/null
|
||||
/sbin/mkswap ${swap_file} > /dev/null
|
||||
/sbin/mkswap -f ${swap_file} > /dev/null
|
||||
|
||||
# TEST 1. Make sure can enable and disable swap unconfined
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /bin/bash
|
||||
# $Id$
|
||||
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 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
|
||||
@@ -114,9 +114,9 @@ rm -f $mknod_file
|
||||
runchecktest "MKNOD sock (permissions)" fail s $mknod_file
|
||||
|
||||
##
|
||||
## D. SETHOSTNAME
|
||||
## C. SYSCTL
|
||||
##
|
||||
sh syscall_sysctl.sh
|
||||
bash syscall_sysctl.sh
|
||||
|
||||
##
|
||||
## D. SETHOSTNAME
|
||||
|
@@ -23,18 +23,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:
|
||||
@@ -64,12 +83,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.
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002-2005 Novell/SUSE
|
||||
* Copyright (C) 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
|
||||
@@ -134,6 +135,7 @@ int main (int argc, char * argv[]) {
|
||||
}
|
||||
|
||||
/* Check for info re: reading the file */
|
||||
memset(inbound_buffer, 0, sizeof(inbound_buffer));
|
||||
if (recv(in_sock, inbound_buffer, 16,0) == -1 ) {
|
||||
fprintf(stderr, "FAIL - recv %s\n",
|
||||
strerror(errno));
|
||||
|
@@ -38,41 +38,59 @@ bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
|
||||
file=$tmpdir/testfile
|
||||
link=$tmpdir/testlink
|
||||
dir=$tmpdir/testdir/
|
||||
tmpmount=$tmpdir/mountpoint
|
||||
diskimg=$tmpdir/disk.img
|
||||
file=$tmpmount/testfile
|
||||
link=$tmpmount/testlink
|
||||
dir=$tmpmount/testdir/
|
||||
okperm=rw
|
||||
badperm=r
|
||||
|
||||
# guarantee fs supports user_xattrs
|
||||
dd if=/dev/zero of=${diskimg} bs=4096 count=4096 2> /dev/null
|
||||
mkfs.ext3 -q -F ${diskimg}
|
||||
mkdir ${tmpmount}
|
||||
mount -o loop,user_xattr ${diskimg} ${tmpmount}
|
||||
|
||||
touch $file
|
||||
ln -s $file $link
|
||||
mkdir $dir
|
||||
|
||||
add_attrs()
|
||||
{
|
||||
#set the xattr for thos that passed above again so we can test removing it
|
||||
setfattr -h -n security.sdtest -v hello "$1"
|
||||
setfattr -h -n trusted.sdtest -v hello "$1"
|
||||
if [ "$1" != $link ] ; then
|
||||
setfattr -h -n user.sdtest -v hello "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
for var in $file $link $dir ; do
|
||||
#write xattr
|
||||
genprofile $var:$badperm
|
||||
xattrtest $var $badperm write security fail
|
||||
#xattrtest $var $badperm write system fail
|
||||
xattrtest $var $badperm write trusted fail
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm write user fail ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm write user xfail ; fi
|
||||
|
||||
genprofile $var:$badperm capability:sys_admin
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" write security xfail
|
||||
#xattrtest $var "$badperm+cap SYS_ADMIN" write system fail
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" write trusted xfail
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" write user fail ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" write user xfail ; fi
|
||||
|
||||
genprofile $var:$okperm
|
||||
xattrtest $var $okperm write security xpass
|
||||
#xattrtest $var $okperm write system fail
|
||||
xattrtest $var $okperm write trusted fail
|
||||
if [ $var != $link ] ; then xattrtest $var $okperm write user xpass ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var $okperm write user pass ; fi
|
||||
|
||||
genprofile $var:$okperm capability:sys_admin
|
||||
xattrtest $var "$okperm+cap SYS_ADMIN" write security pass
|
||||
#xattrtest $var "$okperm+cap SYS_ADMIN" write system pass
|
||||
xattrtest $var "$okperm+cap SYS_ADMIN" write trusted pass
|
||||
if [ $var != $link ] ; then xattrtest $var "$okperm+cap SYS_ADMIN" write user xpass ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var "$okperm+cap SYS_ADMIN" write user pass ; fi
|
||||
|
||||
|
||||
#read xattr
|
||||
@@ -80,13 +98,13 @@ for var in $file $link $dir ; do
|
||||
xattrtest $var $badperm read security pass
|
||||
#xattrtest $var $badperm read system fail
|
||||
xattrtest $var $badperm read trusted fail
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm read user xpass ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm read user pass ; fi
|
||||
|
||||
genprofile $var:$badperm capability:sys_admin
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" read security pass
|
||||
#xattrtest $var "$badperm+cap SYS_ADMIN" read system pass
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" read trusted pass
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" read user xpass ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" read user pass ; fi
|
||||
|
||||
|
||||
#remove xattr
|
||||
@@ -94,23 +112,25 @@ for var in $file $link $dir ; do
|
||||
xattrtest $var $badperm remove security fail
|
||||
#xattrtest $var $badperm remove system fail
|
||||
xattrtest $var $badperm remove trusted fail
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm remove user fail ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var $badperm remove user xfail ; fi
|
||||
|
||||
add_attrs $var
|
||||
|
||||
genprofile $var:$badperm capability:sys_admin
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" remove security xfail
|
||||
#xattrtest $var "$badperm+cap SYS_ADMIN" remove system fail
|
||||
xattrtest $var "$badperm+cap SYS_ADMIN" remove trusted xfail
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" remove user fail ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var "$badperm+cap SYS_ADMIN" remove user xfail ; fi
|
||||
|
||||
add_attrs $var
|
||||
|
||||
genprofile $var:$okperm
|
||||
xattrtest $var $okperm remove security xpass
|
||||
#xattrtest $var $okperm remove system fail
|
||||
xattrtest $var $okperm remove trusted fail
|
||||
if [ $var != $link ] ; then xattrtest $var $okperm remove user xpass ; fi
|
||||
if [ $var != $link ] ; then xattrtest $var $okperm remove user pass ; fi
|
||||
|
||||
#set the xattr for thos that passed above again so we can test removing it
|
||||
setfattr -h -n security.sdtest -v hello $var
|
||||
if [ $var != $link ] ; then setfattr -h -n user.sdtest -v hello $var ; fi
|
||||
add_attrs $var
|
||||
|
||||
genprofile $var:$okperm capability:sys_admin
|
||||
xattrtest $var "$okperm+cap SYS_ADMIN" remove security pass
|
||||
@@ -120,3 +140,4 @@ for var in $file $link $dir ; do
|
||||
|
||||
done
|
||||
|
||||
umount ${tmpmount}
|
||||
|
@@ -41,7 +41,8 @@ all: ${MANPAGES} ${HTMLMANPAGES}
|
||||
DESTDIR=/
|
||||
BINDIR=${DESTDIR}/usr/sbin
|
||||
CONFDIR=${DESTDIR}/etc/apparmor
|
||||
PERLDIR=${DESTDIR}/usr/lib/perl5/vendor_perl/Immunix
|
||||
VENDOR_PERL?=/usr/lib/perl5/vendor_perl
|
||||
PERLDIR=${DESTDIR}${VENDOR_PERL}/Immunix
|
||||
|
||||
po/${NAME}.pot: ${TOOLS}
|
||||
make -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} SubDomain.pm Repository.pm Config.pm Reports.pm"
|
||||
|
@@ -967,7 +967,7 @@ sub getEssStats {
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -980,7 +980,7 @@ sub getEssStats {
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -988,7 +988,7 @@ sub getEssStats {
|
||||
eval { $ret = $dbh->selectall_arrayref("$query"); };
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -233,6 +233,50 @@ my %MODE_HASH = (
|
||||
N => $AA_EXEC_NT,
|
||||
);
|
||||
|
||||
|
||||
# Currently only used by netdomain but there's no reason it couldn't
|
||||
# be extended to support other types.
|
||||
my %operation_types = (
|
||||
|
||||
# Old socket names
|
||||
"socket_create", => "net",
|
||||
"socket_post_create" => "net",
|
||||
"socket_bind" => "net",
|
||||
"socket_connect" => "net",
|
||||
"socket_listen" => "net",
|
||||
"socket_accept" => "net",
|
||||
"socket_sendmsg" => "net",
|
||||
"socket_recvmsg" => "net",
|
||||
"socket_getsockname" => "net",
|
||||
"socket_getpeername" => "net",
|
||||
"socket_getsockopt" => "net",
|
||||
"socket_setsockopt" => "net",
|
||||
"socket_shutdown" => "net",
|
||||
|
||||
# New socket names
|
||||
"create" => "net",
|
||||
"post_create" => "net",
|
||||
"bind" => "net",
|
||||
"connect" => "net",
|
||||
"listen" => "net",
|
||||
"accept" => "net",
|
||||
"sendmsg" => "net",
|
||||
"recvmsg" => "net",
|
||||
"getsockname" => "net",
|
||||
"getpeername" => "net",
|
||||
"getsockopt" => "net",
|
||||
"setsockopt" => "net",
|
||||
"sock_shutdown" => "net",
|
||||
);
|
||||
|
||||
sub optype($) {
|
||||
my $op = shift;
|
||||
my $type = $operation_types{$op};
|
||||
|
||||
return "unknown" if !defined($type);
|
||||
return $type;
|
||||
}
|
||||
|
||||
sub debug ($) {
|
||||
my $message = shift;
|
||||
chomp($message);
|
||||
@@ -1750,6 +1794,9 @@ sub confirm_and_abort {
|
||||
if ($ans eq "y") {
|
||||
UI_Info(gettext("Abandoning all changes."));
|
||||
shutdown_yast();
|
||||
foreach my $prof (@created) {
|
||||
delete_profile($prof);
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
@@ -1909,7 +1956,7 @@ sub handlechildren {
|
||||
$hat = $h;
|
||||
}
|
||||
|
||||
next unless $profile && $hat;
|
||||
next unless $profile && $hat && $detail;
|
||||
my $domainchange = ($type eq "exec") ? "change" : "nochange";
|
||||
|
||||
# escape special characters that show up in literal paths
|
||||
@@ -2304,7 +2351,7 @@ sub handlechildren {
|
||||
unless (-e getprofilefilename($exec_target)) {
|
||||
my $ynans = "y";
|
||||
if ($exec_mode & str_to_mode("i")) {
|
||||
$ynans = UI_YesNo(sprintf(gettext("A profile for %s does not exist create one?"), $exec_target), "n");
|
||||
$ynans = UI_YesNo(sprintf(gettext("A profile for %s does not exist. Create one?"), $exec_target), "n");
|
||||
}
|
||||
if ($ynans eq "y") {
|
||||
$helpers{$exec_target} = "enforce";
|
||||
@@ -2331,7 +2378,7 @@ sub handlechildren {
|
||||
unless ($sd{$profile}{$exec_target}) {
|
||||
my $ynans = "y";
|
||||
if ($exec_mode & str_to_mode("i")) {
|
||||
$ynans = UI_YesNo(sprintf(gettext("A local profile for %s does not exist create one?"), $exec_target), "n");
|
||||
$ynans = UI_YesNo(sprintf(gettext("A local profile for %s does not exist. Create one?"), $exec_target), "n");
|
||||
}
|
||||
if ($ynans eq "y") {
|
||||
$hat = $exec_target;
|
||||
@@ -2341,6 +2388,12 @@ sub handlechildren {
|
||||
# we have seen more than a declaration so clear it
|
||||
$sd{$profile}{$hat}{'declared'} = 0;
|
||||
$sd{$profile}{$hat}{profile} = 1;
|
||||
|
||||
# Otherwise sub-profiles end up getting
|
||||
# put in enforce mode with genprof
|
||||
$sd{$profile}{$hat}{flags} = $sd{$profile}{$profile}{flags} if $profile ne $hat;
|
||||
|
||||
$sd{$profile}{$hat}{flags} = 'complain';
|
||||
$sd{$profile}{$hat}{allow}{path} = { };
|
||||
$sd{$profile}{$hat}{allow}{netdomain} = { };
|
||||
my $file = $sd{$profile}{$profile}{filename};
|
||||
@@ -2420,7 +2473,7 @@ my $RE_LOG_v2_0_audit =
|
||||
my $RE_LOG_v2_1_audit =
|
||||
qr/type=(UNKNOWN\[150[1-6]\]|APPARMOR_(AUDIT|ALLOWED|DENIED|HINT|STATUS|ERROR))/;
|
||||
my $RE_LOG_v2_6_audit =
|
||||
qr/type=AVC\s+audit\([\d\.\:]+\):\s+apparmor=/;
|
||||
qr/type=AVC\s+(msg=)?audit\([\d\.\:]+\):\s+apparmor=/;
|
||||
|
||||
sub prefetch_next_log_entry {
|
||||
# if we already have an existing cache entry, something's broken
|
||||
@@ -2739,6 +2792,13 @@ sub add_event_to_tree ($) {
|
||||
return if ($e->{operation} =~ /profile_set/);
|
||||
|
||||
my ($profile, $hat);
|
||||
|
||||
# The version of AppArmor that was accepted into the mainline kernel
|
||||
# issues audit events for things like change_hat while unconfined.
|
||||
# Previous versions just returned -EPERM without the audit so the
|
||||
# events wouldn't have been picked up here.
|
||||
return if (!$e->{profile});
|
||||
|
||||
# just convert new null profile style names to old before we begin processing
|
||||
# profile and name can contain multiple layers of null- but all we care about
|
||||
# currently is single level.
|
||||
@@ -2906,7 +2966,7 @@ sub add_event_to_tree ($) {
|
||||
}
|
||||
$pid{$child} = $arrayref;
|
||||
push @{$arrayref}, [ "fork", $child, $profile, $hat ];
|
||||
} elsif ($e->{operation} =~ m/socket_/) {
|
||||
} elsif (optype($e->{operation}) eq "net") {
|
||||
add_to_tree( $e->{pid},
|
||||
$e->{parent},
|
||||
"netdomain",
|
||||
@@ -5572,7 +5632,7 @@ sub var_transform($) {
|
||||
sub writelistvars ($$) {
|
||||
my ($prof_data, $depth) = @_;
|
||||
|
||||
return write_pair($prof_data, $depth, '', 'lvar', "", " = ", ",", \&var_transform);
|
||||
return write_pair($prof_data, $depth, '', 'lvar', "", " = ", "", \&var_transform);
|
||||
}
|
||||
|
||||
sub writecap_rules ($$$) {
|
||||
@@ -6610,7 +6670,7 @@ sub parse_event($) {
|
||||
LibAppArmor::aa_log_record::swig_magic_token_get($event);
|
||||
|
||||
# NetDomain
|
||||
if ( $ev{'operation'} && $ev{'operation'} =~ /socket/ ) {
|
||||
if ( $ev{'operation'} && optype($ev{'operation'}) eq "net" ) {
|
||||
$ev{'family'} =
|
||||
LibAppArmor::aa_log_record::swig_net_family_get($event);
|
||||
$ev{'protocol'} =
|
||||
@@ -6622,10 +6682,14 @@ sub parse_event($) {
|
||||
LibAppArmor::free_record($event);
|
||||
|
||||
#map new c and d to w as logprof doesn't support them yet
|
||||
$rmask =~ s/c/w/g;
|
||||
$rmask =~ s/d/w/g;
|
||||
$dmask =~ s/c/w/g;
|
||||
$dmask =~ s/d/w/g;
|
||||
if ($rmask) {
|
||||
$rmask =~ s/c/w/g;
|
||||
$rmask =~ s/d/w/g;
|
||||
}
|
||||
if ($dmask) {
|
||||
$dmask =~ s/c/w/g;
|
||||
$dmask =~ s/d/w/g;
|
||||
}
|
||||
|
||||
if ($rmask && !validate_log_mode(hide_log_mode($rmask))) {
|
||||
fatal_error(sprintf(gettext('Log contains unknown mode %s.'),
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
|
||||
|
||||
=pod
|
||||
@@ -113,12 +112,12 @@ if the apparmor control files aren't available under /sys/kernel/security/.
|
||||
if the user running the script doesn't have enough privileges to read
|
||||
the apparmor control files.
|
||||
|
||||
If you find any additional bugs, please report them to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any additional bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -15,12 +15,12 @@ In this mode security policy is enforced and all access (successes and failures)
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa-complain(1), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa-complain(1), aa_change_hat(2),
|
||||
and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -43,11 +42,12 @@ recursively calling ldd(1) on the executables listed on the command line.
|
||||
|
||||
This program does not perform full static analysis of executables, so
|
||||
the profiles generated are necessarily incomplete. If you find any bugs,
|
||||
please report them to bugzilla at L<http://bugzilla.novell.com>.
|
||||
please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa-complain(1), aa-enforce(1), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-complain(1), aa-enforce(1), aa_change_hat(2),
|
||||
and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -38,12 +37,12 @@ to the system log.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa_change_hat(2), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -41,12 +40,12 @@ be run to change this behavior.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa-complain(1), change_hat(2), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-complain(1), aa_change_hat(2), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -52,7 +52,7 @@ GetOptions(
|
||||
|
||||
my $sd_mountpoint = check_for_subdomain();
|
||||
unless ($sd_mountpoint) {
|
||||
fatal_error(gettext("SubDomain does not appear to be started. Please enable SubDomain and try again."));
|
||||
fatal_error(gettext("SubDomain does not appear to be started. Please enable SubDomain and try again."));
|
||||
}
|
||||
|
||||
# let's convert it to full path...
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -61,7 +60,7 @@ to add to profile and (F)inish.
|
||||
|
||||
If the user selects (S)can or hits return, aa-genprof will parse
|
||||
the complain mode logs and iterate through generated violations
|
||||
using logprof(1).
|
||||
using aa-logprof(1).
|
||||
|
||||
After the user finishes selecting profile entries based on violations
|
||||
that were detected during the program execution, aa-genprof will reload
|
||||
@@ -74,13 +73,12 @@ and any other profiles that were generated, into enforce mode and exit.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa-complain(1), change_hat(2),
|
||||
aa-logprof(1), logprof.conf(5), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa-complain(1), aa_change_hat(2),
|
||||
aa-logprof(1), logprof.conf(5), and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -25,11 +24,11 @@
|
||||
=head1 NAME
|
||||
|
||||
logprof.conf - configuration file for expert options that modify the
|
||||
behavior of the AppArmor logprof(1) program.
|
||||
behavior of the AppArmor aa-logprof(1) program.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The logprof(1) program can be configured to have certain default behavior
|
||||
The aa-logprof(1) program can be configured to have certain default behavior
|
||||
by the contents of logprof.conf.
|
||||
|
||||
The B<[qualifiers]> section lists specific programs that should have
|
||||
@@ -56,7 +55,7 @@ If the user is doing something tricky and wants different behavior,
|
||||
they can tweak or remove the corresponding line in the conf file.
|
||||
|
||||
The B<[defaulthat]> section lists changehat-aware programs and what hat
|
||||
logprof(1) will collapse the entries to for that program if the user
|
||||
aa-logprof(1) will collapse the entries to for that program if the user
|
||||
specifies that the access should be allowed, but should not have it's
|
||||
own hat.
|
||||
|
||||
@@ -65,7 +64,7 @@ with respect to globbing suggestions that the user will be prompted with.
|
||||
|
||||
The format of each line is-- "<perl glob> = <apparmor glob>".
|
||||
|
||||
When logprof(1) asks about a specific path, if the perl glob matches the
|
||||
When aa-logprof(1) asks about a specific path, if the perl glob matches the
|
||||
path, it replaces the part of the path that matched with the corresponding
|
||||
apparmor glob and adds it to the list of globbing suggestions.
|
||||
|
||||
@@ -104,13 +103,13 @@ Lines starting with # are comments and are ignored.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), enforce(1), change_hat(2),
|
||||
complain(1), logprof(1), genprof(1), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), apparmor.d(5), aa-enforce(1), aa_change_hat(2),
|
||||
aa-complain(1), aa-logprof(1), aa-genprof(1), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,23 +1,22 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
#
|
||||
# This publication is intellectual property of Novell Inc. and Canonical
|
||||
# Ltd. Its contents can be duplicated, either in part or in whole, provided
|
||||
# that a copyright label is visibly located on each copy.
|
||||
#
|
||||
# All information found in this book has been compiled with utmost
|
||||
# attention to detail. However, this does not guarantee complete accuracy.
|
||||
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Neither SUSE LINUX GmbH, Canonical Ltd, the authors, nor the translators
|
||||
# shall be held liable for possible errors or the consequences thereof.
|
||||
#
|
||||
# Many of the software and hardware descriptions cited in this book
|
||||
# are registered trademarks. All trade names are subject to copyright
|
||||
# restrictions and may be registered trade marks. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
#
|
||||
# and Canonical Ltd. essentially adhere to the manufacturer's spelling.
|
||||
#
|
||||
# Names of products and trademarks appearing in this book (with or without
|
||||
# specific notation) are likewise subject to trademark and trade protection
|
||||
# laws and may thus fall under copyright restrictions.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
#
|
||||
|
||||
|
||||
=pod
|
||||
@@ -142,7 +141,7 @@ aa-logprof will never suggest "ux" as the default.
|
||||
|
||||
=head2 ChangeHat Events
|
||||
|
||||
If unknown change_hat(2) events are found, the user is prompted to add a new
|
||||
If unknown aa_change_hat(2) events are found, the user is prompted to add a new
|
||||
hat, if the events should go into the default hat for this profile based
|
||||
on the corresponding entry in the defaulthat section of logprof.conf,
|
||||
or if the following events that run under that hat should be denied
|
||||
@@ -156,13 +155,13 @@ user wants to quit. See capability(7) for details.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None. Please report any you find to bugzilla at
|
||||
L<http://bugzilla.novell.com>.
|
||||
If you find any bugs, please report them at
|
||||
L<http://https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
klogd(8), auditd(8), apparmor(7), apparmor.d(5), change_hat(2),
|
||||
klogd(8), auditd(8), apparmor(7), apparmor.d(5), aa_change_hat(2),
|
||||
logprof.conf(5), aa-genprof(1), aa-complain(1), aa-enforce(1), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -14,10 +14,6 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../genprof:55
|
||||
msgid "SubDomain does not appear to be started. Please enable SubDomain and try again."
|
||||
msgstr "Dit lyk nie asof SubDomain begin het nie. Ontsper SubDomain asseblief en probeer weer."
|
||||
|
||||
#: ../genprof:69
|
||||
msgid "Please enter the program to profile: "
|
||||
msgstr "Voer asseblief die program na profiel toe in:"
|
||||
@@ -762,11 +758,6 @@ msgstr "Fatal Error. No directory, %s, found. Exiting."
|
||||
msgid "Fatal Error. Couldn't open %s. Exiting"
|
||||
msgstr "Fatal Error. Couldn't open %s. Exiting"
|
||||
|
||||
#: ../Reports.pm:970 ../Reports.pm:983 ../Reports.pm:991
|
||||
#, perl-format
|
||||
msgid "DBI Execution failed: %s"
|
||||
msgstr "DBI Execution failed: %s"
|
||||
|
||||
#: ../Reports.pm:1592
|
||||
#, perl-format
|
||||
msgid "Fatal Error. getArchReport() couldn't open %s"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user