mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-30 13:58:22 +00:00
Merge remote-tracking branch 'origin/master' into prepare-rc.apparmor.functions-for-Debian-and-Ubuntu
This commit is contained in:
6
Makefile
6
Makefile
@@ -54,12 +54,12 @@ snapshot: clean
|
||||
.PHONY: coverity
|
||||
coverity: snapshot
|
||||
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
|
||||
$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
||||
cov-build --dir $(COVERITY_DIR) -- $(MAKE) -C $(SNAPSHOT_NAME)/$(dir); \
|
||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-$(subst /,.,$(dir)).txt ;)
|
||||
$(foreach dir, libraries/libapparmor utils, \
|
||||
cov-build --dir $(COVERITY_DIR) --no-command --fs-capture-search $(SNAPSHOT_NAME)/$(dir); \
|
||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
|
||||
cov-build --dir $(COVERITY_DIR) -- sh -c \
|
||||
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
||||
$(MAKE) -C $(SNAPSHOT_NAME)/$(dir);) "
|
||||
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
||||
|
||||
.PHONY: export_dir
|
||||
|
@@ -139,7 +139,7 @@ them at L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
apparmor(7), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -30,7 +30,7 @@ SYSTEMD_UNIT_DIR=${DESTDIR}/usr/lib/systemd/system
|
||||
CONFDIR=/etc/apparmor
|
||||
INSTALL_CONFDIR=${DESTDIR}${CONFDIR}
|
||||
LOCALEDIR=/usr/share/locale
|
||||
MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 subdomain.conf.5 aa-teardown.8
|
||||
MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 aa-teardown.8
|
||||
|
||||
YACC := bison
|
||||
YFLAGS := -d
|
||||
@@ -72,9 +72,6 @@ endif
|
||||
# Internationalization support. Define a package and a LOCALEDIR
|
||||
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
||||
|
||||
# Compile-time configuration of the location of the config file
|
||||
EXTRA_CFLAGS+=-DSUBDOMAIN_CONFDIR=\"${CONFDIR}\"
|
||||
|
||||
SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
|
||||
parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
|
||||
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
|
||||
@@ -373,7 +370,6 @@ install-arch: $(INSTALLDEPS)
|
||||
.PHONY: install-indep
|
||||
install-indep: indep
|
||||
install -m 755 -d $(INSTALL_CONFDIR)
|
||||
install -m 644 subdomain.conf $(INSTALL_CONFDIR)
|
||||
install -m 644 parser.conf $(INSTALL_CONFDIR)
|
||||
install -m 755 -d ${DESTDIR}/var/lib/apparmor
|
||||
install -m 755 -d $(APPARMOR_BIN_PREFIX)
|
||||
|
@@ -143,6 +143,56 @@ messages with the KERN facility. Thus, REJECTING and PERMITTING messages
|
||||
may go to either F</var/log/audit/audit.log> or F</var/log/messages>,
|
||||
depending upon local configuration.
|
||||
|
||||
=head1 DEBUGGING
|
||||
|
||||
AppArmor provides a few facilities to log more information,
|
||||
which can help debugging profiles.
|
||||
|
||||
=head2 Enable debug mode
|
||||
|
||||
When debug mode is enabled, AppArmor will log a few extra messages to
|
||||
dmesg (not via the audit subsystem). For example, the logs will tell
|
||||
whether environment scrubbing has been applied.
|
||||
|
||||
To enable debug mode, run:
|
||||
|
||||
echo 1 > /sys/module/apparmor/parameters/debug
|
||||
|
||||
=head2 Turn off deny audit quieting
|
||||
|
||||
By default, operations that trigger C<deny> rules are not logged.
|
||||
This is called I<deny audit quieting>.
|
||||
|
||||
To turn off deny audit quieting, run:
|
||||
|
||||
echo -n noquiet >/sys/module/apparmor/parameters/audit
|
||||
|
||||
=head2 Force audit mode
|
||||
|
||||
AppArmor can log a message for every operation that triggers a rule
|
||||
configured in the policy. This is called I<force audit mode>.
|
||||
|
||||
B<Warning!> Force audit mode can be extremely noisy even for a single profile,
|
||||
let alone when enabled globally.
|
||||
|
||||
To set a specific profile in force audit mode, add the C<audit> flag:
|
||||
|
||||
profile foo flags=(audit) { ... }
|
||||
|
||||
To enable force audit mode globally, run:
|
||||
|
||||
echo -n all > /sys/module/apparmor/parameters/audit
|
||||
|
||||
If auditd is not running, to avoid losing too many of the extra log
|
||||
messages, you will likely have to turn off rate limiting by doing:
|
||||
|
||||
echo 0 > /proc/sys/kernel/printk_ratelimit
|
||||
|
||||
But even then the kernel ring buffer may overflow and you might
|
||||
lose messages.
|
||||
|
||||
Else, if auditd is running, see auditd(8) and auditd.conf(5).
|
||||
|
||||
=head1 FILES
|
||||
|
||||
=over 4
|
||||
@@ -162,7 +212,7 @@ depending upon local configuration.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor_parser(8), aa_change_hat(2), apparmor.d(5),
|
||||
subdomain.conf(5), aa-autodep(1), clean(1),
|
||||
aa-autodep(1), clean(1),
|
||||
auditd(8),
|
||||
aa-unconfined(8), aa-enforce(1), aa-complain(1), and
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
@@ -179,7 +179,7 @@ defined as relative paths.
|
||||
Add element n to the search path when resolving #include directives
|
||||
defined as an absolute paths.
|
||||
|
||||
=item -f n, --subdomainfs n
|
||||
=item -f n, --apparmorfs n
|
||||
|
||||
Set the location of the apparmor security filesystem (default is
|
||||
"/sys/kernel/security/apparmor").
|
||||
@@ -408,7 +408,7 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), subdomain.conf(5), aa_change_hat(2), and
|
||||
apparmor(7), apparmor.d(5), aa_change_hat(2), and
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -549,9 +549,14 @@ static void count_tree_nodes(Node *t, struct node_counts *counts)
|
||||
#include "stdint.h"
|
||||
#include "apparmor_re.h"
|
||||
|
||||
// maximum number of passes to iterate on the expression tree doing
|
||||
// simplification passes. Simplification may exit sooner if no changes
|
||||
// are made.
|
||||
#define MAX_PASSES 1
|
||||
Node *simplify_tree(Node *t, dfaflags_t flags)
|
||||
{
|
||||
bool update;
|
||||
bool update = true;
|
||||
int i;
|
||||
|
||||
if (flags & DFA_DUMP_TREE_STATS) {
|
||||
struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -562,7 +567,7 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
||||
counts.alt, counts.plus, counts.star, counts.any,
|
||||
counts.cat);
|
||||
}
|
||||
do {
|
||||
for (i = 0; update && i < MAX_PASSES; i++) {
|
||||
update = false;
|
||||
//default to right normalize first as this reduces the number
|
||||
//of trailing nodes which might follow an internal *
|
||||
@@ -588,7 +593,7 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
||||
else
|
||||
dir--;
|
||||
}
|
||||
} while (update);
|
||||
}
|
||||
if (flags & DFA_DUMP_TREE_STATS) {
|
||||
struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
count_tree_nodes(t, &counts);
|
||||
|
@@ -116,13 +116,34 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* See the "Dragon Book" for an explanation of nullable, firstpos,
|
||||
* lastpos, and followpos.
|
||||
* firstpos, lastpos, and followpos are used to convert the syntax tree
|
||||
* to a DFA.
|
||||
*
|
||||
* firstpos holds nodes that can match the first character of a string
|
||||
* that matches the syntax tree. For the regex 'a*bcd', firstpos holds
|
||||
* the 'a' and 'b' nodes. firstpos is used to determine the start state
|
||||
* of the DFA.
|
||||
*
|
||||
* lastpos is the same as firstpos for the last character. For the regex
|
||||
* 'a*bcd', lastpos holds the 'd' node. lastpos is used to determine the
|
||||
* accepting states of the DFA.
|
||||
*
|
||||
* followpos holds the set of nodes that can match a character directly
|
||||
* after the current node. For the regexp 'a*bcd', the followpos of the
|
||||
* 'a' node are the 'b' node and the 'a' node itself. followpos is used
|
||||
* to determine the transitions of the DFA.
|
||||
*
|
||||
* nullable indicates that a node can match the empty string. It is used
|
||||
* to compute firstpos and lastpos.
|
||||
*
|
||||
* See the "Dragon Book" 2nd Edition section 3.9.2 for an in-depth
|
||||
* explanation.
|
||||
*/
|
||||
virtual void compute_nullable() { }
|
||||
virtual void compute_firstpos() = 0;
|
||||
virtual void compute_lastpos() = 0;
|
||||
virtual void compute_followpos() { }
|
||||
|
||||
virtual int eq(Node *other) = 0;
|
||||
virtual ostream &dump(ostream &os) = 0;
|
||||
void dump_syntax_tree(ostream &os);
|
||||
|
@@ -17,21 +17,21 @@
|
||||
* along with this program; if not, contact Canonical, Ltd.
|
||||
*/
|
||||
|
||||
/* Handle subdomain includes, as a straight forward preprocessing phase.
|
||||
/* Handle apparmor includes, as a straight forward preprocessing phase.
|
||||
While we are at it we will strip comments. Why? because it made it
|
||||
easier.
|
||||
|
||||
We support 2 types of includes
|
||||
|
||||
#include <name> which searches for the first occurance of name in the
|
||||
subdomain directory path.
|
||||
apparmor directory path.
|
||||
|
||||
#include "name" which will search for a relative or absolute pathed
|
||||
file
|
||||
|
||||
-p : preprocess only. Dump output to stdout
|
||||
-I path : add a path to be search by #include < >
|
||||
-b path : set the base path to something other than /etc/subdomain.d
|
||||
-b path : set the base path to something other than /etc/apparmor.d
|
||||
|
||||
*/
|
||||
|
||||
@@ -57,13 +57,6 @@
|
||||
/* maximum depth of nesting */
|
||||
#define MAX_NEST_LEVEL 100
|
||||
|
||||
/* Location of the subdomain.conf file */
|
||||
#ifdef SUBDOMAIN_CONFDIR
|
||||
#define SUBDOMAIN_CONF SUBDOMAIN_CONFDIR "/subdomain.conf"
|
||||
#else /* !defined SUBDOMAIN_CONFDIR */
|
||||
#define SUBDOMAIN_CONF "/etc/subdomain.conf"
|
||||
#endif /* SUBDOMAIN_CONFDIR */
|
||||
|
||||
static char *path[MAX_PATH] = { NULL };
|
||||
static int npath = 0;
|
||||
|
||||
@@ -71,12 +64,11 @@ static int fgetline(FILE * f, char *buffer, size_t len);
|
||||
static int stripcomment(char *s);
|
||||
static char *stripblanks(char *s);
|
||||
|
||||
/* default base directory is /etc/subdomain.d, it can be overriden
|
||||
/* default base directory is /etc/apparmor.d, it can be overriden
|
||||
with the -b option. */
|
||||
|
||||
const char *basedir;
|
||||
static const char *default_basedir = "/etc/apparmor.d";
|
||||
static const char *old_basedir = "/etc/subdomain.d";
|
||||
|
||||
|
||||
/* set up basedir so that it can be overridden/used later. */
|
||||
@@ -94,12 +86,6 @@ void init_base_dir(void)
|
||||
basedir = default_basedir;
|
||||
return;
|
||||
}
|
||||
|
||||
rc = stat(old_basedir, &sbuf);
|
||||
if (rc == 0 && S_ISDIR(sbuf.st_mode)) {
|
||||
basedir = old_basedir;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the base dir. Used to change default path for relative includes */
|
||||
@@ -164,53 +150,9 @@ int add_search_dir(const char *dir)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse Subdomain.conf and put the default dirs in place.
|
||||
|
||||
subdomain.conf is a shell sourcable file
|
||||
we only parse entries starting with
|
||||
SUBDOMAIN_PATH=
|
||||
|
||||
if there are multiple entries with SUBDOMAIN_PATH=
|
||||
each will get added.
|
||||
|
||||
SUBDOMAIN_PATH=/etc/subdomain.d:/etc/subdomain.d/include
|
||||
is the same as
|
||||
SUBDOMAIN_PATH=/etc/subdomain.d
|
||||
SUBDOMAIN_PATH=/etc/subdomain.d/include */
|
||||
void parse_default_paths(void)
|
||||
{
|
||||
autofclose FILE *f;
|
||||
char buf[1024];
|
||||
char *t, *s;
|
||||
int saved_npath = npath;
|
||||
|
||||
f = fopen(SUBDOMAIN_CONF, "r");
|
||||
if (f == NULL)
|
||||
goto out;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
while (fgetline(f, buf, 1024)) {
|
||||
if (stripcomment(buf) && (t = strstr(buf, "SUBDOMAIN_PATH="))) {
|
||||
t += 15;
|
||||
/* handle : separating path elements */
|
||||
do {
|
||||
s = strchr(t, ':');
|
||||
if (s)
|
||||
*s = 0;
|
||||
if (!add_search_dir(stripblanks(t)))
|
||||
break;
|
||||
if (s)
|
||||
t = s + 1;
|
||||
} while (s != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* if subdomain.conf doesn't set a base search dir set it to this */
|
||||
out:
|
||||
if (npath - saved_npath == 0) {
|
||||
add_search_dir(basedir);
|
||||
}
|
||||
add_search_dir(basedir);
|
||||
}
|
||||
|
||||
FILE *search_path(char *filename, char **fullpath)
|
||||
|
@@ -33,27 +33,12 @@
|
||||
|
||||
CONFIG_DIR=/etc/apparmor
|
||||
MODULE=apparmor
|
||||
OLD_MODULE=subdomain
|
||||
if [ -f "${CONFIG_DIR}/${MODULE}.conf" ] ; then
|
||||
APPARMOR_CONF="${CONFIG_DIR}/${MODULE}.conf"
|
||||
elif [ -f "${CONFIG_DIR}/${OLD_MODULE}.conf" ] ; then
|
||||
APPARMOR_CONF="${CONFIG_DIR}/${OLD_MODULE}.conf"
|
||||
elif [ -f "/etc/immunix/subdomain.conf" ] ; then
|
||||
aa_log_warning_msg "/etc/immunix/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
|
||||
APPARMOR_CONF="/etc/immunix/subdomain.conf"
|
||||
elif [ -f "/etc/subdomain.conf" ] ; then
|
||||
aa_log_warning_msg "/etc/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
|
||||
APPARMOR_CONF="/etc/subdomain.conf"
|
||||
else
|
||||
aa_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
|
||||
fi
|
||||
|
||||
# Read configuration options from /etc/subdomain.conf, default is to
|
||||
# warn if subdomain won't load.
|
||||
SUBDOMAIN_MODULE_PANIC="warn"
|
||||
SUBDOMAIN_ENABLE_OWLSM="no"
|
||||
APPARMOR_ENABLE_AAEVENTD="no"
|
||||
|
||||
if [ -f "${APPARMOR_CONF}" ] ; then
|
||||
#parse the conf file to see what we should do
|
||||
. "${APPARMOR_CONF}"
|
||||
@@ -66,15 +51,11 @@ if [ "${QUIET:-no}" = yes ] || [ "${quiet:-n}" = y ]; then
|
||||
PARSER_OPTS="$PARSER_OPTS --quiet"
|
||||
fi
|
||||
|
||||
# SUBDOMAIN_DIR and APPARMOR_DIR might be defined in subdomain.conf|apparmor.conf
|
||||
# APPARMOR_DIR might be defined in apparmor.conf
|
||||
if [ -d "${APPARMOR_DIR}" ] ; then
|
||||
PROFILE_DIRS=${APPARMOR_DIR}
|
||||
elif [ -d "${SUBDOMAIN_DIR}" ] ; then
|
||||
PROFILE_DIRS=${SUBDOMAIN_DIR}
|
||||
elif [ -d /etc/apparmor.d ] ; then
|
||||
PROFILE_DIRS=/etc/apparmor.d
|
||||
elif [ -d /etc/subdomain.d ] ; then
|
||||
PROFILE_DIRS=/etc/subdomain.d
|
||||
else
|
||||
aa_log_warning_msg "Unable to find profiles directory, installation problem?"
|
||||
fi
|
||||
@@ -82,17 +63,9 @@ ADDITIONAL_PROFILE_DIR=/var/lib/snapd/apparmor/profiles
|
||||
if [ -d "$ADDITIONAL_PROFILE_DIR" ]; then
|
||||
PROFILE_DIRS="${PROFILE_DIRS} ${ADDITIONAL_PROFILE_DIR}"
|
||||
fi
|
||||
AA_EV_BIN=/usr/sbin/aa-eventd
|
||||
AA_EV_PIDFILE=/var/run/aa-eventd.pid
|
||||
AA_STATUS=/usr/sbin/aa-status
|
||||
SD_EV_BIN=/usr/sbin/sd-event-dispatch.pl
|
||||
SD_EV_PIDFILE=/var/run/sd-event-dispatch.init.pid
|
||||
SD_STATUS=/usr/sbin/subdomain_status
|
||||
SECURITYFS=/sys/kernel/security
|
||||
|
||||
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
|
||||
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
|
||||
|
||||
# keep exit status from parser during profile load. 0 is good, 1 is bad
|
||||
STATUS=0
|
||||
|
||||
@@ -106,9 +79,6 @@ is_apparmor_present() {
|
||||
shift
|
||||
done
|
||||
|
||||
# check for subdomainfs version of module
|
||||
grep -qE "^($modules)[[:space:]]" /proc/modules
|
||||
|
||||
[ $? -ne 0 -a -d /sys/module/apparmor ]
|
||||
|
||||
return $?
|
||||
@@ -170,6 +140,8 @@ skip_profile() {
|
||||
local profile=$1
|
||||
if [ "${profile%.rpmnew}" != "${profile}" -o \
|
||||
"${profile%.rpmsave}" != "${profile}" -o \
|
||||
"${profile%.orig}" != "${profile}" -o \
|
||||
"${profile%.rej}" != "${profile}" -o \
|
||||
"${profile%\~}" != "${profile}" ] ; then
|
||||
return 1
|
||||
fi
|
||||
@@ -306,24 +278,10 @@ failstop_system() {
|
||||
if [ $level -ne "1" ] ; then
|
||||
aa_log_failure_msg "- could not start AppArmor. Changing to runlevel 1"
|
||||
telinit 1;
|
||||
return -1;
|
||||
return 255;
|
||||
fi
|
||||
aa_log_failure_msg "- could not start AppArmor."
|
||||
return -1
|
||||
}
|
||||
|
||||
module_panic() {
|
||||
# the module failed to load, determine what action should be taken
|
||||
|
||||
case "$SUBDOMAIN_MODULE_PANIC" in
|
||||
"warn"|"WARN")
|
||||
return 1 ;;
|
||||
"panic"|"PANIC") failstop_system
|
||||
rc=$?
|
||||
return $rc ;;
|
||||
*) aa_log_failure_msg "- invalid AppArmor module fail option"
|
||||
return -1 ;;
|
||||
esac
|
||||
return 255
|
||||
}
|
||||
|
||||
is_apparmor_loaded() {
|
||||
@@ -331,25 +289,12 @@ is_apparmor_loaded() {
|
||||
mount_securityfs
|
||||
fi
|
||||
|
||||
mount_subdomainfs
|
||||
|
||||
if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
|
||||
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -f "${SECURITYFS}/${OLD_MODULE}/profiles" ]; then
|
||||
SFS_MOUNTPOINT="${SECURITYFS}/${OLD_MODULE}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -f "${SUBDOMAINFS_MOUNTPOINT}/profiles" ]; then
|
||||
SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT}
|
||||
return 0
|
||||
fi
|
||||
|
||||
# check for subdomainfs version of module
|
||||
is_apparmor_present apparmor subdomain
|
||||
is_apparmor_present apparmor
|
||||
|
||||
return $?
|
||||
}
|
||||
@@ -368,62 +313,16 @@ mount_securityfs() {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
mount_subdomainfs() {
|
||||
# for backwords compatibility
|
||||
if grep -q subdomainfs /proc/filesystems && \
|
||||
! grep -q subdomainfs /proc/mounts && \
|
||||
[ -n "${SUBDOMAINFS_MOUNTPOINT}" ]; then
|
||||
aa_action "Mounting subdomainfs on ${SUBDOMAINFS_MOUNTPOINT}" \
|
||||
mount "${SUBDOMAINFS_MOUNTPOINT}"
|
||||
return $?
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
unmount_subdomainfs() {
|
||||
SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null)
|
||||
if [ -n "${SUBDOMAINFS}" ]; then
|
||||
aa_action "Unmounting subdomainfs" umount ${SUBDOMAINFS}
|
||||
fi
|
||||
}
|
||||
|
||||
load_module() {
|
||||
local rc=0
|
||||
if modinfo -F filename apparmor > /dev/null 2>&1 ; then
|
||||
MODULE=apparmor
|
||||
elif modinfo -F filename ${OLD_MODULE} > /dev/null 2>&1 ; then
|
||||
MODULE=${OLD_MODULE}
|
||||
fi
|
||||
|
||||
if ! is_apparmor_present apparmor subdomain ; then
|
||||
aa_action "Loading AppArmor module" /sbin/modprobe -q $MODULE $1
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ] ; then
|
||||
module_panic
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ] ; then
|
||||
exit $rc
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! is_apparmor_loaded ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
apparmor_start() {
|
||||
aa_log_daemon_msg "Starting AppArmor"
|
||||
if ! is_apparmor_loaded ; then
|
||||
load_module
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ] ; then
|
||||
aa_log_end_msg $rc
|
||||
return $rc
|
||||
fi
|
||||
if ! is_apparmor_present ; then
|
||||
aa_log_failure_msg "Starting AppArmor - failed, To enable AppArmor, ensure your kernel is configured with CONFIG_SECURITY_APPARMOR=y then add 'security=apparmor apparmor=1' to the kernel command line"
|
||||
aa_log_end_msg 1
|
||||
return 1
|
||||
elif ! is_apparmor_loaded ; then
|
||||
aa_log_failure_msg "Starting AppArmor - AppArmor control files aren't available under /sys/kernel/security/, please make sure securityfs is mounted."
|
||||
aa_log_end_msg 1
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
|
||||
@@ -447,7 +346,7 @@ apparmor_start() {
|
||||
|
||||
remove_profiles() {
|
||||
|
||||
# removing profiles as we directly read from subdomainfs
|
||||
# removing profiles as we directly read from apparmorfs
|
||||
# doesn't work, since we are removing entries which screws up
|
||||
# our position. Lets hope there are never enough profiles to
|
||||
# overflow the variable
|
||||
@@ -495,11 +394,8 @@ apparmor_kill() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
unmount_subdomainfs
|
||||
if is_apparmor_present apparmor ; then
|
||||
MODULE=apparmor
|
||||
elif is_apparmor_present subdomain ; then
|
||||
MODULE=subdomain
|
||||
else
|
||||
aa_log_failure_msg "AppArmor is builtin"
|
||||
return 1
|
||||
@@ -546,27 +442,11 @@ apparmor_try_restart() {
|
||||
return $?
|
||||
}
|
||||
|
||||
configure_owlsm () {
|
||||
if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then
|
||||
# Sigh, the "sh -c" is necessary for the SuSE aa_action
|
||||
# and it can't be abstracted out as a seperate function, as
|
||||
# that breaks under RedHat's action, which needs a
|
||||
# binary to invoke.
|
||||
aa_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
|
||||
elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then
|
||||
aa_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
|
||||
fi
|
||||
}
|
||||
|
||||
apparmor_status () {
|
||||
if test -x ${AA_STATUS} ; then
|
||||
${AA_STATUS} --verbose
|
||||
return $?
|
||||
fi
|
||||
if test -x ${SD_STATUS} ; then
|
||||
${SD_STATUS} --verbose
|
||||
return $?
|
||||
fi
|
||||
if ! is_apparmor_loaded ; then
|
||||
echo "AppArmor is not loaded."
|
||||
rc=1
|
||||
|
@@ -1,53 +0,0 @@
|
||||
# subdomain.conf is a shared AppArmor configuration file that is sh sourcable.
|
||||
|
||||
################## AppArmor init.d configuration ################
|
||||
|
||||
# Move this to /etc/sysconfig/apparmor eventually
|
||||
## Path: System/AppArmor
|
||||
## Description: Enable the OWLSM extension to AppArmor
|
||||
## Type: yesno
|
||||
## Default: no
|
||||
#
|
||||
# Enable OWLSM extension to AppArmor?
|
||||
# OWLSM is an extension to AppArmor that prevents processes from
|
||||
# following symlinks they don't own and creating hardlinks to files they
|
||||
# don't own, in an attempt to prevent /tmp race attacks. However, OWLSM
|
||||
# can break some applications, so is disabled by default.
|
||||
SUBDOMAIN_ENABLE_OWLSM="no"
|
||||
|
||||
## Path: System/AppArmor
|
||||
## Description: Enable the AppArmor event daemon for reporting
|
||||
## Type: yesno
|
||||
## Default: no
|
||||
#
|
||||
# Enable the AppArmor event daemon for reporting?
|
||||
APPARMOR_ENABLE_AAEVENTD="no"
|
||||
|
||||
#SUBDOMAIN_MODULE_PANIC=XXX
|
||||
#This option controls how subdomain behaves when the init script attempts
|
||||
#to load the AppArmor module and fails. There are 4 options
|
||||
#warn - log a failure message. (default behavior)
|
||||
#build - attempt to build the AppArmor module is the module can't be loaded.
|
||||
# If successful
|
||||
# the module will be built for the running kernel and loaded.
|
||||
# If the build fails
|
||||
# a failure message is logged
|
||||
#panic - If the AppArmor module fails to load
|
||||
# a failure message will be logged
|
||||
# and the machine will drop to runlevel 1 (single user)
|
||||
#build-panic - If the AppArmor module fails to load
|
||||
# attempt to build the module
|
||||
# If building the module fails
|
||||
# panic (drop to runlevel 1)
|
||||
|
||||
#SUBDOMAIN_MODULE_PANIC=warn
|
||||
|
||||
################## subdomain_parser configuration ################
|
||||
|
||||
#SUBDOMAIN_PATH=XXXX
|
||||
#This option specifies the include path that the subdomain_parser will
|
||||
#use by default. If no entry is specified /etc/subdomain.d is used by
|
||||
#default.
|
||||
|
||||
#SUBDOMAIN_PATH=/etc/subdomain.d
|
||||
|
@@ -1,104 +0,0 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) 2010 - 2012
|
||||
# Canonical Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
/etc/apparmor/subdomain.conf - configuration file for fine-tuning the
|
||||
behavior of the AppArmor security tool.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The AppArmor security tool can be configured to have
|
||||
certain default behaviors based on configuration options set
|
||||
in subdomain.conf. There are two variables that can be set in
|
||||
subdomain.conf: B<SUBDOMAIN_PATH>, and B<SUBDOMAIN_MODULE_PANIC>.
|
||||
|
||||
=begin comment
|
||||
|
||||
FIXME keep quiet about OWLSM support for now.
|
||||
|
||||
=head2 SUBDOMAIN_ENABLE_OWLSM
|
||||
|
||||
This veriable is a yes/no toggle and is by default set to I<no>.
|
||||
|
||||
This variable determines whether the AppArmor initscript will enable
|
||||
or disable the OWLsm security extension to AppArmor when the AppArmor
|
||||
security tool is started. When enabled the OWLsm feature prevents programs
|
||||
from following symlinks in temporary directories that are not owned by
|
||||
the program's UID, and prevents processes from creating hardlinks to
|
||||
files not owned by their UID.
|
||||
|
||||
=end comment
|
||||
|
||||
=head2 SUBDOMAIN_PATH
|
||||
|
||||
This variable accepts a string (path), and is by default set to
|
||||
'/etc/apparmor.d/' This variable defines where the AppArmor security
|
||||
tool looks for its policy definitions (a.k.a. AppArmor profiles).
|
||||
|
||||
=head2 SUBDOMAIN_MODULE_PANIC
|
||||
|
||||
This variable accepts a string that is one of four values: I<warn>,
|
||||
I<build>, I<panic>, or I<build-panic>, and is set by default to I<warn>.
|
||||
|
||||
This setting controls the behavior of the AppArmor initscript if it
|
||||
cannot successfully load the AppArmor kernel module on startup. The four
|
||||
possible settings are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<warn>
|
||||
|
||||
Log a failure message (the default behavior).
|
||||
|
||||
=item I<build>
|
||||
|
||||
Attempt to build the AppArmor module against the currently running
|
||||
kernel. If the compilation is successful, the module will be loaded and
|
||||
AppArmor started; if the compilation fails, a failure message is logged.
|
||||
|
||||
=item I<panic>
|
||||
|
||||
Log a failure message and drop to runlevel 1 (single user).
|
||||
|
||||
=item I<build-panic>
|
||||
|
||||
Attempt to build the module against the running kernel (like I<build>)
|
||||
and if the compilation fails, drop to runlevel 1 (single user).
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
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 at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor_parser(8), and
|
||||
L<https://wiki.apparmor.net>.
|
@@ -131,9 +131,13 @@ sub test_profile {
|
||||
} elsif ($coredump) {
|
||||
ok(0, "$profile: Produced core dump (signal $signal): $description");
|
||||
} elsif ($istodo) {
|
||||
TODO: {
|
||||
local $TODO = "Unfixed testcase.";
|
||||
ok($expass ? !$result : $result, "TODO: $profile: $description");
|
||||
if ($expass != $result) {
|
||||
fail("TODO passed unexpectedly: $profile: $description");
|
||||
} else {
|
||||
TODO: {
|
||||
local $TODO = "Unfixed testcase.";
|
||||
ok($expass ? !$result : $result, "TODO: $profile: $description");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok($expass ? !$result : $result, "$profile: $description");
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
#=DISABLED - results in "superfluous TODO", but fails after removing TODO
|
||||
|
||||
abi < "abi/4.19">,
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
#=DISABLED - results in "superfluous TODO", but fails after removing TODO
|
||||
|
||||
abi < "abi/4.19" >,
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#=DESCRIPTION reference variables in rules that also have alternations
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||
|
||||
@{FOO}=/bar /baz
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#=DESCRIPTION reference variables is null
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
#needs post var expansion check that variable contained a value
|
||||
|
||||
@{FOO}=
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#=DESCRIPTION reference variables is null
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
#needs post var expansion check that variable contained a value
|
||||
|
||||
@{FOO}=
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#
|
||||
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#
|
||||
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/b* px,
|
||||
|
@@ -90,8 +90,8 @@
|
||||
@{PROC}/meminfo r,
|
||||
@{PROC}/stat r,
|
||||
@{PROC}/cpuinfo r,
|
||||
/sys/devices/system/cpu/ r,
|
||||
/sys/devices/system/cpu/online r,
|
||||
@{sys}/devices/system/cpu/ r,
|
||||
@{sys}/devices/system/cpu/online r,
|
||||
|
||||
# glibc's *printf protections read the maps file
|
||||
@{PROC}/@{pid}/{maps,auxv,status} r,
|
||||
|
@@ -4,6 +4,5 @@
|
||||
# needs to enumerate graphic devices (as with drmParsePciDeviceInfo() from
|
||||
# libdrm).
|
||||
|
||||
# TODO: use @{sys} after it's moved into tunables/kernelvars (LP: #1728551)
|
||||
/sys/devices/pci[0-9]*/**/{device,subsystem_device,subsystem_vendor,uevent,vendor} r,
|
||||
@{sys}/devices/pci[0-9]*/**/{device,subsystem_device,subsystem_vendor,uevent,vendor} r,
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
@{PROC}/driver/nvidia/params r,
|
||||
@{PROC}/modules r,
|
||||
|
||||
/sys/devices/system/memory/block_size_bytes r,
|
||||
@{sys}/devices/system/memory/block_size_bytes r,
|
||||
|
||||
owner @{HOME}/.nv/ w,
|
||||
owner @{HOME}/.nv/GLCache/ rw,
|
||||
|
@@ -4,7 +4,7 @@
|
||||
# System files
|
||||
|
||||
/etc/OpenCL/** r,
|
||||
/sys/bus/pci/devices/ r, # libpocl.so -> libhwlock.so, libnvidia-opencl.so, beignet/libcl.so -> libdrm_intel.so
|
||||
/sys/devices/system/node/ r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
/sys/devices/system/node/node[0-9]*/meminfo r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
@{sys}/bus/pci/devices/ r, # libpocl.so -> libhwlock.so, libnvidia-opencl.so, beignet/libcl.so -> libdrm_intel.so
|
||||
@{sys}/devices/system/node/ r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
@{sys}/devices/system/node/node[0-9]*/meminfo r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
|
||||
|
@@ -12,6 +12,6 @@
|
||||
# System files
|
||||
|
||||
/dev/dri/card[0-9]* rw, # beignet/libcl.so
|
||||
/sys/devices/pci[0-9]*/**/{class,config,resource,revision} r, # libcl.so -> libdrm_intel.so -> libpciaccess.so (move to dri-enumerate ?)
|
||||
@{sys}/devices/pci[0-9]*/**/{class,config,resource,revision} r, # libcl.so -> libdrm_intel.so -> libpciaccess.so (move to dri-enumerate ?)
|
||||
/usr/lib/@{multiarch}/beignet/** r,
|
||||
|
||||
|
@@ -16,8 +16,8 @@
|
||||
# libnvidia-opencl.so rules:
|
||||
/dev/nvidia-uvm rw,
|
||||
/dev/nvidia-uvm-tools rw,
|
||||
/sys/devices/pci[0-9]*/**/config r,
|
||||
/sys/devices/system/memory/block_size_bytes r,
|
||||
@{sys}/devices/pci[0-9]*/**/config r,
|
||||
@{sys}/devices/system/memory/block_size_bytes r,
|
||||
/usr/share/nvidia/** r,
|
||||
@{PROC}/devices r,
|
||||
@{PROC}/sys/vm/mmap_min_addr r,
|
||||
|
@@ -11,22 +11,22 @@
|
||||
# System files
|
||||
|
||||
/ r, # libpocl.so -> libhwloc.so
|
||||
/sys/bus/pci/slots/ r, # libpocl.so -> hwloc_topology_load() from libhwloc.so
|
||||
/sys/bus/{cpu,node}/devices/ r, # libpocl.so -> libhwlock.so
|
||||
/sys/class/net/ r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/ r, # for libpocl -> hwloc_linux_lookup_block_class() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/block/*/dev r, # libpocl.so -> hwloc_linux_lookup_host_block_class() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/{class,local_cpus} r, # libpocl.so -> libhwlock.so
|
||||
/sys/devices/pci[0-9]*/*/net/*/address r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
/sys/devices/system/cpu/ r, # libpocl.so -> libnuma.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/cache/index[0-9]*/* r, # libpocl.so -> libhwloc.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/online r, # libpocl.so -> libhwlock.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/topology/* r, # *_siblings, physical_package_id and lot's of others, for libpocl.so -> libhwloc.so
|
||||
/sys/devices/system/cpu/cpufreq/policy[0-9]*/* r, # for clGetPlatformIDs() from libpocl.so
|
||||
/sys/devices/system/cpu/possible r, # libpocl.so -> libhwloc.so
|
||||
/sys/devices/virtual/dmi/id/{,*} r, # libpocl.so -> libhwloc.so
|
||||
/sys/fs/cgroup/cpuset/cpuset.{cpus,mems} r, # libpocl.so -> libhwloc.so
|
||||
/sys/kernel/mm/hugepages{/,/**} r, # libpocl.so -> libhwloc.so
|
||||
@{sys}/bus/pci/slots/ r, # libpocl.so -> hwloc_topology_load() from libhwloc.so
|
||||
@{sys}/bus/{cpu,node}/devices/ r, # libpocl.so -> libhwlock.so
|
||||
@{sys}/class/net/ r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
@{sys}/devices/pci[0-9]*/**/ r, # for libpocl -> hwloc_linux_lookup_block_class() from libhwloc.so
|
||||
@{sys}/devices/pci[0-9]*/**/block/*/dev r, # libpocl.so -> hwloc_linux_lookup_host_block_class() from libhwloc.so
|
||||
@{sys}/devices/pci[0-9]*/**/{class,local_cpus} r, # libpocl.so -> libhwlock.so
|
||||
@{sys}/devices/pci[0-9]*/*/net/*/address r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
@{sys}/devices/system/cpu/ r, # libpocl.so -> libnuma.so
|
||||
@{sys}/devices/system/cpu/cpu[0-9]*/cache/index[0-9]*/* r, # libpocl.so -> libhwloc.so
|
||||
@{sys}/devices/system/cpu/cpu[0-9]*/online r, # libpocl.so -> libhwlock.so
|
||||
@{sys}/devices/system/cpu/cpu[0-9]*/topology/* r, # *_siblings, physical_package_id and lot's of others, for libpocl.so -> libhwloc.so
|
||||
@{sys}/devices/system/cpu/cpufreq/policy[0-9]*/* r, # for clGetPlatformIDs() from libpocl.so
|
||||
@{sys}/devices/system/cpu/possible r, # libpocl.so -> libhwloc.so
|
||||
@{sys}/devices/virtual/dmi/id/{,*} r, # libpocl.so -> libhwloc.so
|
||||
@{sys}/fs/cgroup/cpuset/cpuset.{cpus,mems} r, # libpocl.so -> libhwloc.so
|
||||
@{sys}/kernel/mm/hugepages{/,/**} r, # libpocl.so -> libhwloc.so
|
||||
/usr/share/pocl/** r,
|
||||
/{,var/}run/udev/data/*:* r, # libpocl.so -> hwloc_linux_block_class_fillinfos() from libhwloc.so
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2015 Canonical, Ltd.
|
||||
# Copyright (C) 2015-2018 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
|
||||
@@ -16,9 +16,9 @@
|
||||
capability sys_chroot,
|
||||
|
||||
# postfix's master can send us signals
|
||||
signal receive peer=/usr/lib/postfix/master,
|
||||
signal receive peer=postfix-master,
|
||||
|
||||
unix (send, receive) peer=(label=/usr/lib/postfix/master),
|
||||
unix (send, receive) peer=(label=postfix-master),
|
||||
|
||||
/etc/mailname r,
|
||||
/etc/postfix/*.cf r,
|
||||
@@ -33,3 +33,5 @@
|
||||
/var/spool/postfix/etc/* r,
|
||||
/var/spool/postfix/lib/lib*.so* mr,
|
||||
/var/spool/postfix/lib/@{multiarch}/lib*.so* mr,
|
||||
|
||||
/etc/postfix/dynamicmaps.cf.d/ r,
|
||||
|
@@ -6,6 +6,7 @@
|
||||
# lot of false positives when reading contents of directories)
|
||||
deny @{HOME}/.*history mrwkl,
|
||||
deny @{HOME}/.fetchmail* mrwkl,
|
||||
deny @{HOME}/.mutt** mrwkl,
|
||||
deny @{HOME}/.viminfo* mrwkl,
|
||||
deny @{HOME}/.*~ mrwkl,
|
||||
deny @{HOME}/.*.swp mrwkl,
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <abstractions/private-files>
|
||||
|
||||
# potentially extremely sensitive files
|
||||
audit deny @{HOME}/.aws/{,**} mrwkl,
|
||||
audit deny @{HOME}/.gnupg/{,**} mrwkl,
|
||||
audit deny @{HOME}/.ssh/{,**} mrwkl,
|
||||
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
|
||||
|
@@ -32,3 +32,8 @@
|
||||
/etc/dehydrated/certs/*/cert-*.pem r,
|
||||
/etc/dehydrated/certs/*/chain-*.pem r,
|
||||
/etc/dehydrated/certs/*/fullchain-*.pem r,
|
||||
|
||||
# certbot
|
||||
/etc/letsencrypt/archive/*/cert*.pem r,
|
||||
/etc/letsencrypt/archive/*/chain*.pem r,
|
||||
/etc/letsencrypt/archive/*/fullchain*.pem r,
|
||||
|
@@ -23,3 +23,6 @@
|
||||
|
||||
# dehydrated
|
||||
/etc/dehydrated/certs/*/privkey-*.pem r,
|
||||
|
||||
# certbot / letsencrypt
|
||||
/etc/letsencrypt/archive/*/privkey*.pem r,
|
||||
|
@@ -41,8 +41,8 @@
|
||||
@{PROC}/@{pid}/ r,
|
||||
@{PROC}/@{pid}/fd/ r,
|
||||
@{PROC}/filesystems r,
|
||||
/sys/devices/system/cpu/ r,
|
||||
/sys/devices/system/cpu/** r,
|
||||
@{sys}/devices/system/cpu/ r,
|
||||
@{sys}/devices/system/cpu/** r,
|
||||
/usr/share/** r,
|
||||
/var/lib/dbus/machine-id r,
|
||||
|
||||
@@ -88,8 +88,8 @@
|
||||
@{PROC}/@{pid}/ r,
|
||||
@{PROC}/@{pid}/fd/ r,
|
||||
@{PROC}/filesystems r,
|
||||
/sys/devices/system/cpu/ r,
|
||||
/sys/devices/system/cpu/** r,
|
||||
@{sys}/devices/system/cpu/ r,
|
||||
@{sys}/devices/system/cpu/** r,
|
||||
/usr/share/** r,
|
||||
/var/lib/dbus/machine-id r,
|
||||
|
||||
|
@@ -2,5 +2,5 @@
|
||||
# video device access
|
||||
|
||||
# System devices
|
||||
/sys/class/video4linux r,
|
||||
/sys/class/video4linux/** r,
|
||||
@{sys}/class/video4linux r,
|
||||
@{sys}/class/video4linux/** r,
|
||||
|
@@ -5,7 +5,7 @@
|
||||
/dev/dri/ r, # libvulkan_radeon.so, libvulkan_intel.so (Mesa)
|
||||
/etc/vulkan/{explicit,implicit}_layer.d/{,*.json} r,
|
||||
# for drmGetMinorNameForFD() from libvulkan_intel.so (Mesa)
|
||||
/sys/devices/pci[0-9]*/*/drm/ r,
|
||||
@{sys}/devices/pci[0-9]*/*/drm/ r,
|
||||
/usr/share/vulkan/icd.d/{,*.json} r,
|
||||
/usr/share/vulkan/{explicit,implicit}_layer.d/{,*.json} r,
|
||||
|
||||
|
@@ -20,13 +20,13 @@
|
||||
/etc/phpsysinfo/config.php r,
|
||||
/etc/udev/udev.conf r,
|
||||
@{PROC}/** r,
|
||||
/sys/bus/ r,
|
||||
/sys/bus/pci/devices/ r,
|
||||
/sys/bus/pci/slots/ r,
|
||||
/sys/bus/pci/slots/** r,
|
||||
/sys/bus/usb/devices/ r,
|
||||
/sys/class/ r,
|
||||
/sys/devices/** r,
|
||||
@{sys}/bus/ r,
|
||||
@{sys}/bus/pci/devices/ r,
|
||||
@{sys}/bus/pci/slots/ r,
|
||||
@{sys}/bus/pci/slots/** r,
|
||||
@{sys}/bus/usb/devices/ r,
|
||||
@{sys}/class/ r,
|
||||
@{sys}/devices/** r,
|
||||
/usr/bin/ r,
|
||||
/usr/bin/apt-cache ixr,
|
||||
/usr/bin/dpkg-query ixr,
|
||||
|
@@ -24,8 +24,8 @@ profile nvidia_modprobe {
|
||||
|
||||
/dev/nvidia-uvm w,
|
||||
/dev/nvidia-uvm-tools w,
|
||||
/sys/bus/pci/devices/ r,
|
||||
/sys/devices/pci[0-9]*/**/config r,
|
||||
@{sys}/bus/pci/devices/ r,
|
||||
@{sys}/devices/pci[0-9]*/**/config r,
|
||||
@{PROC}/devices r,
|
||||
@{PROC}/modules r,
|
||||
@{PROC}/sys/kernel/modprobe r,
|
||||
@@ -51,9 +51,9 @@ profile nvidia_modprobe {
|
||||
|
||||
/etc/modprobe.d/{,*.conf} r,
|
||||
/etc/nvidia/current/*.conf r,
|
||||
/sys/module/ipmi_devintf/initstate r,
|
||||
/sys/module/ipmi_msghandler/initstate r,
|
||||
/sys/module/nvidia/initstate r,
|
||||
@{sys}/module/ipmi_devintf/initstate r,
|
||||
@{sys}/module/ipmi_msghandler/initstate r,
|
||||
@{sys}/module/nvidia/initstate r,
|
||||
@{PROC}/cmdline r,
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
|
||||
/etc/hosts.deny r,
|
||||
/etc/hosts.allow r,
|
||||
/{usr/,}{bin,sbin}/syslog-ng mr,
|
||||
/sys/devices/system/cpu/online r,
|
||||
@{sys}/devices/system/cpu/online r,
|
||||
/usr/share/syslog-ng/** r,
|
||||
/var/lib/syslog-ng/syslog-ng-?????.qf rw,
|
||||
# chrooted applications
|
||||
|
@@ -45,7 +45,7 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
||||
|
||||
/usr/{bin,sbin}/dnsmasq mr,
|
||||
|
||||
/var/log/*dnsmasq.log w,
|
||||
/var/log/dnsmasq*.log w,
|
||||
|
||||
/usr/share/dnsmasq/ r,
|
||||
/usr/share/dnsmasq/* r,
|
||||
@@ -96,6 +96,7 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
||||
/{,var/}run/sendsigs.omit.d/*dnsmasq.pid w,
|
||||
/{,var/}run/NetworkManager/dnsmasq.conf r,
|
||||
/{,var/}run/NetworkManager/dnsmasq.pid w,
|
||||
/{,var/}run/NetworkManager/NetworkManager.pid w,
|
||||
|
||||
profile libvirt_leaseshelper {
|
||||
#include <abstractions/base>
|
||||
@@ -107,9 +108,9 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
||||
owner @{PROC}/@{pid}/net/psched r,
|
||||
owner @{PROC}/@{pid}/status r,
|
||||
|
||||
/sys/devices/system/cpu/ r,
|
||||
/sys/devices/system/node/ r,
|
||||
/sys/devices/system/node/*/meminfo r,
|
||||
@{sys}/devices/system/cpu/ r,
|
||||
@{sys}/devices/system/node/ r,
|
||||
@{sys}/devices/system/node/*/meminfo r,
|
||||
|
||||
# libvirt lease and status files for dnsmasq
|
||||
/var/lib/libvirt/dnsmasq/*.leases rw,
|
||||
|
@@ -38,6 +38,7 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
/etc/lsb-release r,
|
||||
/etc/SuSE-release r,
|
||||
@{PROC}/@{pid}/mounts r,
|
||||
@{PROC}/sys/fs/suid_dumpable r,
|
||||
/usr/bin/doveconf rix,
|
||||
/usr/lib/dovecot/anvil mrPx,
|
||||
/usr/lib/dovecot/auth mrPx,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,18 +11,14 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/anvil {
|
||||
profile postfix-anvil /usr/lib/postfix/{sbin/,}anvil {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/usr/lib/postfix/anvil rmix,
|
||||
/usr/lib/postfix/{sbin/,}anvil rmix,
|
||||
|
||||
/etc/postfix/main.cf r,
|
||||
/{var/spool/postfix/,}private/anvil rw,
|
||||
/{var/spool/postfix/,}pid/unix.anvil rw,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/{var/spool/postfix/,}pid/unix.anvil rwk,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,15 +11,12 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/bounce {
|
||||
profile postfix-bounce /usr/lib/postfix/{sbin/,}bounce {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/usr/lib/postfix/bounce rmix,
|
||||
/usr/lib/postfix/{sbin/,}bounce rmix,
|
||||
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
@@ -36,10 +34,8 @@
|
||||
/{var/spool/postfix/,}trace/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}trace/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}public/cleanup w,
|
||||
/{var/spool/postfix/,}pid/unix.bounce rw,
|
||||
/{var/spool/postfix/,}pid/unix.defer rw,
|
||||
/{var/spool/postfix/,}pid/unix.trace rw,
|
||||
|
||||
/etc/postfix/main.cf r,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/{var/spool/postfix/,}pid/unix.bounce rwk,
|
||||
/{var/spool/postfix/,}pid/unix.defer rwk,
|
||||
/{var/spool/postfix/,}pid/unix.trace rwk,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,23 +11,27 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/cleanup {
|
||||
profile postfix-cleanup /usr/lib/postfix/{sbin/,}cleanup {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability net_bind_service,
|
||||
|
||||
/usr/lib/postfix/cleanup rmix,
|
||||
/usr/lib/postfix/{sbin/,}cleanup rmix,
|
||||
|
||||
/{var/spool/postfix/,}incoming/[0-9]*.[0-9]* rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}private/{rewrite,bounce} w,
|
||||
/{var/spool/postfix/,}public/qmgr w,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]* rw,
|
||||
/{var/spool/postfix/,}private/bounce w,
|
||||
/{var/spool/postfix/,}private/rewrite rw,
|
||||
/{var/spool/postfix/,}public/qmgr rw,
|
||||
/{var/spool/postfix/,}hold/[0-9A-F]* w,
|
||||
/{var/spool/postfix/,}pid/unix.cleanup rw,
|
||||
/{var/spool/postfix/,}public/cleanup rw,
|
||||
/{var/spool/postfix/,}pid/unix.cleanup rwk,
|
||||
|
||||
/etc/{m,fs}tab r,
|
||||
/etc/postfix/* r,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,8 +12,8 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/discard {
|
||||
profile postfix-discard /usr/lib/postfix/{sbin/,}discard {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/lib/postfix/discard rmix,
|
||||
/usr/lib/postfix/{sbin/,}discard rmix,
|
||||
}
|
20
profiles/apparmor/profiles/extras/postfix.dnsblog
Normal file
20
profiles/apparmor/profiles/extras/postfix.dnsblog
Normal file
@@ -0,0 +1,20 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2018 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
profile postfix-dnsblog /usr/lib/postfix/{sbin/,}dnsblog {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/lib/postfix/{sbin/,}dnsblog rmix,
|
||||
|
||||
/var/spool/postfix/private/dnsblog rw,
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2017 Christian Boltz
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,13 +12,13 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/error {
|
||||
profile postfix-error /usr/lib/postfix/{sbin/,}error {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
@{PROC}/sys/kernel/ngroups_max r,
|
||||
/usr/lib/postfix/error mrix,
|
||||
/usr/lib/postfix/{sbin/,}error rmix,
|
||||
|
||||
owner /var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/pid/unix.error rwk,
|
||||
/var/spool/postfix/pid/unix.retry rwk,
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,15 +11,12 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/flush {
|
||||
profile postfix-flush /usr/lib/postfix/{sbin/,}flush {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/usr/lib/postfix/flush rmix,
|
||||
/usr/lib/postfix/{sbin/,}flush rmix,
|
||||
|
||||
/{var/spool/postfix/,}deferred/ r,
|
||||
/{var/spool/postfix/,}deferred/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
@@ -35,8 +33,6 @@
|
||||
/{var/spool/postfix/,}public/qmgr w,
|
||||
/{var/spool/postfix/,}pid/unix.flush rw,
|
||||
/etc/mtab r,
|
||||
/etc/postfix/main.cf r,
|
||||
/etc/postfix/virtual.db r,
|
||||
|
||||
@{HOME}/.forward r,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2017 Christian Boltz
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,12 +12,13 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/lmtp {
|
||||
profile postfix-lmtp /usr/lib/postfix/{sbin/,}lmtp {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/lmtp mrix,
|
||||
/usr/lib/postfix/{sbin/,}lmtp rmix,
|
||||
|
||||
/var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/pid/unix.lmtp rwk,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,7 +11,7 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/local {
|
||||
profile postfix-local /usr/lib/postfix/{sbin/,}local {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/bash>
|
||||
#include <abstractions/nameservice>
|
||||
@@ -23,20 +24,24 @@
|
||||
/var/mailman/mail/wrapper Px,
|
||||
/usr/bin/mlmmj-recieve Px,
|
||||
|
||||
/usr/lib/postfix/local rmix,
|
||||
/usr/lib/postfix/{sbin/,}local rmix,
|
||||
/{usr/,}bin/bash mixr,
|
||||
/{usr/,}bin/date mixr,
|
||||
|
||||
/dev/tty rw,
|
||||
/etc/{postfix/,}aliases.db r,
|
||||
/etc/{postfix/,}aliases.db rk,
|
||||
# mailman on SuSE is configed to have its own alias file
|
||||
/var/lib/mailman/data/aliases.db r,
|
||||
/var/lib/mailman/data/aliases.db rk,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rw,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rw,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ rw,
|
||||
/{var/spool/postfix/,}pid/unix.local rw,
|
||||
/{var/spool/postfix/,}private/{bounce,defer,flush,lmtp,rewrite} rw,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]* rwk,
|
||||
/{var/spool/postfix/,}pid/unix.local rwk,
|
||||
/{var/spool/postfix/,}private/{bounce,defer,flush,lmtp,local,rewrite} rw,
|
||||
/{var/spool/postfix/,}public/{cleanup,flush} rw,
|
||||
/etc/postfix/virtual.db r,
|
||||
/etc/postfix/lists.db r,
|
||||
|
||||
# deliver mail
|
||||
/var/mail/* wk,
|
||||
}
|
52
profiles/apparmor/profiles/extras/postfix.master
Normal file
52
profiles/apparmor/profiles/extras/postfix.master
Normal file
@@ -0,0 +1,52 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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>
|
||||
|
||||
profile postfix-master /usr/lib/postfix/{sbin/,}master {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability net_bind_service,
|
||||
capability kill,
|
||||
capability dac_override,
|
||||
capability dac_read_search,
|
||||
|
||||
signal send peer=postfix-*,
|
||||
signal peer=@{profile_name},
|
||||
|
||||
unix (send receive) type=stream peer=(label=postfix-*),
|
||||
|
||||
/etc/postfix/master.cf r,
|
||||
/{var/spool/postfix/,}pid/master.pid rwk,
|
||||
/{var/spool/postfix/,}private/* wl,
|
||||
/{var/spool/postfix/,}private/tlsmgr rwl,
|
||||
/{var/spool/postfix/,}public/{cleanup,flush,pickup,qmgr,showq,tlsmgr} rwl,
|
||||
|
||||
/usr/lib/postfix/{sbin/,}anvil Px,
|
||||
/usr/lib/postfix/{sbin/,}bounce Px,
|
||||
/usr/lib/postfix/{sbin/,}cleanup Px,
|
||||
/usr/lib/postfix/{sbin/,}flush Px,
|
||||
/usr/lib/postfix/{sbin/,}local Px,
|
||||
/usr/lib/postfix/{sbin/,}master rmix,
|
||||
/usr/lib/postfix/{sbin/,}nqmgr Px,
|
||||
/usr/lib/postfix/{sbin/,}proxymap Px,
|
||||
/usr/lib/postfix/{sbin/,}pickup Px,
|
||||
/usr/lib/postfix/{sbin/,}pipe Px,
|
||||
/usr/lib/postfix/{sbin/,}qmgr Px,
|
||||
/usr/lib/postfix/{sbin/,}scache Px,
|
||||
/usr/lib/postfix/{sbin/,}showq Px,
|
||||
/usr/lib/postfix/{sbin/,}smtp Px,
|
||||
/usr/lib/postfix/{sbin/,}smtpd Px,
|
||||
/usr/lib/postfix/{sbin/,}tlsmgr Px,
|
||||
/usr/lib/postfix/{sbin/,}trivial-rewrite Px,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,12 +11,12 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/nqmgr {
|
||||
profile postfix-nqmgr /usr/lib/postfix/{sbin/,}nqmgr {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/nqmgr rmix,
|
||||
/usr/lib/postfix/{sbin/,}nqmgr rmix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ r,
|
||||
@@ -42,5 +43,4 @@
|
||||
/{var/spool/postfix/,}private/local w,
|
||||
/{var/spool/postfix/,}public/flush w,
|
||||
/{var/spool/postfix/,}public/qmgr r,
|
||||
/etc/postfix/main.cf r,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,10 +12,10 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/oqmgr {
|
||||
profile postfix-oqmgr /usr/lib/postfix/{sbin/,}oqmgr {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/oqmgr rmix,
|
||||
/usr/lib/postfix/{sbin/,}oqmgr rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,14 +11,14 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/pickup {
|
||||
profile postfix-pickup /usr/lib/postfix/{sbin/,}pickup {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/pickup rmix,
|
||||
/usr/lib/postfix/{sbin/,}pickup rmix,
|
||||
|
||||
/{var/spool/postfix/,}public/cleanup w,
|
||||
/{var/spool/postfix/,}public/cleanup rw,
|
||||
/{var/spool/postfix/,}public/pickup r,
|
||||
/{var/spool/postfix/,}maildrop/ r,
|
||||
/{var/spool/postfix/,}maildrop/* rwl,
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2006 Novell/SUSE
|
||||
# Copyright (C) 2017 Christian Boltz
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,12 +12,13 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/pipe {
|
||||
profile postfix-pipe /usr/lib/postfix/{sbin/,}pipe {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/pipe mrix,
|
||||
/usr/lib/postfix/{sbin/,}pipe rmix,
|
||||
|
||||
/var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/private/bounce w,
|
||||
/var/spool/postfix/private/defer w,
|
17
profiles/apparmor/profiles/extras/postfix.postscreen
Normal file
17
profiles/apparmor/profiles/extras/postfix.postscreen
Normal file
@@ -0,0 +1,17 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2018 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>
|
||||
|
||||
profile postfix-postscreen /usr/lib/postfix/{sbin/,}postscreen {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/lib/postfix/{sbin/,}postscreen rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,16 +11,11 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/proxymap {
|
||||
profile postfix-proxymap /usr/lib/postfix/{sbin/,}proxymap {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/usr/lib/postfix/proxymap rmix,
|
||||
|
||||
/etc/postfix/main.cf r,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/usr/lib/postfix/{sbin/,}proxymap rmix,
|
||||
/{var/spool/postfix/,}private/proxymap rw,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,16 +11,18 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/qmgr {
|
||||
profile postfix-qmgr /usr/lib/postfix/{sbin/,}qmgr {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/qmgr rmix,
|
||||
/usr/lib/postfix/{sbin/,}qmgr rmix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]* rwlk,
|
||||
/{var/spool/postfix/,}defer/ r,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
@@ -32,13 +35,14 @@
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]* rwl,
|
||||
/{var/spool/postfix/,}public/flush w,
|
||||
/{var/spool/postfix/,}public/qmgr r,
|
||||
/{var/spool/postfix/,}private/bounce w,
|
||||
/{var/spool/postfix/,}private/defer w,
|
||||
/{var/spool/postfix/,}private/local w,
|
||||
/{var/spool/postfix/,}private/local rw,
|
||||
/{var/spool/postfix/,}private/relay w,
|
||||
/{var/spool/postfix/,}private/rewrite w,
|
||||
/{var/spool/postfix/,}private/rewrite rw,
|
||||
/{var/spool/postfix/,}private/smtp w,
|
||||
/{var/spool/postfix/,}private/trace w,
|
||||
/{var/spool/postfix/,}private/uucp w,
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,10 +11,10 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/spawn {
|
||||
profile postfix-qmqpd /usr/lib/postfix/{sbin/,}qmqpd {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/spawn rmix,
|
||||
/usr/lib/postfix/{sbin/,}qmqpd rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2018 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -12,12 +13,10 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/scache {
|
||||
profile postfix-scache /usr/lib/postfix/{sbin/,}scache {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/scache rmix,
|
||||
|
||||
/{,var/}run/nscd/group r,
|
||||
/usr/lib/postfix/{sbin/,}scache rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,12 +11,12 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/showq {
|
||||
profile postfix-showq /usr/lib/postfix/{sbin/,}showq {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/showq rmix,
|
||||
/usr/lib/postfix/{sbin/,}showq rmix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* r,
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,7 +11,7 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/smtp {
|
||||
profile postfix-smtp /usr/lib/postfix/{sbin/,}smtp {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
@@ -20,7 +21,7 @@
|
||||
capability dac_read_search,
|
||||
capability net_bind_service,
|
||||
|
||||
/usr/lib/postfix/smtp rmix,
|
||||
/usr/lib/postfix/{sbin/,}smtp rmix,
|
||||
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,24 +11,24 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/smtpd {
|
||||
profile postfix-smtpd /usr/lib/postfix/{sbin/,}smtpd {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
#include <abstractions/openssl>
|
||||
#include <abstractions/ssl_certs>
|
||||
#include <abstractions/ssl_keys>
|
||||
|
||||
capability dac_override,
|
||||
capability dac_read_search,
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/usr/lib/postfix/smtpd rmix,
|
||||
/usr/lib/postfix/{sbin/,}smtpd rmix,
|
||||
/usr/sbin/postdrop rPx,
|
||||
|
||||
/dev/urandom r,
|
||||
/etc/aliases.db r,
|
||||
/etc/aliases.db rk,
|
||||
# mailman on SuSE is configured to have its own alias db
|
||||
/var/lib/mailman/data/aliases.db r,
|
||||
/var/lib/mailman/data/aliases.db rk,
|
||||
/etc/mtab r,
|
||||
/etc/fstab r,
|
||||
/etc/postfix/*.db r,
|
||||
@@ -37,21 +38,14 @@
|
||||
/etc/postfix/main.cf r,
|
||||
/etc/postfix/prng_exch rw,
|
||||
|
||||
/usr/lib64/sasl2/ mr,
|
||||
/usr/lib64/sasl2/* mr,
|
||||
/usr/lib/sasl2/ mr,
|
||||
/usr/lib/sasl2/* mr,
|
||||
|
||||
/usr/share/ssl/certs/ca-bundle.crt r,
|
||||
|
||||
/{var/spool/postfix/,}pid/inet.* rw,
|
||||
/{var/spool/postfix/,}private/anvil w,
|
||||
/{var/spool/postfix/,}private/proxymap w,
|
||||
/{var/spool/postfix/,}private/rewrite w,
|
||||
/{var/spool/postfix/,}private/tlsmgr w,
|
||||
/{var/spool/postfix/,}public/cleanup w,
|
||||
/{var/spool/postfix/,}pid/inet.* rwk,
|
||||
/{var/spool/postfix/,}private/anvil rw,
|
||||
/{var/spool/postfix/,}private/proxymap rw,
|
||||
/{var/spool/postfix/,}private/rewrite rw,
|
||||
/{var/spool/postfix/,}private/tlsmgr rw,
|
||||
/{var/spool/postfix/,}public/cleanup rw,
|
||||
|
||||
/{,var/}run/sasl2/mux w,
|
||||
|
||||
@{PROC}/net/if_inet6 r,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,10 +11,10 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/qmqpd {
|
||||
profile postfix-spawn /usr/lib/postfix/{sbin/,}spawn {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/qmqpd rmix,
|
||||
/usr/lib/postfix/{sbin/,}spawn rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -11,15 +12,18 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/tlsmgr {
|
||||
profile postfix-tlsmgr /usr/lib/postfix/{sbin/,}tlsmgr {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/tlsmgr rmix,
|
||||
/usr/lib/postfix/{sbin/,}tlsmgr rmix,
|
||||
|
||||
/etc/postfix/prng_exch rw,
|
||||
/{var/spool/postfix/,}private/tlsmgr r,
|
||||
/var/spool/postfix/dev/urandom r,
|
||||
/{etc,var/lib}/postfix/prng_exch rwk,
|
||||
/{var/spool/postfix/,}private/tlsmgr rw,
|
||||
/{,var/}run/__db.smtpd_tls_session_cache.db rw,
|
||||
/{,var/}run/smtpd_tls_session_cache.db rw,
|
||||
/var/lib/postfix/smtpd_scache.db rwk,
|
||||
/var/lib/postfix/smtp_scache.db rwk,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,16 +11,17 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/trivial-rewrite {
|
||||
profile postfix-trivial-rewrite /usr/lib/postfix/{sbin/,}trivial-rewrite {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/trivial-rewrite rmix,
|
||||
/usr/lib/postfix/{sbin/,}trivial-rewrite rmix,
|
||||
|
||||
/etc/postfix/relocated.db r,
|
||||
/etc/postfix/transport.db r,
|
||||
/etc/postfix/virtual.db r,
|
||||
/etc/{m,fs}tab r,
|
||||
/var/spool/postfix/pid/unix.rewrite rw,
|
||||
/{var/spool/postfix/,}private/rewrite rw,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,10 +11,10 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/verify {
|
||||
profile postfix-verify /usr/lib/postfix/{sbin/,}verify {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/verify rmix,
|
||||
/usr/lib/postfix/{sbin/,}verify rmix,
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 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
|
||||
@@ -10,15 +11,13 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/virtual {
|
||||
profile postfix-virtual /usr/lib/postfix/{sbin/,}virtual {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
/usr/lib/postfix/{sbin/,}virtual rmix,
|
||||
|
||||
/usr/lib/postfix/virtual rmix,
|
||||
/var/spool/postfix/active/* rw,
|
||||
/var/spool/postfix/pid/unix.virtual rw,
|
||||
/var/spool/postfix/private/bounce w,
|
@@ -1,46 +0,0 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/postfix/master {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/postfix-common>
|
||||
|
||||
capability net_bind_service,
|
||||
capability kill,
|
||||
capability dac_override,
|
||||
|
||||
/etc/postfix/master.cf r,
|
||||
/{var/spool/postfix/,}pid/master.pid rwk,
|
||||
/{var/spool/postfix/,}private/* wl,
|
||||
/{var/spool/postfix/,}private/tlsmgr rwl,
|
||||
/{var/spool/postfix/,}public/{cleanup,flush,pickup,qmgr,showq,tlsmgr} rwl,
|
||||
|
||||
/usr/lib/postfix/anvil Px,
|
||||
/usr/lib/postfix/bounce Px,
|
||||
/usr/lib/postfix/cleanup Px,
|
||||
/usr/lib/postfix/flush Px,
|
||||
/usr/lib/postfix/local Px,
|
||||
/usr/lib/postfix/master rmix,
|
||||
/usr/lib/postfix/nqmgr Px,
|
||||
/usr/lib/postfix/proxymap Px,
|
||||
/usr/lib/postfix/pickup Px,
|
||||
/usr/lib/postfix/pipe Px,
|
||||
/usr/lib/postfix/qmgr Px,
|
||||
/usr/lib/postfix/scache Px,
|
||||
/usr/lib/postfix/showq Px,
|
||||
/usr/lib/postfix/smtp Px,
|
||||
/usr/lib/postfix/smtpd Px,
|
||||
/usr/lib/postfix/tlsmgr Px,
|
||||
/usr/lib/postfix/trivial-rewrite Px,
|
||||
/usr/lib/postfix/master rmix,
|
||||
}
|
@@ -30,5 +30,5 @@
|
||||
/var/spool/postfix/maildrop r,
|
||||
/var/spool/postfix/maildrop/* rwl,
|
||||
/var/spool/postfix/pid r,
|
||||
/var/spool/postfix/public/pickup w,
|
||||
/var/spool/postfix/public/pickup rw,
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
SUBDIRS=subdomain
|
||||
SUBDIRS=apparmor
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
@@ -107,7 +107,7 @@ apparmor.check_qualifiers(program)
|
||||
|
||||
apparmor.loadincludes()
|
||||
|
||||
profile_filename = apparmor.get_profile_filename(program)
|
||||
profile_filename = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
if os.path.exists(profile_filename):
|
||||
apparmor.helpers[program] = apparmor.get_profile_flags(profile_filename, program)
|
||||
else:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python3
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -57,7 +57,7 @@ def reset_aa():
|
||||
apparmor.aa.aa = apparmor.aa.hasher()
|
||||
apparmor.aa.filelist = apparmor.aa.hasher()
|
||||
apparmor.aa.include = dict()
|
||||
apparmor.aa.existing_profiles = apparmor.aa.hasher()
|
||||
apparmor.aa.active_profiles = apparmor.aa.ProfileList()
|
||||
apparmor.aa.original_aa = apparmor.aa.hasher()
|
||||
|
||||
def find_profiles_from_files(files):
|
||||
@@ -75,7 +75,7 @@ def find_files_from_profiles(profiles):
|
||||
apparmor.aa.read_profiles()
|
||||
|
||||
for profile_name in profiles:
|
||||
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename(profile_name)
|
||||
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename_from_profile_name(profile_name, True)
|
||||
|
||||
reset_aa()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -49,6 +49,8 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END, RE_PROFILE_LINK,
|
||||
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
|
||||
strip_quotes, parse_profile_start_line, re_match_include )
|
||||
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
from apparmor.profile_storage import (ProfileStorage, add_or_remove_flag, ruletypes, write_alias,
|
||||
write_abi, write_includes, write_list_vars )
|
||||
|
||||
@@ -89,7 +91,8 @@ extra_profile_dir = None
|
||||
# To keep track of previously included profile fragments
|
||||
include = dict()
|
||||
|
||||
existing_profiles = dict()
|
||||
active_profiles = ProfileList()
|
||||
extra_profiles = ProfileList()
|
||||
|
||||
# To store the globs entered by users so they can be provided again
|
||||
# format: user_globs['/foo*'] = AARE('/foo*')
|
||||
@@ -217,11 +220,29 @@ def find_executable(bin_path):
|
||||
return full_bin
|
||||
return None
|
||||
|
||||
def get_profile_filename(profile):
|
||||
"""Returns the full profile name"""
|
||||
if existing_profiles.get(profile, False):
|
||||
return existing_profiles[profile]
|
||||
elif profile.startswith('/'):
|
||||
def get_profile_filename_from_profile_name(profile, get_new=False):
|
||||
"""Returns the full profile name for the given profile name"""
|
||||
|
||||
filename = active_profiles.filename_from_profile_name(profile)
|
||||
if filename:
|
||||
return filename
|
||||
|
||||
if get_new:
|
||||
return get_new_profile_filename(profile)
|
||||
|
||||
def get_profile_filename_from_attachment(profile, get_new=False):
|
||||
"""Returns the full profile name for the given attachment"""
|
||||
|
||||
filename = active_profiles.filename_from_attachment(profile)
|
||||
if filename:
|
||||
return filename
|
||||
|
||||
if get_new:
|
||||
return get_new_profile_filename(profile)
|
||||
|
||||
def get_new_profile_filename(profile):
|
||||
'''Compose filename for a new profile'''
|
||||
if profile.startswith('/'):
|
||||
# Remove leading /
|
||||
profile = profile[1:]
|
||||
else:
|
||||
@@ -238,7 +259,7 @@ def name_to_prof_filename(prof_filename):
|
||||
else:
|
||||
bin_path = find_executable(prof_filename)
|
||||
if bin_path:
|
||||
prof_filename = get_profile_filename(bin_path)
|
||||
prof_filename = get_profile_filename_from_attachment(bin_path, True)
|
||||
if os.path.isfile(prof_filename):
|
||||
return (prof_filename, bin_path)
|
||||
|
||||
@@ -464,7 +485,7 @@ def create_new_profile(localfile, is_stub=False):
|
||||
|
||||
def delete_profile(local_prof):
|
||||
"""Deletes the specified file from the disk and remove it from our list"""
|
||||
profile_file = get_profile_filename(local_prof)
|
||||
profile_file = get_profile_filename_from_profile_name(local_prof, True)
|
||||
if os.path.isfile(profile_file):
|
||||
os.remove(profile_file)
|
||||
if aa.get(local_prof, False):
|
||||
@@ -498,13 +519,15 @@ def get_profile(prof_name):
|
||||
if inactive_profile:
|
||||
uname = 'Inactive local profile for %s' % prof_name
|
||||
inactive_profile[prof_name][prof_name]['flags'] = 'complain'
|
||||
orig_filename = inactive_profile[prof_name][prof_name]['filename'] # needed for CMD_VIEW_PROFILE
|
||||
inactive_profile[prof_name][prof_name]['filename'] = ''
|
||||
profile_hash[uname]['username'] = uname
|
||||
profile_hash[uname]['profile_type'] = 'INACTIVE_LOCAL'
|
||||
profile_hash[uname]['profile'] = serialize_profile(inactive_profile[prof_name], prof_name, {})
|
||||
profile_hash[uname]['profile_data'] = inactive_profile
|
||||
|
||||
existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
|
||||
# no longer necessary after splitting active and extra profiles
|
||||
# existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
|
||||
|
||||
# If no profiles in repo and no inactive profiles
|
||||
if not profile_hash.keys():
|
||||
@@ -538,11 +561,7 @@ def get_profile(prof_name):
|
||||
q.selected = options.index(options[arg])
|
||||
if ans == 'CMD_VIEW_PROFILE':
|
||||
pager = get_pager()
|
||||
proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
|
||||
# proc.communicate('Profile submitted by %s:\n\n%s\n\n' %
|
||||
# (options[arg], p['profile']))
|
||||
proc.communicate(p['profile'].encode())
|
||||
proc.kill()
|
||||
subprocess.call([pager, orig_filename])
|
||||
elif ans == 'CMD_USE_PROFILE':
|
||||
if p['profile_type'] == 'INACTIVE_LOCAL':
|
||||
profile_data = p['profile_data']
|
||||
@@ -551,21 +570,6 @@ def get_profile(prof_name):
|
||||
profile_data = parse_repo_profile(prof_name, repo_url, p)
|
||||
return profile_data
|
||||
|
||||
def activate_repo_profiles(url, profiles, complain):
|
||||
read_profiles()
|
||||
try:
|
||||
for p in profiles:
|
||||
pname = p[0]
|
||||
profile_data = parse_repo_profile(pname, url, p[1])
|
||||
attach_profile_data(aa, profile_data)
|
||||
write_profile(pname)
|
||||
if complain:
|
||||
fname = get_profile_filename(pname)
|
||||
change_profile_flags(profile_dir + fname, None, 'complain', True)
|
||||
aaui.UI_Info(_('Setting %s to complain mode.') % pname)
|
||||
except Exception as e:
|
||||
sys.stderr.write(_("Error activating profiles: %s") % e)
|
||||
|
||||
def autodep(bin_name, pname=''):
|
||||
bin_full = None
|
||||
global repo_cfg
|
||||
@@ -592,7 +596,7 @@ def autodep(bin_name, pname=''):
|
||||
# Create a new profile if no existing profile
|
||||
if not profile_data:
|
||||
profile_data = create_new_profile(pname)
|
||||
file = get_profile_filename(pname)
|
||||
file = get_profile_filename_from_profile_name(pname, True)
|
||||
profile_data[pname][pname]['filename'] = None # will be stored in /etc/apparmor.d when saving, so it shouldn't carry the extra_profile_dir filename
|
||||
attach_profile_data(aa, profile_data)
|
||||
attach_profile_data(original_aa, profile_data)
|
||||
@@ -661,6 +665,7 @@ def change_profile_flags(prof_filename, program, flag, set_flag):
|
||||
'flags': newflags,
|
||||
'profile_keyword': matches['profile_keyword'],
|
||||
'header_comment': matches['comment'] or '',
|
||||
'xattrs': matches['xattrs'],
|
||||
}
|
||||
line = write_header(header_data, len(space)/2, profile, False, True)
|
||||
line = '%s\n' % line[0]
|
||||
@@ -692,15 +697,16 @@ def profile_exists(program):
|
||||
"""Returns True if profile exists, False otherwise"""
|
||||
# Check cache of profiles
|
||||
|
||||
if existing_profiles.get(program, False):
|
||||
if active_profiles.filename_from_attachment(program):
|
||||
return True
|
||||
# Check the disk for profile
|
||||
prof_path = get_profile_filename(program)
|
||||
prof_path = get_profile_filename_from_attachment(program, True)
|
||||
#print(prof_path)
|
||||
if os.path.isfile(prof_path):
|
||||
# Add to cache of profile
|
||||
existing_profiles[program] = prof_path
|
||||
return True
|
||||
raise AppArmorBug('Reached strange condition in profile_exists(), please open a bugreport!')
|
||||
# active_profiles[program] = prof_path
|
||||
# return True
|
||||
return False
|
||||
|
||||
def sync_profile():
|
||||
@@ -1088,9 +1094,9 @@ def handle_children(profile, hat, root):
|
||||
options += 'd'
|
||||
# Define the default option
|
||||
default = None
|
||||
if 'p' in options and os.path.exists(get_profile_filename(exec_target)):
|
||||
if 'p' in options and os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
|
||||
default = 'CMD_px'
|
||||
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename(exec_target))
|
||||
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename_from_attachment(exec_target, True))
|
||||
elif 'i' in options:
|
||||
default = 'CMD_ix'
|
||||
elif 'c' in options:
|
||||
@@ -1104,7 +1110,7 @@ def handle_children(profile, hat, root):
|
||||
parent_uses_ld_xxx = check_for_LD_XXX(profile)
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
|
||||
severity = sev_db.rank_path(exec_target, 'x')
|
||||
|
||||
# Prompt portion starts
|
||||
@@ -1228,7 +1234,7 @@ def handle_children(profile, hat, root):
|
||||
profile_changes[pid] = '%s' % profile
|
||||
|
||||
# Check profile exists for px
|
||||
if not os.path.exists(get_profile_filename(exec_target)):
|
||||
if not os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
|
||||
ynans = 'y'
|
||||
if 'i' in exec_mode:
|
||||
ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
|
||||
@@ -1362,7 +1368,7 @@ def ask_the_questions(log_dict):
|
||||
UI_SelectUpdatedRepoProfile(profile, p)
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
|
||||
|
||||
# Sorted list of hats with the profile name coming first
|
||||
hats = list(filter(lambda key: key != profile, sorted(log_dict[aamode][profile].keys())))
|
||||
@@ -1769,7 +1775,7 @@ def set_logfile(filename):
|
||||
def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
|
||||
# set up variables for this pass
|
||||
# transitions = hasher()
|
||||
global existing_profiles
|
||||
global active_profiles
|
||||
global sev_db
|
||||
# aa = hasher()
|
||||
# profile_changes = hasher()
|
||||
@@ -1786,13 +1792,13 @@ def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
|
||||
if not sev_db:
|
||||
sev_db = apparmor.severity.Severity(CONFDIR + '/severity.db', _('unknown'))
|
||||
#print(pid)
|
||||
#print(existing_profiles)
|
||||
#print(active_profiles)
|
||||
##if not repo_cf and cfg['repostory']['url']:
|
||||
## repo_cfg = read_config('repository.conf')
|
||||
## if not repo_cfg['repository'].get('enabled', False) or repo_cfg['repository]['enabled'] not in ['yes', 'no']:
|
||||
## UI_ask_to_enable_repo()
|
||||
|
||||
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, existing_profiles, profile_dir)
|
||||
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, active_profiles, profile_dir)
|
||||
log = log_reader.read_log(logmark)
|
||||
#read_log(logmark)
|
||||
|
||||
@@ -1867,7 +1873,7 @@ def save_profiles():
|
||||
if aa[which][which].get('filename', False):
|
||||
oldprofile = aa[which][which]['filename']
|
||||
else:
|
||||
oldprofile = get_profile_filename(which)
|
||||
oldprofile = get_profile_filename_from_attachment(which, True)
|
||||
|
||||
serialize_options = {'METADATA': True}
|
||||
newprofile = serialize_profile(aa[which], which, serialize_options)
|
||||
@@ -2082,9 +2088,29 @@ def read_profile(file, active_profile):
|
||||
if profile_data and active_profile:
|
||||
attach_profile_data(aa, profile_data)
|
||||
attach_profile_data(original_aa, profile_data)
|
||||
|
||||
for profile in profile_data: # TODO: also honor hats
|
||||
name = profile_data[profile][profile]['name']
|
||||
attachment = profile_data[profile][profile]['attachment']
|
||||
filename = profile_data[profile][profile]['filename']
|
||||
|
||||
if not attachment and name.startswith('/'):
|
||||
active_profiles.add(filename, name, name) # use name as name and attachment
|
||||
else:
|
||||
active_profiles.add(filename, name, attachment)
|
||||
|
||||
elif profile_data:
|
||||
attach_profile_data(extras, profile_data)
|
||||
|
||||
for profile in profile_data: # TODO: also honor hats
|
||||
name = profile_data[profile][profile]['name']
|
||||
attachment = profile_data[profile][profile]['attachment']
|
||||
filename = profile_data[profile][profile]['filename']
|
||||
|
||||
if not attachment and name.startswith('/'):
|
||||
extra_profiles.add(filename, name, name) # use name as name and attachment
|
||||
else:
|
||||
extra_profiles.add(filename, name, attachment)
|
||||
|
||||
def attach_profile_data(profiles, profile_data):
|
||||
# Make deep copy of data to avoid changes to
|
||||
@@ -2132,8 +2158,9 @@ def parse_profile_start(line, file, lineno, profile, hat):
|
||||
|
||||
attachment = matches['attachment']
|
||||
flags = matches['flags']
|
||||
xattrs = matches['xattrs']
|
||||
|
||||
return (profile, hat, attachment, flags, in_contained_hat, pps_set_profile, pps_set_hat_external)
|
||||
return (profile, hat, attachment, xattrs, flags, in_contained_hat, pps_set_profile, pps_set_hat_external)
|
||||
|
||||
def parse_profile_data(data, file, do_include):
|
||||
profile_data = hasher()
|
||||
@@ -2161,7 +2188,7 @@ def parse_profile_data(data, file, do_include):
|
||||
lastline = None
|
||||
# Starting line of a profile
|
||||
if RE_PROFILE_START.search(line):
|
||||
(profile, hat, attachment, flags, in_contained_hat, pps_set_profile, pps_set_hat_external) = parse_profile_start(line, file, lineno, profile, hat)
|
||||
(profile, hat, attachment, xattrs, flags, in_contained_hat, pps_set_profile, pps_set_hat_external) = parse_profile_start(line, file, lineno, profile, hat)
|
||||
|
||||
if profile_data[profile].get(hat, False):
|
||||
raise AppArmorException('Profile %(profile)s defined twice in %(file)s, last found in line %(line)s' %
|
||||
@@ -2176,14 +2203,12 @@ def parse_profile_data(data, file, do_include):
|
||||
if pps_set_hat_external:
|
||||
profile_data[profile][hat]['external'] = True
|
||||
|
||||
# Profile stored
|
||||
existing_profiles[profile] = file
|
||||
|
||||
# save profile name and filename
|
||||
profile_data[profile][hat]['name'] = profile
|
||||
profile_data[profile][hat]['filename'] = file
|
||||
filelist[file]['profiles'][profile][hat] = True
|
||||
|
||||
profile_data[profile][hat]['xattrs'] = xattrs
|
||||
profile_data[profile][hat]['flags'] = flags
|
||||
|
||||
# Save the initial comment
|
||||
@@ -2504,6 +2529,11 @@ def parse_profile_data(data, file, do_include):
|
||||
else:
|
||||
raise AppArmorException(_('Syntax Error: Unknown line found in file %(file)s line %(lineno)s:\n %(line)s') % { 'file': file, 'lineno': lineno + 1, 'line': line })
|
||||
|
||||
if lastline:
|
||||
# lastline gets merged into line (and reset to None) when reading the next line.
|
||||
# If it isn't empty, this means there's something unparseable at the end of the profile
|
||||
raise AppArmorException(_('Syntax Error: Unknown line found in file %(file)s line %(lineno)s:\n %(line)s') % { 'file': file, 'lineno': lineno + 1, 'line': lastline })
|
||||
|
||||
# Below is not required I'd say
|
||||
if not do_include:
|
||||
for hatglob in cfg['required_hats'].keys():
|
||||
@@ -2589,11 +2619,15 @@ def write_header(prof_data, depth, name, embedded_hat, write_flags):
|
||||
if (not embedded_hat and re.search('^[^/]', unquoted_name)) or (embedded_hat and re.search('^[^^]', unquoted_name)) or prof_data['attachment'] or prof_data['profile_keyword']:
|
||||
name = 'profile %s%s' % (name, attachment)
|
||||
|
||||
xattrs = ''
|
||||
if prof_data['xattrs']:
|
||||
xattrs = ' xattrs=(%s)' % prof_data['xattrs']
|
||||
|
||||
flags = ''
|
||||
if write_flags and prof_data['flags']:
|
||||
flags = ' flags=(%s)' % prof_data['flags']
|
||||
|
||||
data.append('%s%s%s {%s' % (pre, name, flags, comment))
|
||||
data.append('%s%s%s%s {%s' % (pre, name, xattrs, flags, comment))
|
||||
|
||||
return data
|
||||
|
||||
@@ -2677,7 +2711,11 @@ def serialize_profile(profile_data, name, options):
|
||||
# comment.replace('\\n', '\n')
|
||||
# string += comment + '\n'
|
||||
|
||||
prof_filename = get_profile_filename(name)
|
||||
if options.get('is_attachment'):
|
||||
prof_filename = get_profile_filename_from_attachment(name, True)
|
||||
else:
|
||||
prof_filename = get_profile_filename_from_profile_name(name, True)
|
||||
|
||||
if filelist.get(prof_filename, False):
|
||||
data += write_abi(filelist[prof_filename], 0)
|
||||
data += write_alias(filelist[prof_filename], 0)
|
||||
@@ -2703,16 +2741,18 @@ def serialize_profile(profile_data, name, options):
|
||||
|
||||
return string + '\n'
|
||||
|
||||
def write_profile_ui_feedback(profile):
|
||||
def write_profile_ui_feedback(profile, is_attachment=False):
|
||||
aaui.UI_Info(_('Writing updated profile for %s.') % profile)
|
||||
write_profile(profile)
|
||||
write_profile(profile, is_attachment)
|
||||
|
||||
def write_profile(profile):
|
||||
def write_profile(profile, is_attachment=False):
|
||||
prof_filename = None
|
||||
if aa[profile][profile].get('filename', False):
|
||||
prof_filename = aa[profile][profile]['filename']
|
||||
elif is_attachment:
|
||||
prof_filename = get_profile_filename_from_attachment(profile, True)
|
||||
else:
|
||||
prof_filename = get_profile_filename(profile)
|
||||
prof_filename = get_profile_filename_from_profile_name(profile, True)
|
||||
|
||||
newprof = tempfile.NamedTemporaryFile('w', suffix='~', delete=False, dir=profile_dir)
|
||||
if os.path.exists(prof_filename):
|
||||
@@ -2722,7 +2762,7 @@ def write_profile(profile):
|
||||
#os.chmod(newprof.name, permission_600)
|
||||
pass
|
||||
|
||||
serialize_options = {'METADATA': True}
|
||||
serialize_options = {'METADATA': True, 'is_attachment': is_attachment}
|
||||
|
||||
profile_string = serialize_profile(aa[profile], profile, serialize_options)
|
||||
newprof.write(profile_string)
|
||||
@@ -2844,7 +2884,7 @@ def reload_base(bin_path):
|
||||
if not check_for_apparmor():
|
||||
return None
|
||||
|
||||
prof_filename = get_profile_filename(bin_path)
|
||||
prof_filename = get_profile_filename_from_profile_name(bin_path, True)
|
||||
|
||||
# XXX use reload_profile() from tools.py instead (and don't hide output in /dev/null)
|
||||
subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" % (prof_filename, parser, profile_dir), shell=True)
|
||||
|
@@ -40,7 +40,7 @@ from apparmor.common import AppArmorException, open_file_read # , warn, msg,
|
||||
|
||||
# CFG = None
|
||||
# REPO_CFG = None
|
||||
# SHELL_FILES = ['easyprof.conf', 'notify.conf', 'parser.conf', 'subdomain.conf']
|
||||
# SHELL_FILES = ['easyprof.conf', 'notify.conf', 'parser.conf']
|
||||
class Config(object):
|
||||
def __init__(self, conf_type, conf_dir='/etc/apparmor'):
|
||||
self.CONF_DIR = conf_dir
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2015-2016 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2015-2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -44,11 +44,11 @@ class ReadLog:
|
||||
# used to pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing
|
||||
RE_LOG_ALL = re.compile('(' + '|'.join(RE_log_parts) + ')')
|
||||
|
||||
def __init__(self, pid, filename, existing_profiles, profile_dir):
|
||||
def __init__(self, pid, filename, active_profiles, profile_dir):
|
||||
self.filename = filename
|
||||
self.profile_dir = profile_dir
|
||||
self.pid = pid
|
||||
self.existing_profiles = existing_profiles
|
||||
self.active_profiles = active_profiles
|
||||
self.log = []
|
||||
self.debug_logger = DebugLogger('ReadLog')
|
||||
self.LOG = None
|
||||
@@ -447,15 +447,16 @@ class ReadLog:
|
||||
def profile_exists(self, program):
|
||||
"""Returns True if profile exists, False otherwise"""
|
||||
# Check cache of profiles
|
||||
if self.existing_profiles.get(program, False):
|
||||
if self.active_profiles.filename_from_profile_name(program):
|
||||
return True
|
||||
# Check the disk for profile
|
||||
prof_path = self.get_profile_filename(program)
|
||||
#print(prof_path)
|
||||
if os.path.isfile(prof_path):
|
||||
# Add to cache of profile
|
||||
self.existing_profiles[program] = prof_path
|
||||
return True
|
||||
raise AppArmorBug('This should never happen, please open a bugreport!')
|
||||
# self.active_profiles[program] = prof_path
|
||||
# return True
|
||||
return False
|
||||
|
||||
def get_profile_filename(self, profile):
|
||||
|
73
utils/apparmor/profile_list.py
Normal file
73
utils/apparmor/profile_list.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# 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 as 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.
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
from apparmor.aare import AARE
|
||||
from apparmor.common import AppArmorBug, AppArmorException
|
||||
|
||||
# setup module translations
|
||||
from apparmor.translations import init_translation
|
||||
_ = init_translation()
|
||||
|
||||
|
||||
class ProfileList:
|
||||
''' Stores the list of profiles (both name and attachment) and in which files they live '''
|
||||
|
||||
def __init__(self):
|
||||
self.profile_names = {} # profile name -> filename
|
||||
self.attachments = {} # attachment -> filename
|
||||
self.attachments_AARE = {} # AARE(attachment) -> filename
|
||||
|
||||
def add(self, filename, profile_name, attachment):
|
||||
''' Add the given profile and attachment to the list '''
|
||||
|
||||
if not filename:
|
||||
raise AppArmorBug('Empty filename given to ProfileList')
|
||||
|
||||
if not profile_name and not attachment:
|
||||
raise AppArmorBug('Neither profile name or attachment given')
|
||||
|
||||
if profile_name in self.profile_names:
|
||||
raise AppArmorException(_('Profile %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': profile_name, 'filename': filename, 'filename2': self.profile_names[profile_name]}))
|
||||
|
||||
if attachment in self.attachments:
|
||||
raise AppArmorException(_('Profile for %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': attachment, 'filename': filename, 'filename2': self.attachments[attachment]}))
|
||||
|
||||
if profile_name:
|
||||
self.profile_names[profile_name] = filename
|
||||
|
||||
if attachment:
|
||||
self.attachments[attachment] = filename
|
||||
self.attachments_AARE[attachment] = AARE(attachment, True)
|
||||
|
||||
def filename_from_profile_name(self, name):
|
||||
''' Return profile filename for the given profile name, or None '''
|
||||
|
||||
return self.profile_names.get(name, None)
|
||||
|
||||
def filename_from_attachment(self, attachment):
|
||||
''' Return profile filename for the given attachment/executable path, or None '''
|
||||
|
||||
if not attachment.startswith( ('/', '@', '{') ):
|
||||
raise AppArmorBug('Called filename_from_attachment with non-path attachment: %s' % attachment)
|
||||
|
||||
# plain path
|
||||
if self.attachments.get(attachment):
|
||||
return self.attachments[attachment]
|
||||
|
||||
# try AARE matches to cover profile names with alternations and wildcards
|
||||
for path in self.attachments.keys():
|
||||
if self.attachments_AARE[path].match(attachment):
|
||||
return self.attachments[path] # XXX this returns the first match, not necessarily the best one
|
||||
|
||||
return None # nothing found
|
@@ -69,6 +69,7 @@ class ProfileStorage:
|
||||
data['filename'] = ''
|
||||
data['name'] = ''
|
||||
data['attachment'] = ''
|
||||
data['xattrs'] = ''
|
||||
data['flags'] = ''
|
||||
data['external'] = False
|
||||
data['header_comment'] = '' # currently only set by change_profile_flags()
|
||||
|
@@ -30,6 +30,8 @@ RE_PATH = '/\S*|"/[^"]*"' # filename (starting with '/') withou
|
||||
RE_PROFILE_PATH = '(?P<%s>(' + RE_PATH + '))' # quoted or unquoted filename. %s is the match group name
|
||||
RE_PROFILE_PATH_OR_VAR = '(?P<%s>(' + RE_PATH + '|@{\S+}\S*|"@{\S+}[^"]*"))' # quoted or unquoted filename or variable. %s is the match group name
|
||||
RE_SAFE_OR_UNSAFE = '(?P<execmode>(safe|unsafe))'
|
||||
RE_XATTRS = '(\s+xattrs\s*=\s*\((?P<xattrs>([^)=]+=[^)=]+\s?)+)\)\s*)?'
|
||||
RE_FLAGS = '(\s+(flags\s*=\s*)?\((?P<flags>[^)]+)\))?'
|
||||
|
||||
RE_PROFILE_END = re.compile('^\s*\}' + RE_EOL)
|
||||
RE_PROFILE_CAP = re.compile(RE_AUDIT_DENY + 'capability(?P<capability>(\s+\S+)+)?' + RE_COMMA_EOL)
|
||||
@@ -43,7 +45,7 @@ RE_PROFILE_CONDITIONAL_VARIABLE = re.compile('^\s*if\s+(not\s+)?defined\s+(@\{?\
|
||||
RE_PROFILE_CONDITIONAL_BOOLEAN = re.compile('^\s*if\s+(not\s+)?defined\s+(\$\{?\w+\}?)\s*\{\s*(#.*)?$')
|
||||
RE_PROFILE_NETWORK = re.compile(RE_AUDIT_DENY + 'network(?P<details>\s+.*)?' + RE_COMMA_EOL)
|
||||
RE_PROFILE_CHANGE_HAT = re.compile('^\s*\^(\"??.+?\"??)' + RE_COMMA_EOL)
|
||||
RE_PROFILE_HAT_DEF = re.compile('^(?P<leadingspace>\s*)(?P<hat_keyword>\^|hat\s+)(?P<hat>\"??.+?\"??)\s+((flags=)?\((?P<flags>.+)\)\s+)*\{' + RE_EOL)
|
||||
RE_PROFILE_HAT_DEF = re.compile('^(?P<leadingspace>\s*)(?P<hat_keyword>\^|hat\s+)(?P<hat>\"??[^)]+?\"??)' + RE_XATTRS + RE_FLAGS + '\s*\{' + RE_EOL)
|
||||
RE_PROFILE_DBUS = re.compile(RE_AUDIT_DENY + '(dbus\s*,|dbus(?P<details>\s+[^#]*)\s*,)' + RE_EOL)
|
||||
RE_PROFILE_MOUNT = re.compile(RE_AUDIT_DENY + '((mount|remount|umount|unmount)(\s+[^#]*)?\s*,)' + RE_EOL)
|
||||
RE_PROFILE_SIGNAL = re.compile(RE_AUDIT_DENY + '(signal\s*,|signal(?P<details>\s+[^#]*)\s*,)' + RE_EOL)
|
||||
@@ -68,7 +70,9 @@ RE_PROFILE_START = re.compile(
|
||||
'|' + # or
|
||||
'(' + 'profile' + '\s+' + RE_PROFILE_NAME % 'namedprofile' + '(\s+' + RE_PROFILE_PATH_OR_VAR % 'attachment' + ')?' + ')' + # 'profile', profile name, optionally attachment
|
||||
')' +
|
||||
'\s+((flags\s*=\s*)?\((?P<flags>.+)\)\s*)?\{' +
|
||||
RE_XATTRS +
|
||||
RE_FLAGS +
|
||||
'\s*\{' +
|
||||
RE_EOL)
|
||||
|
||||
|
||||
@@ -110,7 +114,7 @@ def parse_profile_start_line(line, filename):
|
||||
|
||||
result = {}
|
||||
|
||||
for section in [ 'leadingspace', 'plainprofile', 'namedprofile', 'attachment', 'flags', 'comment']:
|
||||
for section in [ 'leadingspace', 'plainprofile', 'namedprofile', 'attachment', 'xattrs', 'flags', 'comment']:
|
||||
if matches.group(section):
|
||||
result[section] = matches.group(section)
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2015-2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -66,12 +67,12 @@ class aa_tools:
|
||||
profile = fq_path
|
||||
else:
|
||||
program = fq_path
|
||||
profile = apparmor.get_profile_filename(fq_path)
|
||||
profile = apparmor.get_profile_filename_from_attachment(fq_path, True)
|
||||
else:
|
||||
which = apparmor.which(p)
|
||||
if which is not None:
|
||||
program = apparmor.get_full_path(which)
|
||||
profile = apparmor.get_profile_filename(program)
|
||||
profile = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
elif os.path.exists(os.path.join(apparmor.profile_dir, p)):
|
||||
program = None
|
||||
profile = apparmor.get_full_path(os.path.join(apparmor.profile_dir, p)).strip()
|
||||
@@ -190,7 +191,7 @@ class aa_tools:
|
||||
|
||||
apparmor.check_qualifiers(program)
|
||||
|
||||
if os.path.exists(apparmor.get_profile_filename(program)) and not self.force:
|
||||
if os.path.exists(apparmor.get_profile_filename_from_attachment(program, True)) and not self.force:
|
||||
aaui.UI_Info(_('Profile for %s already exists - skipping.') % program)
|
||||
else:
|
||||
apparmor.autodep(program)
|
||||
@@ -198,7 +199,7 @@ class aa_tools:
|
||||
apparmor.reload(program)
|
||||
|
||||
def clean_profile(self, program):
|
||||
filename = apparmor.get_profile_filename(program)
|
||||
filename = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
import apparmor.cleanprofile as cleanprofile
|
||||
prof = cleanprofile.Prof(filename)
|
||||
cleanprof = cleanprofile.CleanProf(True, prof, prof)
|
||||
@@ -220,14 +221,14 @@ class aa_tools:
|
||||
while ans != 'CMD_SAVE_CHANGES':
|
||||
ans, arg = q.promptUser()
|
||||
if ans == 'CMD_SAVE_CHANGES':
|
||||
apparmor.write_profile_ui_feedback(program)
|
||||
apparmor.write_profile_ui_feedback(program, True)
|
||||
self.reload_profile(filename)
|
||||
elif ans == 'CMD_VIEW_CHANGES':
|
||||
#oldprofile = apparmor.serialize_profile(apparmor.original_aa[program], program, {})
|
||||
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, {})
|
||||
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, {'is_attachment': True})
|
||||
aaui.UI_Changes(filename, newprofile, comments=True)
|
||||
else:
|
||||
apparmor.write_profile_ui_feedback(program)
|
||||
apparmor.write_profile_ui_feedback(program, True)
|
||||
self.reload_profile(filename)
|
||||
else:
|
||||
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.') % program)
|
||||
|
@@ -511,32 +511,42 @@ class AaTest_parse_profile_start(AATest):
|
||||
|
||||
def test_parse_profile_start_01(self):
|
||||
result = self._parse('/foo {', None, None)
|
||||
expected = ('/foo', '/foo', None, None, False, False, False)
|
||||
expected = ('/foo', '/foo', None, None, None, False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_02(self):
|
||||
result = self._parse('/foo (complain) {', None, None)
|
||||
expected = ('/foo', '/foo', None, 'complain', False, False, False)
|
||||
expected = ('/foo', '/foo', None, None, 'complain', False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_03(self):
|
||||
result = self._parse('profile foo /foo {', None, None) # named profile
|
||||
expected = ('foo', 'foo', '/foo', None, False, False, False)
|
||||
expected = ('foo', 'foo', '/foo', None, None, False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_04(self):
|
||||
result = self._parse('profile /foo {', '/bar', '/bar') # child profile
|
||||
expected = ('/bar', '/foo', None, None, True, True, False)
|
||||
expected = ('/bar', '/foo', None, None, None, True, True, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_05(self):
|
||||
result = self._parse('/foo//bar {', None, None) # external hat
|
||||
expected = ('/foo', 'bar', None, None, False, False, True)
|
||||
expected = ('/foo', 'bar', None, None, None, False, False, True)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_06(self):
|
||||
result = self._parse('profile "/foo" (complain) {', None, None)
|
||||
expected = ('/foo', '/foo', None, 'complain', False, False, False)
|
||||
expected = ('/foo', '/foo', None, None, 'complain', False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_07(self):
|
||||
result = self._parse('profile "/foo" xattrs=(user.bar=bar) {', None, None)
|
||||
expected = ('/foo', '/foo', None, 'user.bar=bar', None, False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_08(self):
|
||||
result = self._parse('profile "/foo" xattrs=(user.bar=bar user.foo=*) {', None, None)
|
||||
expected = ('/foo', '/foo', None, 'user.bar=bar user.foo=*', None, False, False, False)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_parse_profile_start_unsupported_01(self):
|
||||
@@ -566,6 +576,44 @@ class AaTest_parse_profile_data(AATest):
|
||||
# file contains two profiles with the same name
|
||||
parse_profile_data('profile /foo {\n}\nprofile /foo {\n}\n'.split(), 'somefile', False)
|
||||
|
||||
def test_parse_xattrs_01(self):
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar) {\n}\n'.split(), 'somefile', False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
self.assertEqual(prof['/foo']['/foo']['name'], '/foo')
|
||||
self.assertEqual(prof['/foo']['/foo']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo']['/foo']['flags'], None)
|
||||
self.assertEqual(prof['/foo']['/foo']['xattrs'], 'user.bar=bar')
|
||||
|
||||
def test_parse_xattrs_02(self):
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar user.foo=*) {\n}\n'.split(), 'somefile', False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
self.assertEqual(prof['/foo']['/foo']['name'], '/foo')
|
||||
self.assertEqual(prof['/foo']['/foo']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo']['/foo']['flags'], None)
|
||||
self.assertEqual(prof['/foo']['/foo']['xattrs'], 'user.bar=bar user.foo=*')
|
||||
|
||||
def test_parse_xattrs_03(self):
|
||||
d = '/foo xattrs=(user.bar=bar) flags=(complain) {\n}\n'
|
||||
prof = parse_profile_data(d.split(), 'somefile', False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
self.assertEqual(prof['/foo']['/foo']['name'], '/foo')
|
||||
self.assertEqual(prof['/foo']['/foo']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo']['/foo']['flags'], 'complain')
|
||||
self.assertEqual(prof['/foo']['/foo']['xattrs'], 'user.bar=bar')
|
||||
|
||||
def test_parse_xattrs_04(self):
|
||||
with self.assertRaises(AppArmorException):
|
||||
# flags before xattrs
|
||||
d = '/foo flags=(complain) xattrs=(user.bar=bar) {\n}\n'
|
||||
parse_profile_data(d.split(), 'somefile', False)
|
||||
|
||||
|
||||
class AaTest_separate_vars(AATest):
|
||||
tests = [
|
||||
('' , set() ),
|
||||
@@ -669,11 +717,50 @@ class AaTest_write_header(AATest):
|
||||
embedded_hat = params[1]
|
||||
write_flags = params[2]
|
||||
depth = params[3]
|
||||
prof_data = { 'flags': params[4], 'attachment': params[5], 'profile_keyword': params[6], 'header_comment': params[7] }
|
||||
prof_data = { 'flags': params[4], 'attachment': params[5], 'profile_keyword': params[6], 'header_comment': params[7], 'xattrs': '' }
|
||||
|
||||
result = write_header(prof_data, depth, name, embedded_hat, write_flags)
|
||||
self.assertEqual(result, [expected])
|
||||
|
||||
class AaTest_write_header_01(AATest):
|
||||
tests = [
|
||||
(
|
||||
{'name': '/foo', 'write_flags': True, 'depth': 1, 'flags': 'complain'},
|
||||
' /foo flags=(complain) {',
|
||||
),
|
||||
(
|
||||
{'name': '/foo', 'write_flags': True, 'depth': 1, 'flags': 'complain', 'profile_keyword': 'profile'},
|
||||
' profile /foo flags=(complain) {',
|
||||
),
|
||||
(
|
||||
{'name': '/foo', 'write_flags': True, 'flags': 'complain'},
|
||||
'/foo flags=(complain) {',
|
||||
),
|
||||
(
|
||||
{'name': '/foo', 'xattrs': 'user.foo=bar', 'write_flags': True, 'flags': 'complain'},
|
||||
'/foo xattrs=(user.foo=bar) flags=(complain) {',
|
||||
),
|
||||
(
|
||||
{'name': '/foo', 'xattrs': 'user.foo=bar', 'embedded_hat': True},
|
||||
'profile /foo xattrs=(user.foo=bar) {',
|
||||
),
|
||||
]
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
name = params['name']
|
||||
embedded_hat = params.get('embedded_hat', False)
|
||||
write_flags = params.get('write_flags', False)
|
||||
depth = params.get('depth', 0)
|
||||
prof_data = {
|
||||
'xattrs': params.get('xattrs', None),
|
||||
'flags': params.get('flags', None),
|
||||
'attachment': params.get('attachment', None),
|
||||
'profile_keyword': params.get('profile_keyword', None),
|
||||
'header_comment': params.get('header_comment', None),
|
||||
}
|
||||
result = write_header(prof_data, depth, name, embedded_hat, write_flags)
|
||||
self.assertEqual(result, [expected])
|
||||
|
||||
class AaTest_get_file_perms_1(AATest):
|
||||
tests = [
|
||||
('/usr/share/common-licenses/foo/bar', {'allow': {'all': set(), 'owner': {'w'} }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/share/common-licenses/**'} }),
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2015-2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -18,6 +18,7 @@ from apparmor.common import open_file_read
|
||||
|
||||
import apparmor.aa
|
||||
from apparmor.logparser import ReadLog
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
class TestLibapparmorTestMulti(AATest):
|
||||
'''Parse all libraries/libapparmor/testsuite/test_multi tests and compare the result with the *.out files'''
|
||||
@@ -249,9 +250,15 @@ def logfile_to_profile(logfile):
|
||||
if '//' in profile:
|
||||
profile, hat = profile.split('//')
|
||||
|
||||
apparmor.aa.existing_profiles = {profile: profile_dummy_file}
|
||||
apparmor.aa.active_profiles = ProfileList()
|
||||
|
||||
log_reader = ReadLog(dict(), logfile, apparmor.aa.existing_profiles, '')
|
||||
# optional for now, might be needed one day
|
||||
# if profile.startswith('/'):
|
||||
# apparmor.aa.active_profiles.add(profile_dummy_file, profile, profile)
|
||||
# else:
|
||||
apparmor.aa.active_profiles.add(profile_dummy_file, profile, '')
|
||||
|
||||
log_reader = ReadLog(dict(), logfile, apparmor.aa.active_profiles, '')
|
||||
log = log_reader.read_log('')
|
||||
|
||||
for root in log:
|
||||
|
@@ -40,11 +40,6 @@ skip_startswith = (
|
||||
# testcases that should raise an exception, but don't
|
||||
exception_not_raised = [
|
||||
# most abi/bad_* aren't detected as bad by the basic implementation in the tools
|
||||
'abi/bad_1.sd',
|
||||
'abi/bad_2.sd',
|
||||
'abi/bad_3.sd',
|
||||
'abi/bad_4.sd',
|
||||
'abi/bad_5.sd',
|
||||
'abi/bad_10.sd',
|
||||
'abi/bad_11.sd',
|
||||
'abi/bad_12.sd',
|
||||
@@ -155,13 +150,9 @@ exception_not_raised = [
|
||||
'unix/bad_regex_04.sd',
|
||||
'unix/bad_shutdown_1.sd',
|
||||
'unix/bad_shutdown_2.sd',
|
||||
'vars/boolean/boolean_bad_1.sd',
|
||||
'vars/boolean/boolean_bad_2.sd',
|
||||
'vars/boolean/boolean_bad_3.sd',
|
||||
'vars/boolean/boolean_bad_4.sd',
|
||||
'vars/boolean/boolean_bad_6.sd',
|
||||
'vars/boolean/boolean_bad_7.sd',
|
||||
'vars/boolean/boolean_bad_8.sd',
|
||||
'vars/vars_bad_3.sd',
|
||||
'vars/vars_bad_4.sd',
|
||||
'vars/vars_bad_5.sd',
|
||||
@@ -200,7 +191,6 @@ exception_not_raised = [
|
||||
'vars/vars_recursion_2.sd',
|
||||
'vars/vars_recursion_3.sd',
|
||||
'vars/vars_recursion_4.sd',
|
||||
'vars/vars_simple_assignment_10.sd',
|
||||
'vars/vars_simple_assignment_3.sd',
|
||||
'vars/vars_simple_assignment_8.sd',
|
||||
'vars/vars_simple_assignment_9.sd',
|
||||
|
114
utils/test/test-profile-list.py
Normal file
114
utils/test/test-profile-list.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2018 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
import unittest
|
||||
from common_test import AATest, setup_all_loops
|
||||
|
||||
from apparmor.common import AppArmorBug, AppArmorException
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
class TestAdd(AATest):
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
|
||||
def testEmpty(self):
|
||||
self.assertEqual(self.pl.profile_names, {})
|
||||
self.assertEqual(self.pl.attachments, {})
|
||||
|
||||
def testAdd_1(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
|
||||
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
|
||||
|
||||
def testAdd_2(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
self.assertEqual(self.pl.profile_names, {})
|
||||
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
|
||||
|
||||
def testAdd_3(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
|
||||
self.assertEqual(self.pl.attachments, {})
|
||||
|
||||
|
||||
def testAddError_1(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.add('', 'foo', '/bin/foo') # no filename
|
||||
|
||||
def testAddError_2(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, None) # neither attachment or profile name
|
||||
|
||||
def testAddError_twice_1(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_2(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
|
||||
def testAddError_twice_3(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_4(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_5(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
class TestFilename_from_profile_name(AATest):
|
||||
tests = [
|
||||
('foo', '/etc/apparmor.d/bin.foo'),
|
||||
('/bin/foo', None),
|
||||
('bar', None),
|
||||
]
|
||||
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(self.pl.filename_from_profile_name(params), expected)
|
||||
|
||||
class TestFilename_from_attachment(AATest):
|
||||
tests = [
|
||||
('/bin/foo', '/etc/apparmor.d/bin.foo'),
|
||||
('/bin/baz', '/etc/apparmor.d/bin.baz'),
|
||||
('/bin/foobar', '/etc/apparmor.d/bin.foobar'),
|
||||
('@{foo}', None), # XXX variables not supported yet (and @{foo} isn't defined in this test)
|
||||
('/bin/404', None),
|
||||
]
|
||||
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
self.pl.add('/etc/apparmor.d/bin.baz', 'baz', '/bin/ba*')
|
||||
self.pl.add('/etc/apparmor.d/bin.foobar', 'foobar', '/bin/foo{bar,baz}')
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(self.pl.filename_from_attachment(params), expected)
|
||||
|
||||
def test_non_path_attachment(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.filename_from_attachment('foo')
|
||||
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
Reference in New Issue
Block a user