mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 14:25:52 +00:00
Compare commits
93 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
59ec31bcb3 | ||
|
b1b046f4b6 | ||
|
53e34f9d53 | ||
|
93f080fe8e | ||
|
79d03f4279 | ||
|
d01bfaefc7 | ||
|
4d8bbf97fc | ||
|
5d030f7765 | ||
|
bcef865116 | ||
|
b86bb506ef | ||
|
64fbb1e25b | ||
|
2cedb8794c | ||
|
37e691bd8a | ||
|
5af298855f | ||
|
071eb797ef | ||
|
c7d426255b | ||
|
0729b13293 | ||
|
3396bf8d77 | ||
|
debe35adf5 | ||
|
ec44a2c46b | ||
|
4ba0e3897a | ||
|
4a9d52c7e6 | ||
|
27c931f089 | ||
|
9e22a6e1e3 | ||
|
fe64edc828 | ||
|
7ab110df19 | ||
|
244334eab3 | ||
|
4831e933f0 | ||
|
b5a2a1ec13 | ||
|
4ee00aa076 | ||
|
55da3a19c2 | ||
|
e58742c028 | ||
|
7f84e8bc4e | ||
|
8b939b8dd4 | ||
|
4c6f8352b1 | ||
|
f79ea041a4 | ||
|
4983fda88b | ||
|
3db5d76282 | ||
|
1cd34e5ce6 | ||
|
06b56e2511 | ||
|
377613433f | ||
|
6e8df906bf | ||
|
f65572d847 | ||
|
b35b15ae70 | ||
|
acf97383ae | ||
|
88acc4006d | ||
|
42c12930a3 | ||
|
9d24cef8d5 | ||
|
e35e838034 | ||
|
c848e8e270 | ||
|
f5c0fe6dce | ||
|
49f3b6649b | ||
|
543da0cee9 | ||
|
c4a2f5d9b1 | ||
|
b0f08aa9d6 | ||
|
f8cdac9017 | ||
|
4c7042c1fc | ||
|
900b595cab | ||
|
4992a6ab86 | ||
|
dd7f1817b4 | ||
|
ec93821b54 | ||
|
7497ff4353 | ||
|
c4150a1659 | ||
|
cd464446b6 | ||
|
ba23532a59 | ||
|
11d1f3812f | ||
|
51144b5cbb | ||
|
3e18c0785a | ||
|
15595eb51d | ||
|
ad30555a96 | ||
|
b0e12a5788 | ||
|
1ba978b65c | ||
|
3c2ddc2ede | ||
|
805cb2c796 | ||
|
8cb1f8f4f6 | ||
|
ff72ea9a56 | ||
|
eab43b5358 | ||
|
bf75381287 | ||
|
80efc15e18 | ||
|
49db93a79d | ||
|
935003883e | ||
|
5ee729331a | ||
|
d89478794e | ||
|
738c7c60ba | ||
|
e142376368 | ||
|
8f39da5501 | ||
|
2f774431cb | ||
|
b64bf7771a | ||
|
848664b47b | ||
|
526c902ba2 | ||
|
b73b8ed432 | ||
|
59589308eb | ||
|
2ef17fa972 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -4,6 +4,8 @@ binutils/aa-enabled
|
||||
binutils/aa-enabled.1
|
||||
binutils/aa-exec
|
||||
binutils/aa-exec.1
|
||||
binutils/aa-features-abi
|
||||
binutils/aa-features-abi.1
|
||||
binutils/aa-status
|
||||
binutils/aa-status.8
|
||||
binutils/cJSON.o
|
||||
@@ -201,8 +203,10 @@ utils/*.tmp
|
||||
utils/po/*.mo
|
||||
utils/apparmor/*.pyc
|
||||
utils/apparmor/rule/*.pyc
|
||||
utils/htmlcov/
|
||||
utils/test/common_test.pyc
|
||||
utils/test/.coverage
|
||||
utils/test/coverage-report.txt
|
||||
utils/test/htmlcov/
|
||||
utils/vim/apparmor.vim
|
||||
utils/vim/apparmor.vim.5
|
||||
|
@@ -156,12 +156,12 @@ install-arch: arch
|
||||
install -m 755 -d ${SBINDIR}
|
||||
ln -sf aa-status ${SBINDIR}/apparmor_status
|
||||
install -m 755 ${SBINTOOLS} ${SBINDIR}
|
||||
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
|
||||
|
||||
.PHONY: install-indep
|
||||
install-indep: indep
|
||||
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
|
||||
$(MAKE) install_manpages DESTDIR=${DESTDIR}
|
||||
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
|
||||
|
||||
ifndef VERBOSE
|
||||
.SILENT: clean
|
||||
|
@@ -83,7 +83,7 @@ if B<aa-enabled> doesn't have enough privileges to read the apparmor control fil
|
||||
|
||||
=item B<10>
|
||||
|
||||
AppArmor is enabled but does not have access to shared LSM interaces.
|
||||
AppArmor is enabled but does not have access to shared LSM interfaces.
|
||||
|
||||
=item B<64>
|
||||
|
||||
|
@@ -32,7 +32,7 @@ B<aa-features-abi> [OPTIONS] <SOURCE> [OUTPUT OPTIONS]
|
||||
|
||||
B<aa-features-abi> is used to extract a features abi and output to
|
||||
either stdout or a specified file. A SOURCE_OPTION must be specified.
|
||||
If an output option is not specified the features abi is writen to
|
||||
If an output option is not specified the features abi is written to
|
||||
stdout.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
@@ -20,7 +20,7 @@ void print_help(const char *command)
|
||||
{
|
||||
printf(_("%s: [options]\n"
|
||||
" options:\n"
|
||||
" -x | --exclusive Shared interfaces must be availabe\n"
|
||||
" -x | --exclusive Shared interfaces must be available\n"
|
||||
" -q | --quiet Don't print out any messages\n"
|
||||
" -h | --help Print help\n"),
|
||||
command);
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
@@ -1,13 +1,14 @@
|
||||
# Copyright (C) 2015 Canonical Ltd
|
||||
# This file is distributed under the same license as the AppArmor package.
|
||||
# John Johansen <john.johansen@canonical.com>, 2015.
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Canonical Ltd
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -16,51 +17,57 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../aa_enabled.c:26
|
||||
#: ../aa_enabled.c:21
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: [options]\n"
|
||||
" options:\n"
|
||||
" -x | --exclusive Shared interfaces must be availabe\n"
|
||||
" -q | --quiet Don't print out any messages\n"
|
||||
" -h | --help Print help\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:45
|
||||
#, c-format
|
||||
msgid "unknown or incompatible options\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:55
|
||||
#, c-format
|
||||
msgid "unknown option '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:64
|
||||
#, c-format
|
||||
msgid "Yes\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:71
|
||||
#: ../aa_enabled.c:37
|
||||
#, c-format
|
||||
msgid "No - not available on this system.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:74
|
||||
#: ../aa_enabled.c:41
|
||||
#, c-format
|
||||
msgid "No - disabled at boot.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:77
|
||||
#: ../aa_enabled.c:45
|
||||
#, c-format
|
||||
msgid "Maybe - policy interface not available.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:81
|
||||
#: ../aa_enabled.c:50
|
||||
#, c-format
|
||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:84
|
||||
#: ../aa_enabled.c:54
|
||||
#, c-format
|
||||
msgid "Error - '%s'\n"
|
||||
msgid "Partially - public shared interfaces are not available.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:58
|
||||
#, c-format
|
||||
msgid "Error - %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:73
|
||||
#, c-format
|
||||
msgid "unknown or incompatible options\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:87
|
||||
#, c-format
|
||||
msgid "unknown option '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:98
|
||||
#, c-format
|
||||
msgid "Yes\n"
|
||||
msgstr ""
|
55
binutils/po/aa_exec.pot
Normal file
55
binutils/po/aa_exec.pot
Normal file
@@ -0,0 +1,55 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Canonical Ltd
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../aa_exec.c:50
|
||||
#, c-format
|
||||
msgid ""
|
||||
"USAGE: %s [OPTIONS] <prog> <args>\n"
|
||||
"\n"
|
||||
"Confine <prog> with the specified PROFILE.\n"
|
||||
"\n"
|
||||
"OPTIONS:\n"
|
||||
" -p PROFILE, --profile=PROFILE\t\tPROFILE to confine <prog> with\n"
|
||||
" -n NAMESPACE, --namespace=NAMESPACE\tNAMESPACE to confine <prog> in\n"
|
||||
" -d, --debug\t\t\t\tshow messages with debugging information\n"
|
||||
" -i, --immediate\t\t\tchange profile immediately instead of at exec\n"
|
||||
" -v, --verbose\t\t\t\tshow messages with stats\n"
|
||||
" -h, --help\t\t\t\tdisplay this help\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_exec.c:65
|
||||
#, c-format
|
||||
msgid "[%ld] aa-exec: ERROR: "
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_exec.c:76
|
||||
#, c-format
|
||||
msgid "[%ld] aa-exec: DEBUG: "
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_exec.c:89
|
||||
#, c-format
|
||||
msgid "[%ld] "
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_exec.c:107
|
||||
#, c-format
|
||||
msgid "[%ld] exec"
|
||||
msgstr ""
|
51
binutils/po/aa_features_abi.pot
Normal file
51
binutils/po/aa_features_abi.pot
Normal file
@@ -0,0 +1,51 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Canonical Ltd
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../aa_features_abi.c:53
|
||||
#, c-format
|
||||
msgid ""
|
||||
"USAGE: %s [OPTIONS] <SOURCE> [OUTPUT OPTIONS]\n"
|
||||
"\n"
|
||||
"Output AppArmor feature abi from SOURCE to OUTPUT\n"
|
||||
"OPTIONS:\n"
|
||||
" -d, --debug show messages with debugging information\n"
|
||||
" -v, --verbose show messages with stats\n"
|
||||
" -h, --help display this help\n"
|
||||
"SOURCE:\n"
|
||||
" -f F, --file=F load features abi from file F\n"
|
||||
" -x, --extract extract features abi from the kernel\n"
|
||||
"OUTPUT OPTIONS:\n"
|
||||
" --stdout default, write features to stdout\n"
|
||||
" -w F, --write=F write features abi to the file F instead of stdout\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_features_abi.c:73
|
||||
#, c-format
|
||||
msgid "%s: ERROR: "
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_features_abi.c:85
|
||||
#, c-format
|
||||
msgid "%s: DEBUG: "
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_features_abi.c:98
|
||||
msgid "\n"
|
||||
msgstr ""
|
@@ -1 +1 @@
|
||||
3.0.0
|
||||
3.0.2
|
||||
|
@@ -58,7 +58,7 @@ if test "$with_perl" = "yes"; then
|
||||
AC_PATH_PROG(PERL, perl)
|
||||
test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings])
|
||||
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
|
||||
AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no)
|
||||
AS_IF([test -e "$perl_includedir/perl.h"], enable_perl=yes, enable_perl=no)
|
||||
fi
|
||||
|
||||
|
||||
|
@@ -70,6 +70,10 @@ AppArmor extensions to the system are not available.
|
||||
|
||||
AppArmor is available on the system but has been disabled at boot.
|
||||
|
||||
=item B<EBUSY>
|
||||
|
||||
AppArmor is available but only via private interfaces.
|
||||
|
||||
=item B<ENOENT>
|
||||
|
||||
AppArmor is available (and maybe even enforcing policy) but the interface is
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -13,7 +13,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([PYTHON_CONFIG],[`basename [$PYTHON]-config`])
|
||||
AC_PATH_TOOL([PYTHON_CONFIG],[`basename [$PYTHON]-config`])
|
||||
if test -z "$PYTHON_CONFIG"; then
|
||||
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION-config in your system path])
|
||||
fi
|
||||
|
@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
|
||||
# For more information, see:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
#
|
||||
AA_LIB_CURRENT = 8
|
||||
AA_LIB_REVISION = 0
|
||||
AA_LIB_AGE = 7
|
||||
AA_LIB_CURRENT = 9
|
||||
AA_LIB_REVISION = 1
|
||||
AA_LIB_AGE = 8
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
|
||||
|
@@ -47,6 +47,132 @@
|
||||
#define UNCONFINED "unconfined"
|
||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||
|
||||
/*
|
||||
* AppArmor kernel interfaces. Potentially used by this code to
|
||||
* implement the various library functions.
|
||||
*
|
||||
*
|
||||
* /sys/module/apparmor/parameters/ *
|
||||
*
|
||||
* Available on all kernels, some options may not be available and policy
|
||||
* may block access.
|
||||
* audit - normal,quiet_denied,quiet,noquiet,all
|
||||
* debug (bool) - turn on debug messages if enabled during compile
|
||||
* hash_policy (bool) - provide a hash of loaded policy
|
||||
* logsyscall (bool) - ignored
|
||||
* paranoid_load (bool) - whether full policy checks are done. Should only
|
||||
* be disabled for embedded device kernels
|
||||
* audit_header (bool) - include "apparmor=<mode> in messages"
|
||||
* enabled (bool) - whether apparmor is enabled. This can be
|
||||
* different than whether apparmor is available.
|
||||
* See virtualization and LSM stacking.
|
||||
* lock_policy (bool) - one way trigger. Once set policy can not be
|
||||
* loaded, replace, removed.
|
||||
* mode - global policy namespace control of whether
|
||||
* apparmor is in "enforce", "complain"
|
||||
* path_max - maximum path size. Can always be read but
|
||||
* can only be set on some kernels.
|
||||
*
|
||||
* securityfs/apparmor - usually mounted at /sys/kernel/security/apparmor/ *
|
||||
* .access - transactional interface used to query kernel
|
||||
* .ns_level - RO policy namespace level of current task
|
||||
* .ns_name - RO current policy namespace of current task
|
||||
* .ns_stacked - RO boolean if stacking is in use with the namespace
|
||||
* .null - special device file used to redirect closed fds to
|
||||
* profiles - RO virtualized text list of visible loaded profiles
|
||||
* .remove - WO names of profiles to remove
|
||||
* .replace - WO binary policy to replace (will load if not present)
|
||||
* .load - WO binary policy to load (will fail if already present)
|
||||
* revision - RO unique incrementing revision number for policy
|
||||
* .stacked - RO boolean if label is currently stacked
|
||||
* features/ - RO feature set supported by kernel
|
||||
* policy/ - RO policy loaded into kernel
|
||||
*
|
||||
*
|
||||
* /proc/<tid>/attr/apparmor/ *
|
||||
* New proc attr interface compatible with LSM stacking. Available even
|
||||
* when LSM stacking is not in use.
|
||||
* current - see /proc/<tid>/attr/current
|
||||
* exec - see /proc/<tid>/attr/exec
|
||||
* prev - see /proc/<tid>/attr/prev
|
||||
*
|
||||
* /proc/<tid>/attr/ * Old proc attr interface shared between LSMs goes
|
||||
* to first registered LSM that wants the proc interface, but can be
|
||||
* virtualized by setting the display LSM. So if LSM stacking is in
|
||||
* use this interface may belong to another LSM. Use
|
||||
* /proc/<tid>/attr/apparmor/ *
|
||||
* first if possible, and do NOT use if
|
||||
* /sys/module/apparmor/parameters/enabled=N.
|
||||
* Note: older version of the library only used this interface and did not
|
||||
* check if it was available. Which could lead to weird failures if
|
||||
* another LSM has claimed it. This version of the library tries to
|
||||
* fix this problem, but unfortunately it is impossible to completely
|
||||
* address, because access to interfaces required to determine
|
||||
* whether apparmor owns the interface may be restricted, either
|
||||
* by existing apparmor policy that has not been updated to use the
|
||||
* new interface or by another LSM.
|
||||
* current - current confinement
|
||||
* display - LSM stacking. Which LSM currently owns the interface.
|
||||
* exec - label to switch to at exec
|
||||
* fscreate - unused by apparmor
|
||||
* keycreate - unused by apparmor
|
||||
* prev - when in HAT set to parent label
|
||||
* sockcreate - unused by apparmor
|
||||
*
|
||||
*
|
||||
* Below /proc/ interface combinations are documented on how the library
|
||||
* currently behaves and how it used to behave. This serves to document
|
||||
* known failure points as we can not entirely fix this mess.
|
||||
* Note: userspace applications using the interface directly have all
|
||||
* the issues/failures of AppArmor 2.x unless they have specifically
|
||||
* been updated to deal with this mess.
|
||||
*
|
||||
*
|
||||
* AppArmor 2.x Lib
|
||||
*
|
||||
* LSM AA sys sys proc/ proc/ user
|
||||
* Stk | Blt | LSM | enabl | avail | aa/ | * | space |
|
||||
* ----+-----+-------+-------+-------+-------+-------+-------+--------+
|
||||
* N | N | - | - | - | - | N | AA2.x | - |
|
||||
* N | N | other | - | - | - | N | AA2.x | FAIL |
|
||||
* N | N | other |denied | - | - | N | AA2.x | FAIL |
|
||||
* N | Y | - | N | - | - | N | AA2.x | - |
|
||||
* N | Y | other | - | - | - | N | AA2.x | FAIL |
|
||||
* N | Y | AA | - | - | - | Y | AA2.x | PASS |
|
||||
* Y | N | - | - | - | - | N | AA2.x | - |
|
||||
* Y | N | other | - | - | - | N | AA2.x | FAIL |
|
||||
* Y | Y | - | N | - | - | N | AA2.x | - |
|
||||
* Y | Y | other | - | - | - | N | AA2.x | FAIL |
|
||||
* Y | Y | AA | - | - | - | Y | AA2.x | PASS |
|
||||
* Y | Y | major | - | - | - | Y | AA2.x | PASS |
|
||||
* Y | Y | minor | - | - | - | N | AA2.x | FAIL |
|
||||
*
|
||||
*
|
||||
* AppArmor 3.x Lib - adds stacking support.
|
||||
*
|
||||
* Will FAIL in a few cases because it can not determine if apparmor
|
||||
* is enabled and has control of the old interface. Not failing in these
|
||||
* cases where AppArmor is available will result in regressions where
|
||||
* the library will not work correctly with old kernels. In these
|
||||
* cases its better that apparmor userspace is not used.
|
||||
*
|
||||
* AppArmor 3.x will avoid the failure cases if any of enabled, avail
|
||||
* or the new proc interfaces are available to the task. AppArmor 3.x
|
||||
* will also automatically add permissions to access the new proc
|
||||
* interfaces so change_hat and change_profile won't experience these
|
||||
* failures, it will only happen for confined applications hitting the
|
||||
* interfaces and not using change_hat or change_profile.
|
||||
*
|
||||
* LSM AA sys sys proc/ proc/
|
||||
* Stk | Blt | LSM | enabl | avail | aa/ | * |
|
||||
* ----+-----+-------+-------+-------+-------+-------+-----------------
|
||||
* Y/N | N | other | denied| NA | NA | Y | old interface avail
|
||||
* Y/N | Y | other | denied| NA | NA | Y | old interface avail
|
||||
* Y | Y | minor | denied| NA | NA | Y | old interface avail
|
||||
* Y | Y | minor | denied| NA | denied| Y | old interface avail
|
||||
* Y/N | Y | minor | denied| denied| denied| Y | old interface avail
|
||||
*/
|
||||
|
||||
/**
|
||||
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
|
||||
* @mnt: returns buffer with the mountpoint string
|
||||
@@ -93,25 +219,34 @@ int aa_find_mountpoint(char **mnt)
|
||||
return rc;
|
||||
}
|
||||
|
||||
// done as a macro so we can paste the param
|
||||
/**
|
||||
* pararm_check_base - return boolean value for PARAM
|
||||
* PARAM: parameter to check
|
||||
*
|
||||
* Returns: 1 == Y
|
||||
* 0 == N
|
||||
* <0 == error
|
||||
*
|
||||
* done as a macro so we can paste the param
|
||||
*/
|
||||
|
||||
#define param_check_base(PARAM) \
|
||||
({ \
|
||||
int rc, fd; \
|
||||
fd = open("/sys/module/apparmor/parameters/" PARAM, O_RDONLY); \
|
||||
if (fd == -1) { \
|
||||
rc = errno; \
|
||||
rc = -errno; \
|
||||
} else { \
|
||||
char buffer[2]; \
|
||||
int size = read(fd, &buffer, 2); \
|
||||
rc = errno; \
|
||||
rc = -errno; \
|
||||
close(fd); \
|
||||
errno = rc; \
|
||||
errno = -rc; \
|
||||
if (size > 0) { \
|
||||
if (buffer[0] == 'Y') \
|
||||
rc = 0; \
|
||||
rc = 1; \
|
||||
else \
|
||||
rc = ECANCELED; \
|
||||
rc = 0; \
|
||||
} \
|
||||
} \
|
||||
(rc); \
|
||||
@@ -130,31 +265,37 @@ static void param_check_enabled_init_once(void)
|
||||
|
||||
static int param_check_enabled()
|
||||
{
|
||||
if (pthread_once(¶m_enabled_ctl, param_check_enabled_init_once) == 0)
|
||||
if (pthread_once(¶m_enabled_ctl, param_check_enabled_init_once) == 0 && param_enabled >= 0)
|
||||
return param_enabled;
|
||||
/* fallback if not initialized OR we recorded an error when
|
||||
* initializing.
|
||||
*/
|
||||
return param_check_base("enabled");
|
||||
}
|
||||
|
||||
static int is_enabled(void)
|
||||
{
|
||||
return !param_check_enabled();
|
||||
return param_check_enabled() == 1;
|
||||
}
|
||||
|
||||
static void param_check_private_enabled_init_once(void)
|
||||
{
|
||||
param_enabled = param_check_base("private_enabled");
|
||||
param_private_enabled = param_check_base("available");
|
||||
}
|
||||
|
||||
static int param_check_private_enabled()
|
||||
{
|
||||
if (pthread_once(¶m_private_enabled_ctl, param_check_private_enabled_init_once) == 0)
|
||||
if (pthread_once(¶m_private_enabled_ctl, param_check_private_enabled_init_once) == 0 && param_private_enabled >= 0)
|
||||
return param_private_enabled;
|
||||
return param_check_base("private_enabled");
|
||||
/* fallback if not initialized OR we recorded an error when
|
||||
* initializing.
|
||||
*/
|
||||
return param_check_base("available");
|
||||
}
|
||||
|
||||
static int is_private_enabled(void)
|
||||
{
|
||||
return !param_check_private_enabled();
|
||||
return param_check_private_enabled() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,15 +315,17 @@ int aa_is_enabled(void)
|
||||
bool private = false;
|
||||
|
||||
rc = param_check_enabled();
|
||||
if (rc) {
|
||||
if (rc == ENOENT)
|
||||
errno = ENOSYS;
|
||||
else
|
||||
errno = rc;
|
||||
if (rc < 1) {
|
||||
if (!is_private_enabled()) {
|
||||
if (rc == 0)
|
||||
errno = ECANCELED;
|
||||
else if (rc == -ENOENT)
|
||||
errno = ENOSYS;
|
||||
else
|
||||
errno = -rc;
|
||||
|
||||
if (!is_private_enabled())
|
||||
return 0;
|
||||
|
||||
}
|
||||
/* actually available but only on private interfaces */
|
||||
private = true;
|
||||
}
|
||||
@@ -227,41 +370,128 @@ static inline pid_t aa_gettid(void)
|
||||
* present.
|
||||
*/
|
||||
static pthread_once_t proc_attr_base_ctl = PTHREAD_ONCE_INIT;
|
||||
static char *proc_attr_base = "/proc/%d/attr/%s";
|
||||
static char *proc_attr_base_stacking = "/proc/%d/attr/apparmor/%s";
|
||||
static char *proc_attr_base_unavailable = "/proc/%d/attr/apparmor/unavailable/%s";
|
||||
static const char *proc_attr_base_old = "/proc/%d/attr/%s";
|
||||
static const char *proc_attr_new_dir = "/proc/%d/attr/apparmor/";
|
||||
static const char *proc_attr_base_stacking = "/proc/%d/attr/apparmor/%s";
|
||||
static const char *proc_attr_base_unavailable = "/proc/%d/attr/apparmor/unavailable/%s";
|
||||
static const char *proc_attr_base = NULL;
|
||||
static int proc_stacking_present = -1; /* unknown */
|
||||
|
||||
static void proc_attr_base_init_once(void)
|
||||
{
|
||||
autofree char *tmp;
|
||||
|
||||
/* if we fail we just fall back to the default value */
|
||||
if (asprintf(&tmp, "/proc/%d/attr/apparmor/current", aa_gettid())) {
|
||||
autoclose int fd = open(tmp, O_RDONLY);
|
||||
if (fd != -1)
|
||||
if (asprintf(&tmp, proc_attr_new_dir, aa_gettid()) > 0) {
|
||||
struct stat sb;
|
||||
if (stat(tmp, &sb) == 0) {
|
||||
proc_attr_base = proc_attr_base_stacking;
|
||||
} else if (!is_enabled() && is_private_enabled()) {
|
||||
/* new stacking interfaces aren't available and apparmor
|
||||
* is disabled, but available. do not use the
|
||||
* /proc/<pid>/attr/ * interfaces as they could be
|
||||
* in use by another LSM
|
||||
proc_stacking_present = 1;
|
||||
return;
|
||||
} else if (errno == ENOENT) {
|
||||
/* no stacking - try falling back */
|
||||
proc_stacking_present = 0;
|
||||
} else if (errno == EACCES) {
|
||||
/* the dir exists, but access is denied */
|
||||
proc_stacking_present = 1;
|
||||
proc_attr_base = proc_attr_base_stacking;
|
||||
} /* else
|
||||
denied by policy, or other error try falling back */
|
||||
} else {
|
||||
/* failed allocation - proc_attr_base stays NULL */
|
||||
return;
|
||||
}
|
||||
/* check for new interface failed, see if we can fallback */
|
||||
if (param_check_enabled() == 0) {
|
||||
/* definate NO (not just an error) on enabled. Do not fall
|
||||
* back to old shared proc interface
|
||||
*
|
||||
* First try an alternate check for private proc interface
|
||||
*/
|
||||
int enabled = param_check_private_enabled();
|
||||
if (enabled == 1) {
|
||||
/* the private interface exists and we can't
|
||||
* fallback so just keep trying on the new
|
||||
* interface.
|
||||
*/
|
||||
proc_attr_base = proc_attr_base_stacking;
|
||||
} else if (enabled == 0) {
|
||||
/* definite NO - no interface available */
|
||||
proc_attr_base = proc_attr_base_unavailable;
|
||||
} else {
|
||||
/* error can't determine, proc_attr_base stays NULL */
|
||||
}
|
||||
} else if (param_check_enabled() == 1) {
|
||||
/* apparmor is enabled, we can use the old interface */
|
||||
proc_attr_base = proc_attr_base_old;
|
||||
} else if (errno != EACCES) {
|
||||
/* this shouldn't happen unless apparmor is not builtin
|
||||
* or proc isn't mounted
|
||||
*/
|
||||
proc_attr_base = proc_attr_base_unavailable;
|
||||
}
|
||||
/* else default to pre-assigned value */
|
||||
} /* else
|
||||
denied by policy - proc_attr_base stays NULL */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static char *procattr_path(pid_t pid, const char *attr)
|
||||
{
|
||||
char *path = NULL;
|
||||
const char *tmp;
|
||||
|
||||
/* TODO: rework this with futex or userspace RCU so we can update
|
||||
* the base value instead of continually using the same base
|
||||
* after we have hit an error
|
||||
*/
|
||||
/* ignore failure, we just fallback to the default value */
|
||||
(void) pthread_once(&proc_attr_base_ctl, proc_attr_base_init_once);
|
||||
if (asprintf(&path, proc_attr_base, pid, attr) > 0)
|
||||
|
||||
if (proc_attr_base)
|
||||
tmp = proc_attr_base;
|
||||
else if (proc_stacking_present)
|
||||
/* couldn't determine during init */
|
||||
tmp = proc_attr_base_stacking;
|
||||
else
|
||||
/* couldn't determine during init and no stacking */
|
||||
tmp = proc_attr_base_old;
|
||||
if (asprintf(&path, tmp, pid, attr) > 0)
|
||||
return path;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int procattr_open(pid_t tid, const char *attr, int flags)
|
||||
{
|
||||
char *tmp;
|
||||
int fd;
|
||||
|
||||
tmp = procattr_path(tid, attr);
|
||||
if (!tmp) {
|
||||
return -1;
|
||||
}
|
||||
fd = open(tmp, flags);
|
||||
free(tmp);
|
||||
/* Test is we can fallback to the old interface (this is ugly).
|
||||
* If we haven't tried the old interface already
|
||||
* proc_attr_base == proc_attr_base_old - no fallback
|
||||
* else if is_enabled()
|
||||
* apparmor is available on the old interface
|
||||
* we do NOT use is_private_enabled() as
|
||||
* 1. the new private interface would have been tried first above
|
||||
* 2. that can be true even when another LSM is using the
|
||||
* old interface where is_enabled() is only successful if
|
||||
* the old interface is available to apparmor.
|
||||
*/
|
||||
if (fd == -1 && tmp != proc_attr_base_old && param_check_enabled() != 0) {
|
||||
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0)
|
||||
return -1;
|
||||
fd = open(tmp, flags);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_unconfined - check for the unconfined label
|
||||
* @con: the confinement context
|
||||
@@ -371,12 +601,7 @@ int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = procattr_path(tid, attr);
|
||||
if (!tmp)
|
||||
goto out;
|
||||
|
||||
fd = open(tmp, O_RDONLY);
|
||||
free(tmp);
|
||||
fd = procattr_open(tid, attr, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
goto out;
|
||||
}
|
||||
@@ -487,18 +712,13 @@ static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
|
||||
{
|
||||
int rc = -1;
|
||||
int fd, ret;
|
||||
char *ctl = NULL;
|
||||
|
||||
if (!buf) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctl = procattr_path(tid, attr);
|
||||
if (!ctl)
|
||||
goto out;
|
||||
|
||||
fd = open(ctl, O_WRONLY);
|
||||
fd = procattr_open(tid, attr, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
goto out;
|
||||
}
|
||||
@@ -519,9 +739,6 @@ static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
|
||||
(void)close(fd);
|
||||
|
||||
out:
|
||||
if (ctl) {
|
||||
free(ctl);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -117,6 +117,7 @@ APPARMOR_2.13.1 {
|
||||
|
||||
APPARMOR_3.0 {
|
||||
global:
|
||||
aa_features_new_from_file;
|
||||
aa_features_write_to_fd;
|
||||
aa_features_value;
|
||||
local:
|
||||
@@ -126,6 +127,7 @@ APPARMOR_3.0 {
|
||||
PRIVATE {
|
||||
global:
|
||||
_aa_is_blacklisted;
|
||||
_aa_asprintf;
|
||||
_aa_autofree;
|
||||
_aa_autoclose;
|
||||
_aa_autofclose;
|
||||
|
@@ -474,7 +474,7 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_dirs = readdirfd(cb_dirfd, &namelist, NULL);
|
||||
num_dirs = readdirfd(cb_dirfd, &namelist, alphasort);
|
||||
if (num_dirs == -1) {
|
||||
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
|
||||
return -1;
|
||||
|
@@ -14,7 +14,7 @@ MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
|
||||
|
||||
all-local: libapparmor_wrap.c setup.py
|
||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS)" $(PYTHON) setup.py build
|
||||
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
|
||||
|
||||
install-exec-local:
|
||||
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"
|
||||
|
@@ -54,7 +54,7 @@ endif
|
||||
CPPFLAGS += -D_GNU_SOURCE
|
||||
|
||||
STDLIB_INCLUDE:="\#include <stdlib.h>"
|
||||
HAVE_REALLOCARRAY:=$(shell echo $(STDLIB_INCLUDE) | cpp ${CPPFLAGS} | grep -q reallocarray && echo true)
|
||||
HAVE_REALLOCARRAY:=$(shell echo $(STDLIB_INCLUDE) | ${CPP} ${CPPFLAGS} - - | grep -q reallocarray && echo true)
|
||||
|
||||
WARNINGS = -Wall
|
||||
CXX_WARNINGS = ${WARNINGS} ${EXTRA_WARNINGS}
|
||||
@@ -102,7 +102,7 @@ SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
|
||||
af_rule.cc af_unix.cc policy_cache.c default_features.c
|
||||
HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h \
|
||||
rule.h common_optarg.h signal.h ptrace.h network.h af_rule.h af_unix.h \
|
||||
policy_cache.h
|
||||
policy_cache.h file_cache.h
|
||||
TOOLS = apparmor_parser
|
||||
|
||||
OBJECTS = $(patsubst %.cc, %.o, $(SRCS:.c=.o))
|
||||
@@ -215,10 +215,10 @@ apparmor_parser: $(OBJECTS) $(AAREOBJECTS) $(LIBAPPARMOR_A)
|
||||
$(CXX) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
|
||||
${LEXLIB} $(AAREOBJECTS) $(AARE_LDFLAGS) $(AALIB)
|
||||
|
||||
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h profile.h
|
||||
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h profile.h file_cache.h
|
||||
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
|
||||
|
||||
parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h mount.h dbus.h policy_cache.h
|
||||
parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h mount.h dbus.h policy_cache.h file_cache.h
|
||||
$(LEX) ${LEXFLAGS} -o$@ $<
|
||||
|
||||
parser_lex.o: parser_lex.c parser.h parser_yacc.h
|
||||
@@ -230,13 +230,13 @@ parser_misc.o: parser_misc.c parser.h parser_yacc.h profile.h cap_names.h $(APPA
|
||||
parser_yacc.o: parser_yacc.c parser_yacc.h $(APPARMOR_H)
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_main.o: parser_main.c parser.h parser_version.h policy_cache.h libapparmor_re/apparmor_re.h $(APPARMOR_H)
|
||||
parser_main.o: parser_main.c parser.h parser_version.h policy_cache.h file_cache.h libapparmor_re/apparmor_re.h $(APPARMOR_H)
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_interface.o: parser_interface.c parser.h profile.h libapparmor_re/apparmor_re.h
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_include.o: parser_include.c parser.h parser_include.h
|
||||
parser_include.o: parser_include.c parser.h parser_include.h file_cache.h
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_merge.o: parser_merge.c parser.h profile.h
|
||||
@@ -257,7 +257,7 @@ parser_policy.o: parser_policy.c parser.h parser_yacc.h profile.h
|
||||
parser_alias.o: parser_alias.c parser.h profile.h
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_common.o: parser_common.c parser.h
|
||||
parser_common.o: parser_common.c parser.h file_cache.h
|
||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
mount.o: mount.cc mount.h parser.h immunix.h rule.h
|
||||
|
@@ -194,14 +194,18 @@ void unix_rule::downgrade_rule(Profile &prof) {
|
||||
yyerror(_("Memory allocation error."));
|
||||
if (sock_type_n != -1)
|
||||
mask = 1 << sock_type_n;
|
||||
if (deny) {
|
||||
prof.net.deny[AF_UNIX] |= mask;
|
||||
if (!audit)
|
||||
prof.net.quiet[AF_UNIX] |= mask;
|
||||
} else {
|
||||
if (!deny) {
|
||||
prof.net.allow[AF_UNIX] |= mask;
|
||||
if (audit)
|
||||
prof.net.audit[AF_UNIX] |= mask;
|
||||
} else {
|
||||
/* deny rules have to be dropped because the downgrade makes
|
||||
* the rule less specific meaning it will make the profile more
|
||||
* restrictive and may end up denying accesses that might be
|
||||
* allowed by the profile.
|
||||
*/
|
||||
if (warnflags & WARN_RULE_NOT_ENFORCED)
|
||||
rule_t::warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1273,7 +1273,7 @@ I<auto> keyword. Eg.
|
||||
To indicate that the rule only applies to auto binding of unix domain
|
||||
sockets. It is important to note this only applies to the I<bind>
|
||||
permission as once the socket is bound to an address it is
|
||||
indistiguishable from a socket that have an addr bound with a
|
||||
indistinguishable from a socket that have an addr bound with a
|
||||
specified name. When the I<auto> keyword is used with other permissions
|
||||
or as part of a peer addr it will be replaced with a pattern that
|
||||
can match an autobound socket. Eg. For some kernels
|
||||
@@ -1752,7 +1752,7 @@ If the policy abi is specified as B<kernel> then the running kernel's
|
||||
abi will be used. This should never be used in shipped policy as it
|
||||
can cause system breakage when a new kernel is installed.
|
||||
|
||||
=head3 ABI compatability with AppArmor 2.x
|
||||
=head3 ABI compatibility with AppArmor 2.x
|
||||
|
||||
AppArmor 3 remains compatible with AppArmor 2.x by detecting when a
|
||||
profile does not have a feature ABI specified. In this case the policy
|
||||
|
@@ -352,12 +352,15 @@ Eg.
|
||||
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
|
||||
-jx1 is equivalent to -jauto
|
||||
|
||||
The default value is the number of cpus in the system.
|
||||
The default value is the number of cpus in the system. Note that if jobs
|
||||
is a positive integer number the --jobs-max parameter is automatically
|
||||
set to the same value.
|
||||
|
||||
=item --max-jobs n
|
||||
|
||||
Set a hard cap on the value that can be specified by the --jobs flag.
|
||||
It takes the same set of options available to the --jobs option, and
|
||||
When --jobs is set to a scaling value (ie. auto or xN) the specify a
|
||||
hard cap on the value that can be specified by the --jobs flag. It
|
||||
takes the same set of options available to the --jobs option, and
|
||||
defaults to 8*cpus
|
||||
|
||||
=item -O n, --optimize=n
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
AppArmor profile xattr(7) matching
|
||||
apparmor_xattrs - AppArmor profile xattr(7) matching
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
@@ -8,6 +8,8 @@
|
||||
|
||||
{"bpf", CAP_BPF, CAP_SYS_ADMIN, CAPFLAG_BASE_FEATURE},
|
||||
|
||||
{"checkpoint_restore", CAP_CHECKPOINT_RESTORE, CAP_SYS_ADMIN, CAPFLAG_BASE_FEATURE},
|
||||
|
||||
{"chown", CAP_CHOWN, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE},
|
||||
|
||||
{"dac_override", CAP_DAC_OVERRIDE, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE},
|
||||
|
@@ -29,6 +29,10 @@
|
||||
#define CAP_BPF 39
|
||||
#endif
|
||||
|
||||
#ifndef CAP_CHECKPOINT_RESTORE
|
||||
#define CAP_CHECKPOINT_RESTORE 40
|
||||
#endif
|
||||
|
||||
typedef enum capability_flags {
|
||||
CAPFLAGS_CLEAR = 0,
|
||||
CAPFLAG_BASE_FEATURE = 1,
|
||||
|
52
parser/file_cache.h
Normal file
52
parser/file_cache.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2021
|
||||
* 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 Canonical Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __AA_FILE_CACHE_H
|
||||
#define __AA_FILE_CACHE_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* TODO: have includecache be a frontend for file cache, don't just
|
||||
* store name.
|
||||
*/
|
||||
class IncludeCache_t {
|
||||
public:
|
||||
set<string> cache;
|
||||
|
||||
IncludeCache_t() = default;
|
||||
virtual ~IncludeCache_t() = default;
|
||||
|
||||
/* return true if in set */
|
||||
bool find(const char *name) {
|
||||
return cache.find(name) != cache.end();
|
||||
}
|
||||
|
||||
bool insert(const char *name) {
|
||||
pair<set<string>::iterator,bool> res = cache.insert(name);
|
||||
if (res.second == false) {
|
||||
return false;
|
||||
}
|
||||
/* inserted */
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __AA_FILE_CACHE_H */
|
@@ -65,10 +65,15 @@
|
||||
### policy to be used in AppArmor 3.x without the warning
|
||||
### Warning from stdin (stdin line 1): apparmor_parser: File 'example'
|
||||
### missing feature abi, falling back to default policy feature abi.
|
||||
### For more info please see
|
||||
### https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorpolicyfeaturesabi
|
||||
|
||||
### Turn off abi rule warnings without pinning the abi
|
||||
#warn=no-abi
|
||||
|
||||
### Only a single feature ABI rule should be used at a time.
|
||||
## Pin older policy to the 5.4 kernel abi
|
||||
#policy-features=/etc/apparmor.d/abi/kernel-5.4-outoftree-network
|
||||
#policy-features=/etc/apparmor.d/abi/kernel-5.4-vanilla
|
||||
|
||||
## Pin older policy to the 5.4 kernel abi + out of tree network and af_unix
|
||||
#policy-features=/etc/apparmor.d/abi/kernel-5.4-vanilla
|
||||
#policy-features=/etc/apparmor.d/abi/kernel-5.4-outoftree-network
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
#include "file_cache.h"
|
||||
#include "immunix.h"
|
||||
#include "libapparmor_re/apparmor_re.h"
|
||||
#include "libapparmor_re/aare_rules.h"
|
||||
@@ -353,6 +354,8 @@ extern char *profile_ns;
|
||||
extern char *current_filename;
|
||||
extern FILE *ofile;
|
||||
extern int read_implies_exec;
|
||||
extern IncludeCache_t *g_includecache;
|
||||
|
||||
extern void pwarnf(bool werr, const char *fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
|
||||
extern void common_warn_once(const char *name, const char *msg, const char **warned_name);
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "parser.h"
|
||||
#include "file_cache.h"
|
||||
|
||||
/* Policy versioning is determined by a combination of 3 values:
|
||||
* policy_version: version of txt policy
|
||||
@@ -95,6 +96,8 @@ char *current_filename = NULL;
|
||||
|
||||
FILE *ofile = NULL;
|
||||
|
||||
IncludeCache_t *g_includecache;
|
||||
|
||||
#ifdef FORCE_READ_IMPLIES_EXEC
|
||||
int read_implies_exec = 1;
|
||||
#else
|
||||
|
@@ -151,7 +151,7 @@ void parse_default_paths(void)
|
||||
add_search_dir(basedir);
|
||||
}
|
||||
|
||||
FILE *search_path(char *filename, char **fullpath)
|
||||
FILE *search_path(char *filename, char **fullpath, bool *skip)
|
||||
{
|
||||
FILE *newf = NULL;
|
||||
char *buf = NULL;
|
||||
@@ -161,15 +161,27 @@ FILE *search_path(char *filename, char **fullpath)
|
||||
perror("asprintf");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (g_includecache->find(buf)) {
|
||||
/* hit do not want to re-include */
|
||||
*skip = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newf = fopen(buf, "r");
|
||||
if (newf && fullpath)
|
||||
*fullpath = buf;
|
||||
else
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
if (newf)
|
||||
if (newf) {
|
||||
/* ignore failing to insert into cache */
|
||||
(void) g_includecache->insert(buf);
|
||||
if (fullpath)
|
||||
*fullpath = buf;
|
||||
else
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
*skip = false;
|
||||
return newf;
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ extern void init_base_dir(void);
|
||||
extern void set_base_dir(char *dir);
|
||||
extern void parse_default_paths(void);
|
||||
extern int do_include_preprocessing(char *profilename);
|
||||
FILE *search_path(char *filename, char **fullpath);
|
||||
FILE *search_path(char *filename, char **fullpath, bool *skip);
|
||||
|
||||
extern void push_include_stack(char *filename);
|
||||
extern void pop_include_stack(void);
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "parser_yacc.h"
|
||||
#include "lib.h"
|
||||
#include "policy_cache.h"
|
||||
#include "file_cache.h"
|
||||
|
||||
#ifdef PDEBUG
|
||||
#undef PDEBUG
|
||||
@@ -134,10 +135,17 @@ static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
if (is_blacklisted(name, path))
|
||||
return 0;
|
||||
|
||||
if (g_includecache->find(path)) {
|
||||
PDEBUG("skipping reinclude of \'%s\' in \'%s\'\n", path,
|
||||
d->filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
if (!(yyin = fopen(path,"r")))
|
||||
yyerror(_("Could not open '%s' in '%s'"), path, d->filename);
|
||||
PDEBUG("Opened include \"%s\" in \"%s\"\n", path, d->filename);
|
||||
(void) g_includecache->insert(path);
|
||||
update_mru_tstamp(yyin, path);
|
||||
push_include_stack(path);
|
||||
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
@@ -151,16 +159,29 @@ void include_filename(char *filename, int search, bool if_exists)
|
||||
FILE *include_file = NULL;
|
||||
struct stat my_stat;
|
||||
autofree char *fullpath = NULL;
|
||||
bool cached;
|
||||
|
||||
if (search) {
|
||||
if (preprocess_only)
|
||||
include_file = search_path(filename, &fullpath, &cached);
|
||||
if (!include_file && cached) {
|
||||
goto skip;
|
||||
} else if (preprocess_only) {
|
||||
fprintf(yyout, "\n\n##included <%s>\n", filename);
|
||||
include_file = search_path(filename, &fullpath);
|
||||
} else if (!include_file && preprocess_only) {
|
||||
fprintf(yyout, "\n\n##failed include <%s>\n", filename);
|
||||
}
|
||||
|
||||
} else if (g_includecache->find(filename)) {
|
||||
/* duplicate entry skip */
|
||||
goto skip;
|
||||
} else {
|
||||
if (preprocess_only)
|
||||
fprintf(yyout, "\n\n##included \"%s\"\n", filename);
|
||||
fullpath = strdup(filename);
|
||||
include_file = fopen(fullpath, "r");
|
||||
if (include_file)
|
||||
/* ignore failure to insert into cache */
|
||||
(void) g_includecache->insert(filename);
|
||||
}
|
||||
|
||||
if (!include_file) {
|
||||
@@ -181,6 +202,7 @@ void include_filename(char *filename, int search, bool if_exists)
|
||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||
} else if (S_ISDIR(my_stat.st_mode)) {
|
||||
struct cb_struct data = { fullpath, filename };
|
||||
update_mru_tstamp(include_file, fullpath);
|
||||
fclose(include_file);
|
||||
include_file = NULL;
|
||||
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
|
||||
@@ -188,6 +210,13 @@ void include_filename(char *filename, int search, bool if_exists)
|
||||
" '%s' in '%s'"), fullpath, filename);;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
skip:
|
||||
if (preprocess_only)
|
||||
fprintf(yyout, "\n\n##skipped duplicate include <%s>\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
static char *lsntrim(char *s, int l)
|
||||
|
@@ -50,6 +50,7 @@
|
||||
#include "common_optarg.h"
|
||||
#include "policy_cache.h"
|
||||
#include "libapparmor_re/apparmor_re.h"
|
||||
#include "file_cache.h"
|
||||
|
||||
#define OLD_MODULE_NAME "subdomain"
|
||||
#define PROC_MODULES "/proc/modules"
|
||||
@@ -259,7 +260,7 @@ optflag_table_t warnflag_table[] = {
|
||||
{ 1, "jobs", "enable job control warnings", WARN_JOBS },
|
||||
{ 1, "dangerous", "warn on dangerous policy", WARN_DANGEROUS },
|
||||
{ 1, "unexpected", "warn when an unexpected condition is found", WARN_UNEXPECTED },
|
||||
{ 1, "format", "warn on unnecessary or confusing formating", WARN_FORMAT },
|
||||
{ 1, "format", "warn on unnecessary or confusing formatting", WARN_FORMAT },
|
||||
{ 1, "missing", "warn when missing qualifier and a default is used", WARN_MISSING },
|
||||
{ 1, "override", "warn when overriding", WARN_OVERRIDE },
|
||||
{ 1, "dev", "turn on warnings that are useful for profile development", WARN_DEV },
|
||||
@@ -730,6 +731,8 @@ static int process_arg(int c, char *optarg)
|
||||
jobs = process_jobs_arg("-j", optarg);
|
||||
if (jobs == 0)
|
||||
jobs_max = 0;
|
||||
else if (jobs != JOBS_AUTO && jobs < LONG_MAX)
|
||||
jobs_max = jobs;
|
||||
break;
|
||||
case ARG_MAX_JOBS:
|
||||
jobs_max = process_jobs_arg("max-jobs", optarg);
|
||||
@@ -1000,6 +1003,8 @@ void reset_parser(const char *filename)
|
||||
aa_features_unref(policy_features);
|
||||
policy_features = NULL;
|
||||
clear_cap_flag(CAPFLAG_POLICY_FEATURE);
|
||||
delete g_includecache;
|
||||
g_includecache = new IncludeCache_t();
|
||||
}
|
||||
|
||||
int test_for_dir_mode(const char *basename, const char *linkdir)
|
||||
@@ -1159,9 +1164,11 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
/* cache file generated by load_policy */
|
||||
retval = load_policy(option, kernel_interface, cachetmp);
|
||||
if (retval == 0 && write_cache) {
|
||||
if (cachetmp == -1) {
|
||||
if (force_complain) {
|
||||
pwarn(WARN_CACHE, "Caching disabled for: '%s' due to force complain\n", basename);
|
||||
} else if (cachetmp == -1) {
|
||||
unlink(cachetmpname);
|
||||
pwarn(WARN_CACHE, "Warning failed to create cache: %s\n",
|
||||
pwarn(WARN_CACHE, "Failed to create cache: %s\n",
|
||||
basename);
|
||||
} else {
|
||||
install_cache(cachetmpname, writecachename);
|
||||
@@ -1295,6 +1302,8 @@ static void setup_parallel_compile(void)
|
||||
if (maxn == -1)
|
||||
/* unable to determine number of processors, default to 1 */
|
||||
maxn = 1;
|
||||
if (jobs < 0 || jobs == JOBS_AUTO)
|
||||
jobs_scale = 1;
|
||||
jobs = compute_jobs(n, jobs);
|
||||
jobs_max = compute_jobs(maxn, jobs_max);
|
||||
|
||||
@@ -1302,7 +1311,7 @@ static void setup_parallel_compile(void)
|
||||
pwarn(WARN_JOBS, "%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
||||
progname, jobs_max, jobs);
|
||||
jobs = jobs_max;
|
||||
} else if (jobs < jobs_max)
|
||||
} else if (jobs_scale && jobs < jobs_max)
|
||||
/* the bigger the difference the more sample chances given */
|
||||
jobs_scale = jobs_max + 1 - n;
|
||||
|
||||
|
@@ -326,7 +326,8 @@ bool add_cap_feature_mask(struct aa_features *features, capability_flags flags)
|
||||
|
||||
value = aa_features_value(features, "caps/mask", &valuelen);
|
||||
if (!value)
|
||||
return false;
|
||||
/* nothing to add, just use existing set */
|
||||
return true;
|
||||
|
||||
n = 0;
|
||||
for (capstr = strn_token(value, len);
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "parser.h"
|
||||
#include "profile.h"
|
||||
#include "parser_yacc.h"
|
||||
@@ -145,6 +146,56 @@ void add_entry_to_policy(Profile *prof, struct cod_entry *entry)
|
||||
prof->entries = entry;
|
||||
}
|
||||
|
||||
static bool add_proc_access(Profile *prof, const char *rule)
|
||||
{
|
||||
/* FIXME: should use @{PROC}/@{PID}/attr/{apparmor/,}{current,exec} */
|
||||
struct cod_entry *new_ent;
|
||||
/* allow probe for new interfaces */
|
||||
char *buffer = strdup("/proc/*/attr/apparmor/");
|
||||
if (!buffer) {
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
new_ent = new_entry(buffer, AA_MAY_READ, NULL);
|
||||
if (!new_ent) {
|
||||
free(buffer);
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
add_entry_to_policy(prof, new_ent);
|
||||
|
||||
/* allow probe if apparmor is enabled for the old interface */
|
||||
buffer = strdup("/sys/module/apparmor/parameters/enabled");
|
||||
if (!buffer) {
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
new_ent = new_entry(buffer, AA_MAY_READ, NULL);
|
||||
if (!new_ent) {
|
||||
free(buffer);
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
add_entry_to_policy(prof, new_ent);
|
||||
|
||||
/* allow setting on new and old interfaces */
|
||||
buffer = strdup(rule);
|
||||
if (!buffer) {
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
new_ent = new_entry(buffer, AA_MAY_WRITE, NULL);
|
||||
if (!new_ent) {
|
||||
free(buffer);
|
||||
PERROR("Memory allocation error\n");
|
||||
return FALSE;
|
||||
}
|
||||
add_entry_to_policy(prof, new_ent);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define CHANGEPROFILE_PATH "/proc/*/attr/{apparmor/,}{current,exec}"
|
||||
void post_process_file_entries(Profile *prof)
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
@@ -170,22 +221,11 @@ void post_process_file_entries(Profile *prof)
|
||||
}
|
||||
|
||||
/* if there are change_profile rules, this implies that we need
|
||||
* access to /proc/self/attr/current
|
||||
* access to some /proc/ interfaces
|
||||
*/
|
||||
if (cp_mode & AA_CHANGE_PROFILE) {
|
||||
/* FIXME: should use @{PROC}/@{PID}/attr/{apparmor/,}{current,exec} */
|
||||
struct cod_entry *new_ent;
|
||||
char *buffer = strdup("/proc/*/attr/{apparmor/,}{current,exec}");
|
||||
if (!buffer) {
|
||||
PERROR("Memory allocation error\n");
|
||||
if (!add_proc_access(prof, CHANGEPROFILE_PATH))
|
||||
exit(1);
|
||||
}
|
||||
new_ent = new_entry(buffer, AA_MAY_WRITE, NULL);
|
||||
if (!new_ent) {
|
||||
PERROR("Memory allocation error\n");
|
||||
exit(1);
|
||||
}
|
||||
add_entry_to_policy(prof, new_ent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,19 +242,13 @@ void post_process_rule_entries(Profile *prof)
|
||||
*/
|
||||
static int profile_add_hat_rules(Profile *prof)
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
|
||||
/* don't add hat rules if not hat or profile doesn't have hats */
|
||||
if (!prof->flags.hat && prof->hat_table.empty())
|
||||
return 0;
|
||||
|
||||
/* add entry to hat */
|
||||
entry = new_entry(strdup(CHANGEHAT_PATH), AA_MAY_WRITE, NULL);
|
||||
if (!entry)
|
||||
if (!add_proc_access(prof, CHANGEHAT_PATH))
|
||||
return ENOMEM;
|
||||
|
||||
add_entry_to_policy(prof, entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -468,20 +468,26 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
{
|
||||
std::string tbuf;
|
||||
pattern_t ptype;
|
||||
const char *name;
|
||||
char *name;
|
||||
|
||||
struct cond_entry *entry;
|
||||
const char *xattr_value;
|
||||
|
||||
/* don't filter_slashes for profile names */
|
||||
if (prof->attachment)
|
||||
if (prof->attachment) {
|
||||
name = prof->attachment;
|
||||
else
|
||||
name = local_name(prof->name);
|
||||
} else {
|
||||
/* don't filter_slashes for profile names, do on attachment */
|
||||
name = strdup(local_name(prof->name));
|
||||
if (!name)
|
||||
return FALSE;
|
||||
}
|
||||
filter_slashes(name);
|
||||
ptype = convert_aaregex_to_pcre(name, 0, glob_default, tbuf,
|
||||
&prof->xmatch_len);
|
||||
if (ptype == ePatternBasic)
|
||||
prof->xmatch_len = strlen(name);
|
||||
if (!prof->attachment)
|
||||
free(name);
|
||||
|
||||
if (ptype == ePatternInvalid) {
|
||||
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
|
||||
@@ -505,6 +511,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
list_for_each(prof->altnames, alt) {
|
||||
int len;
|
||||
tbuf.clear();
|
||||
filter_slashes(alt->name);
|
||||
ptype = convert_aaregex_to_pcre(alt->name, 0,
|
||||
glob_default,
|
||||
tbuf, &len);
|
||||
@@ -516,7 +523,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
}
|
||||
if (prof->xattrs.list) {
|
||||
if (!(features_supports_domain_xattr && kernel_supports_oob)) {
|
||||
warn_once_xattr(name);
|
||||
warn_once_xattr(prof->name);
|
||||
free_cond_entry_list(prof->xattrs);
|
||||
goto build;
|
||||
}
|
||||
@@ -642,6 +649,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
||||
int pos;
|
||||
vec[0] = tbuf.c_str();
|
||||
if (entry->link_name) {
|
||||
filter_slashes(entry->link_name);
|
||||
ptype = convert_aaregex_to_pcre(entry->link_name, 0, glob_default, lbuf, &pos);
|
||||
if (ptype == ePatternInvalid)
|
||||
return FALSE;
|
||||
|
@@ -220,6 +220,7 @@ void add_local_entry(Profile *prof);
|
||||
struct cond_entry_list cond_entry_list;
|
||||
int boolean;
|
||||
struct prefixes prefix;
|
||||
IncludeCache_t *includecache;
|
||||
}
|
||||
|
||||
%type <id> TOK_ID
|
||||
@@ -334,9 +335,17 @@ opt_id: { /* nothing */ $$ = NULL; }
|
||||
opt_id_or_var: { /* nothing */ $$ = NULL; }
|
||||
| id_or_var { $$ = $1; }
|
||||
|
||||
profile_base: TOK_ID opt_id_or_var opt_cond_list flags TOK_OPEN rules TOK_CLOSE
|
||||
profile_base: TOK_ID opt_id_or_var opt_cond_list flags TOK_OPEN
|
||||
{
|
||||
Profile *prof = $6;
|
||||
/* mid rule action
|
||||
* save current cache, restore at end of block
|
||||
*/
|
||||
$<includecache>$ = g_includecache;
|
||||
g_includecache = new IncludeCache_t();
|
||||
}
|
||||
rules TOK_CLOSE
|
||||
{
|
||||
Profile *prof = $7;
|
||||
bool self_stack = false;
|
||||
|
||||
if (!prof) {
|
||||
@@ -387,6 +396,10 @@ profile_base: TOK_ID opt_id_or_var opt_cond_list flags TOK_OPEN rules TOK_CLOSE
|
||||
post_process_file_entries(prof);
|
||||
post_process_rule_entries(prof);
|
||||
prof->flags.debug(cerr);
|
||||
|
||||
/* restore previous blocks include cache */
|
||||
delete g_includecache;
|
||||
g_includecache = $<includecache>6;
|
||||
$$ = prof;
|
||||
|
||||
};
|
||||
@@ -1775,12 +1788,17 @@ static int abi_features_base(struct aa_features **features, char *filename, bool
|
||||
autofclose FILE *f = NULL;
|
||||
struct stat my_stat;
|
||||
char *fullpath = NULL;
|
||||
bool cached;
|
||||
|
||||
if (search) {
|
||||
if (strcmp(filename, "kernel") == 0)
|
||||
return aa_features_new_from_kernel(features);
|
||||
f = search_path(filename, &fullpath);
|
||||
PDEBUG("abi lookup '%s' -> '%s' f %p\n", filename, fullpath, f);
|
||||
f = search_path(filename, &fullpath, &cached);
|
||||
PDEBUG("abi lookup '%s' -> '%s' f %p cached %d\n", filename, fullpath, f, cached);
|
||||
if (!f && cached) {
|
||||
*features = NULL;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
f = fopen(filename, "r");
|
||||
PDEBUG("abi relpath '%s' f %p\n", filename, f);
|
||||
@@ -1809,10 +1827,15 @@ static void abi_features(char *filename, bool search)
|
||||
yyerror(_("failed to find features abi '%s': %m"), filename);
|
||||
}
|
||||
if (policy_features) {
|
||||
if (!aa_features_is_equal(tmp_features, policy_features)) {
|
||||
pwarn(WARN_ABI, _("%s: %s features abi '%s' differs from policy declared feature abi, using the features abi declared in policy\n"), progname, current_filename, filename);
|
||||
if (tmp_features) {
|
||||
if (!aa_features_is_equal(tmp_features, policy_features)) {
|
||||
pwarn(WARN_ABI, _("%s: %s features abi '%s' differs from policy declared feature abi, using the features abi declared in policy\n"), progname, current_filename, filename);
|
||||
}
|
||||
aa_features_unref(tmp_features);
|
||||
}
|
||||
aa_features_unref(tmp_features);
|
||||
} else if (!tmp_features) {
|
||||
/* skipped reinclude, but features not set */
|
||||
yyerror(_("failed features abi not set but include cache skipped\n"));
|
||||
} else {
|
||||
/* first features abi declaration */
|
||||
policy_features = tmp_features;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR NOVELL, Inc.
|
||||
# Copyright (C) YEAR Canonical Ltd
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2014-09-13 00:11-0700\n"
|
||||
"POT-Creation-Date: 2020-10-14 04:04-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,95 +17,106 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../parser_include.c:113 ../parser_include.c:111
|
||||
#: ../parser_include.c:113 ../parser_include.c:111 ../parser_include.c:96
|
||||
msgid "Error: Out of memory.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_include.c:123 ../parser_include.c:121
|
||||
#: ../parser_include.c:123 ../parser_include.c:121 ../parser_include.c:106
|
||||
#, c-format
|
||||
msgid "Error: basedir %s is not a directory, skipping.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_include.c:137
|
||||
#: ../parser_include.c:137 ../parser_include.c:122
|
||||
#, c-format
|
||||
msgid "Error: Could not add directory %s to search path.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_include.c:147 ../parser_include.c:151
|
||||
#: ../parser_include.c:147 ../parser_include.c:151 ../parser_include.c:136
|
||||
msgid "Error: Could not allocate memory.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:69 ../parser_interface.c:72 ../parser_interface.c:49
|
||||
#: ../parser_interface.c:52
|
||||
msgid "Bad write position\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:72 ../parser_interface.c:75 ../parser_interface.c:52
|
||||
#: ../parser_interface.c:55
|
||||
msgid "Permission denied\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:75 ../parser_interface.c:78 ../parser_interface.c:55
|
||||
#: ../parser_interface.c:58
|
||||
msgid "Out of memory\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:78 ../parser_interface.c:81 ../parser_interface.c:58
|
||||
#: ../parser_interface.c:61
|
||||
msgid "Couldn't copy profile: Bad memory address\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:81 ../parser_interface.c:84 ../parser_interface.c:61
|
||||
#: ../parser_interface.c:64
|
||||
msgid "Profile doesn't conform to protocol\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:84 ../parser_interface.c:87 ../parser_interface.c:64
|
||||
#: ../parser_interface.c:67
|
||||
msgid "Profile does not match signature\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:87 ../parser_interface.c:90 ../parser_interface.c:67
|
||||
#: ../parser_interface.c:70
|
||||
msgid "Profile version not supported by Apparmor module\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:90 ../parser_interface.c:93 ../parser_interface.c:70
|
||||
#: ../parser_interface.c:73
|
||||
msgid "Profile already exists\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:93 ../parser_interface.c:96 ../parser_interface.c:73
|
||||
#: ../parser_interface.c:76
|
||||
msgid "Profile doesn't exist\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:96 ../parser_interface.c:99 ../parser_interface.c:76
|
||||
#: ../parser_interface.c:79
|
||||
msgid "Permission denied; attempted to load a profile while confined?\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:99 ../parser_interface.c:102 ../parser_interface.c:79
|
||||
#: ../parser_interface.c:82
|
||||
#, c-format
|
||||
msgid "Unknown error (%d): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:116 ../parser_interface.c:119
|
||||
#: ../parser_interface.c:96
|
||||
#: ../parser_interface.c:116 ../parser_interface.c:119 ../parser_interface.c:96
|
||||
#: ../parser_interface.c:100
|
||||
#, c-format
|
||||
msgid "%s: Unable to add \"%s\". "
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:121 ../parser_interface.c:124
|
||||
#: ../parser_interface.c:101
|
||||
#: ../parser_interface.c:101 ../parser_interface.c:105
|
||||
#, c-format
|
||||
msgid "%s: Unable to replace \"%s\". "
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:126 ../parser_interface.c:129
|
||||
#: ../parser_interface.c:106
|
||||
#: ../parser_interface.c:106 ../parser_interface.c:110
|
||||
#, c-format
|
||||
msgid "%s: Unable to remove \"%s\". "
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:131 ../parser_interface.c:134
|
||||
#: ../parser_interface.c:111
|
||||
#: ../parser_interface.c:111 ../parser_interface.c:115
|
||||
#, c-format
|
||||
msgid "%s: Unable to write to stdout\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:135 ../parser_interface.c:138
|
||||
#: ../parser_interface.c:115
|
||||
#: ../parser_interface.c:115 ../parser_interface.c:119
|
||||
#, c-format
|
||||
msgid "%s: Unable to write to output file\n"
|
||||
msgstr ""
|
||||
@@ -113,24 +124,25 @@ msgstr ""
|
||||
#: ../parser_interface.c:138 ../parser_interface.c:162
|
||||
#: ../parser_interface.c:141 ../parser_interface.c:165
|
||||
#: ../parser_interface.c:118 ../parser_interface.c:142
|
||||
#: ../parser_interface.c:123 ../parser_interface.c:147
|
||||
#, c-format
|
||||
msgid "%s: ASSERT: Invalid option: %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:147 ../parser_interface.c:150
|
||||
#: ../parser_interface.c:127
|
||||
#: ../parser_interface.c:127 ../parser_interface.c:132
|
||||
#, c-format
|
||||
msgid "Addition succeeded for \"%s\".\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:151 ../parser_interface.c:154
|
||||
#: ../parser_interface.c:131
|
||||
#: ../parser_interface.c:131 ../parser_interface.c:136
|
||||
#, c-format
|
||||
msgid "Replacement succeeded for \"%s\".\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:155 ../parser_interface.c:158
|
||||
#: ../parser_interface.c:135
|
||||
#: ../parser_interface.c:135 ../parser_interface.c:140
|
||||
#, c-format
|
||||
msgid "Removal succeeded for \"%s\".\n"
|
||||
msgstr ""
|
||||
@@ -141,7 +153,7 @@ msgid "PANIC bad increment buffer %p pos %p ext %p size %d res %p\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:656 ../parser_interface.c:658
|
||||
#: ../parser_interface.c:446
|
||||
#: ../parser_interface.c:446 ../parser_interface.c:476
|
||||
#, c-format
|
||||
msgid "profile %s network rules not enforced\n"
|
||||
msgstr ""
|
||||
@@ -186,7 +198,7 @@ msgid "%s: Unable to write entire profile entry\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:839 ../parser_interface.c:831
|
||||
#: ../parser_interface.c:593
|
||||
#: ../parser_interface.c:593 ../parser_interface.c:579
|
||||
#, c-format
|
||||
msgid "%s: Unable to write entire profile entry to cache\n"
|
||||
msgstr ""
|
||||
@@ -196,7 +208,7 @@ msgstr ""
|
||||
msgid "Could not open '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_lex.l:104 parser_lex.l:167 parser_lex.l:173
|
||||
#: parser_lex.l:104 parser_lex.l:167 parser_lex.l:173 parser_lex.l:174
|
||||
#, c-format
|
||||
msgid "fstat failed for '%s'"
|
||||
msgstr ""
|
||||
@@ -222,7 +234,7 @@ msgstr ""
|
||||
msgid "Found unexpected character: '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428
|
||||
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428 parser_lex.l:474
|
||||
msgid "Variable declarations do not accept trailing commas"
|
||||
msgstr ""
|
||||
|
||||
@@ -242,6 +254,7 @@ msgid "%s: Could not allocate memory for subdomainbase mount point\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:577 ../parser_main.c:616 ../parser_main.c:479
|
||||
#: ../parser_main.c:1444
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: unable to find a suitable fs in %s, is it mounted?\n"
|
||||
@@ -249,6 +262,7 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:597 ../parser_main.c:635 ../parser_main.c:498
|
||||
#: ../parser_main.c:822
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Sorry. You need root privileges to run this program.\n"
|
||||
@@ -256,6 +270,7 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:604 ../parser_main.c:642 ../parser_main.c:505
|
||||
#: ../parser_main.c:828
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Warning! You've set this program setuid root.\n"
|
||||
@@ -264,7 +279,7 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:704 ../parser_main.c:813 ../parser_main.c:836
|
||||
#: ../parser_main.c:946 ../parser_main.c:860
|
||||
#: ../parser_main.c:946 ../parser_main.c:860 ../parser_main.c:1038
|
||||
#, c-format
|
||||
msgid "Error: Could not read profile %s: %s.\n"
|
||||
msgstr ""
|
||||
@@ -286,26 +301,36 @@ msgstr ""
|
||||
#: parser_yacc.y:1166 parser_yacc.y:1170 parser_yacc.y:1180 parser_yacc.y:1190
|
||||
#: parser_yacc.y:1298 parser_yacc.y:1376 parser_yacc.y:1479 parser_yacc.y:1490
|
||||
#: parser_yacc.y:1565 parser_yacc.y:1583 parser_yacc.y:1590 parser_yacc.y:1639
|
||||
#: ../network.c:314 ../af_unix.cc:203
|
||||
#: ../network.c:314 ../af_unix.cc:203 ../parser_misc.c:215 ../parser_misc.c:939
|
||||
#: parser_yacc.y:343 parser_yacc.y:367 parser_yacc.y:533 parser_yacc.y:543
|
||||
#: parser_yacc.y:660 parser_yacc.y:741 parser_yacc.y:750 parser_yacc.y:1171
|
||||
#: parser_yacc.y:1219 parser_yacc.y:1255 parser_yacc.y:1264 parser_yacc.y:1268
|
||||
#: parser_yacc.y:1278 parser_yacc.y:1288 parser_yacc.y:1382 parser_yacc.y:1460
|
||||
#: parser_yacc.y:1592 parser_yacc.y:1597 parser_yacc.y:1674 parser_yacc.y:1692
|
||||
#: parser_yacc.y:1699 parser_yacc.y:1748 ../network.c:315 ../af_unix.cc:194
|
||||
msgid "Memory allocation error."
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:740 ../parser_main.c:872 ../parser_main.c:757
|
||||
#: ../parser_main.c:975
|
||||
#, c-format
|
||||
msgid "Cached load succeeded for \"%s\".\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:744 ../parser_main.c:876 ../parser_main.c:761
|
||||
#: ../parser_main.c:979
|
||||
#, c-format
|
||||
msgid "Cached reload succeeded for \"%s\".\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:910 ../parser_main.c:1058 ../parser_main.c:967
|
||||
#: ../parser_main.c:1132
|
||||
#, c-format
|
||||
msgid "%s: Errors found in file. Aborting.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:426 ../parser_misc.c:597 ../parser_misc.c:339
|
||||
#: ../parser_misc.c:532
|
||||
msgid ""
|
||||
"Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
|
||||
"See the apparmor.d(5) manpage for details.\n"
|
||||
@@ -313,14 +338,17 @@ msgstr ""
|
||||
|
||||
#: ../parser_misc.c:467 ../parser_misc.c:474 ../parser_misc.c:638
|
||||
#: ../parser_misc.c:645 ../parser_misc.c:380 ../parser_misc.c:387
|
||||
#: ../parser_misc.c:573 ../parser_misc.c:580
|
||||
msgid "Conflict 'a' and 'w' perms are mutually exclusive."
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:491 ../parser_misc.c:662 ../parser_misc.c:404
|
||||
#: ../parser_misc.c:597
|
||||
msgid "Exec qualifier 'i' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:502 ../parser_misc.c:673 ../parser_misc.c:415
|
||||
#: ../parser_misc.c:608
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Unconfined exec qualifier (%c%c) allows some dangerous environment variables "
|
||||
@@ -329,22 +357,26 @@ msgstr ""
|
||||
|
||||
#: ../parser_misc.c:510 ../parser_misc.c:551 ../parser_misc.c:681
|
||||
#: ../parser_misc.c:722 ../parser_misc.c:423 ../parser_misc.c:464
|
||||
#: ../parser_misc.c:616 ../parser_misc.c:657
|
||||
#, c-format
|
||||
msgid "Exec qualifier '%c' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:537 ../parser_misc.c:545 ../parser_misc.c:708
|
||||
#: ../parser_misc.c:716 ../parser_misc.c:450 ../parser_misc.c:458
|
||||
#: ../parser_misc.c:643 ../parser_misc.c:651
|
||||
#, c-format
|
||||
msgid "Exec qualifier '%c%c' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:593 ../parser_misc.c:764 ../parser_misc.c:506
|
||||
#: ../parser_misc.c:699
|
||||
#, c-format
|
||||
msgid "Internal: unexpected mode character '%c' in input"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:615 ../parser_misc.c:786 ../parser_misc.c:528
|
||||
#: ../parser_misc.c:721
|
||||
#, c-format
|
||||
msgid "Internal error generated invalid perm 0x%llx\n"
|
||||
msgstr ""
|
||||
@@ -356,10 +388,12 @@ msgid "AppArmor parser error: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_merge.c:92 ../parser_merge.c:91 ../parser_merge.c:83
|
||||
#: ../parser_merge.c:71
|
||||
msgid "Couldn't merge entries. Out of Memory\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_merge.c:111 ../parser_merge.c:113 ../parser_merge.c:105
|
||||
#: ../parser_merge.c:93
|
||||
#, c-format
|
||||
msgid "profile %s: has merged rule %s with conflicting x modifiers\n"
|
||||
msgstr ""
|
||||
@@ -368,114 +402,117 @@ msgstr ""
|
||||
msgid "Profile attachment must begin with a '/'."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348
|
||||
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348 parser_yacc.y:407
|
||||
msgid ""
|
||||
"Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:296 parser_yacc.y:338 parser_yacc.y:384
|
||||
#: parser_yacc.y:296 parser_yacc.y:338 parser_yacc.y:384 parser_yacc.y:449
|
||||
#, c-format
|
||||
msgid "Failed to create alias %s -> %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:417 parser_yacc.y:460 parser_yacc.y:506
|
||||
#: parser_yacc.y:417 parser_yacc.y:460 parser_yacc.y:506 parser_yacc.y:581
|
||||
msgid "Profile flag chroot_relative conflicts with namespace_relative"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:421 parser_yacc.y:464 parser_yacc.y:510
|
||||
#: parser_yacc.y:421 parser_yacc.y:464 parser_yacc.y:510 parser_yacc.y:585
|
||||
msgid "Profile flag mediate_deleted conflicts with delegate_deleted"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:424 parser_yacc.y:467 parser_yacc.y:513
|
||||
#: parser_yacc.y:424 parser_yacc.y:467 parser_yacc.y:513 parser_yacc.y:588
|
||||
msgid "Profile flag attach_disconnected conflicts with no_attach_disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:427 parser_yacc.y:470 parser_yacc.y:516
|
||||
#: parser_yacc.y:427 parser_yacc.y:470 parser_yacc.y:516 parser_yacc.y:591
|
||||
msgid "Profile flag chroot_attach conflicts with chroot_no_attach"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:441 parser_yacc.y:484 parser_yacc.y:530
|
||||
#: parser_yacc.y:441 parser_yacc.y:484 parser_yacc.y:530 parser_yacc.y:607
|
||||
msgid "Profile flag 'debug' is no longer valid."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:463 parser_yacc.y:506 parser_yacc.y:552
|
||||
#: parser_yacc.y:463 parser_yacc.y:506 parser_yacc.y:552 parser_yacc.y:629
|
||||
#, c-format
|
||||
msgid "Invalid profile flag: %s."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:498 parser_yacc.y:520 parser_yacc.y:548 parser_yacc.y:594
|
||||
#: parser_yacc.y:673
|
||||
msgid "Assert: `rule' returned NULL."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:501 parser_yacc.y:546 parser_yacc.y:552 parser_yacc.y:584
|
||||
#: parser_yacc.y:598 parser_yacc.y:630
|
||||
#: parser_yacc.y:598 parser_yacc.y:630 parser_yacc.y:677 parser_yacc.y:709
|
||||
msgid ""
|
||||
"Invalid mode, in deny rules 'x' must not be preceded by exec qualifier 'i', "
|
||||
"'p', or 'u'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:524 parser_yacc.y:556 parser_yacc.y:602
|
||||
#: parser_yacc.y:524 parser_yacc.y:556 parser_yacc.y:602 parser_yacc.y:681
|
||||
msgid ""
|
||||
"Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', 'c', or 'u'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:549 parser_yacc.y:587 parser_yacc.y:633
|
||||
#: parser_yacc.y:549 parser_yacc.y:587 parser_yacc.y:633 parser_yacc.y:712
|
||||
msgid "Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', or 'u'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:574 parser_yacc.y:612 parser_yacc.y:614 parser_yacc.y:660
|
||||
#: parser_yacc.y:739
|
||||
msgid "Assert: `network_rule' return invalid protocol."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:649 parser_yacc.y:696 parser_yacc.y:786
|
||||
#: parser_yacc.y:649 parser_yacc.y:696 parser_yacc.y:786 parser_yacc.y:867
|
||||
msgid "Assert: `change_profile' returned NULL."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:680 parser_yacc.y:720 parser_yacc.y:810
|
||||
#: parser_yacc.y:680 parser_yacc.y:720 parser_yacc.y:810 parser_yacc.y:905
|
||||
msgid "Assert: 'hat rule' returned NULL."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:689 parser_yacc.y:729 parser_yacc.y:819
|
||||
#: parser_yacc.y:689 parser_yacc.y:729 parser_yacc.y:819 parser_yacc.y:914
|
||||
msgid "Assert: 'local_profile rule' returned NULL."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:824 parser_yacc.y:885 parser_yacc.y:992
|
||||
#: parser_yacc.y:824 parser_yacc.y:885 parser_yacc.y:992 parser_yacc.y:1077
|
||||
#, c-format
|
||||
msgid "Unset boolean variable %s used in if-expression"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:882 parser_yacc.y:986 parser_yacc.y:1092
|
||||
#: parser_yacc.y:882 parser_yacc.y:986 parser_yacc.y:1092 parser_yacc.y:1181
|
||||
msgid "unsafe rule missing exec permissions"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060
|
||||
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060 parser_yacc.y:1148
|
||||
msgid "subset can only be used with link rules."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:903 parser_yacc.y:956 parser_yacc.y:1062
|
||||
#: parser_yacc.y:903 parser_yacc.y:956 parser_yacc.y:1062 parser_yacc.y:1150
|
||||
msgid "link and exec perms conflict on a file rule using ->"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:905 parser_yacc.y:958 parser_yacc.y:1064
|
||||
#: parser_yacc.y:905 parser_yacc.y:958 parser_yacc.y:1064 parser_yacc.y:1152
|
||||
msgid "link perms are not allowed on a named profile transition.\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:921 parser_yacc.y:1003 parser_yacc.y:1109
|
||||
#: parser_yacc.y:921 parser_yacc.y:1003 parser_yacc.y:1109 parser_yacc.y:1198
|
||||
#, c-format
|
||||
msgid "missing an end of line character? (entry: %s)"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:975 parser_yacc.y:985 parser_yacc.y:1057 parser_yacc.y:1067
|
||||
#: parser_yacc.y:1145 parser_yacc.y:1155
|
||||
#: parser_yacc.y:1145 parser_yacc.y:1155 parser_yacc.y:1234 parser_yacc.y:1244
|
||||
msgid "Invalid network entry."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1039 parser_yacc.y:1048 parser_yacc.y:1254 parser_yacc.y:1510
|
||||
#: parser_yacc.y:1617
|
||||
#, c-format
|
||||
msgid "Invalid capability %s."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525 parser_yacc.y:1637
|
||||
#, c-format
|
||||
msgid "AppArmor parser error for %s%s%s at line %d: %s\n"
|
||||
msgstr ""
|
||||
@@ -491,17 +528,20 @@ msgid "%s: Illegal open {, nesting groupings not allowed\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:265 ../parser_regex.c:274 ../parser_regex.c:278
|
||||
#: ../parser_regex.c:306
|
||||
#, c-format
|
||||
msgid "%s: Regex grouping error: Invalid number of items between {}\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:271 ../parser_regex.c:280 ../parser_regex.c:284
|
||||
#: ../parser_regex.c:312
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close }, no matching open { detected\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:337 ../parser_regex.c:343 ../parser_regex.c:361
|
||||
#: ../parser_regex.c:403
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Unclosed grouping or character class, expecting "
|
||||
@@ -514,16 +554,19 @@ msgid "%s: Internal buffer overflow detected, %d characters exceeded\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:355 ../parser_regex.c:361 ../parser_regex.c:377
|
||||
#: ../parser_regex.c:419
|
||||
#, c-format
|
||||
msgid "%s: Unable to parse input line '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:397 ../parser_regex.c:405 ../parser_regex.c:421
|
||||
#: ../parser_regex.c:487
|
||||
#, c-format
|
||||
msgid "%s: Invalid profile name '%s' - bad regular expression\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:202 ../parser_policy.c:402 ../parser_policy.c:375
|
||||
#: ../parser_policy.c:383
|
||||
#, c-format
|
||||
msgid "ERROR merging rules for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
@@ -537,16 +580,19 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:279 ../parser_policy.c:359 ../parser_policy.c:332
|
||||
#: ../parser_policy.c:340
|
||||
#, c-format
|
||||
msgid "ERROR processing regexs for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:306 ../parser_policy.c:389 ../parser_policy.c:362
|
||||
#: ../parser_policy.c:370
|
||||
#, c-format
|
||||
msgid "ERROR expanding variables for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:390 ../parser_policy.c:382 ../parser_policy.c:355
|
||||
#: ../parser_policy.c:363
|
||||
#, c-format
|
||||
msgid "ERROR adding hat access rule for profile %s\n"
|
||||
msgstr ""
|
||||
@@ -576,7 +622,7 @@ msgstr ""
|
||||
msgid "%s: Errors found in combining rules postprocessing. Aborting.\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_lex.l:180 parser_lex.l:186
|
||||
#: parser_lex.l:180 parser_lex.l:186 parser_lex.l:187
|
||||
#, c-format
|
||||
msgid "Could not process include directory '%s' in '%s'"
|
||||
msgstr ""
|
||||
@@ -586,7 +632,8 @@ msgid "Feature buffer full."
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1115 ../parser_main.c:1132 ../parser_main.c:1024
|
||||
#: ../parser_main.c:1041
|
||||
#: ../parser_main.c:1041 ../parser_main.c:1332 ../parser_main.c:1354
|
||||
#: ../parser_misc.c:280 ../parser_misc.c:299 ../parser_misc.c:308
|
||||
msgid "Out of memory"
|
||||
msgstr ""
|
||||
|
||||
@@ -615,11 +662,11 @@ msgstr ""
|
||||
msgid "Internal error generated invalid DBus perm 0x%x\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:575 parser_yacc.y:621
|
||||
#: parser_yacc.y:575 parser_yacc.y:621 parser_yacc.y:700
|
||||
msgid "deny prefix not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:612 parser_yacc.y:658
|
||||
#: parser_yacc.y:612 parser_yacc.y:658 parser_yacc.y:737
|
||||
msgid "owner prefix not allowed"
|
||||
msgstr ""
|
||||
|
||||
@@ -635,41 +682,41 @@ msgstr ""
|
||||
msgid "owner prefix not allow on capability rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1357 parser_yacc.y:1613
|
||||
#: parser_yacc.y:1357 parser_yacc.y:1613 parser_yacc.y:1722
|
||||
#, c-format
|
||||
msgid "invalid mount conditional %s%s"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1374 parser_yacc.y:1628
|
||||
#: parser_yacc.y:1374 parser_yacc.y:1628 parser_yacc.y:1737
|
||||
msgid "bad mount rule"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1381 parser_yacc.y:1635
|
||||
#: parser_yacc.y:1381 parser_yacc.y:1635 parser_yacc.y:1744
|
||||
msgid "mount point conditions not currently supported"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1398 parser_yacc.y:1650
|
||||
#: parser_yacc.y:1398 parser_yacc.y:1650 parser_yacc.y:1759
|
||||
#, c-format
|
||||
msgid "invalid pivotroot conditional '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:241 ../parser_regex.c:236
|
||||
#: ../parser_regex.c:241 ../parser_regex.c:236 ../parser_regex.c:264
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close ], no matching open [ detected\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:257 ../parser_regex.c:256
|
||||
#: ../parser_regex.c:257 ../parser_regex.c:256 ../parser_regex.c:284
|
||||
#, c-format
|
||||
msgid "%s: Regex grouping error: Exceeded maximum nesting of {}\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:366 ../parser_policy.c:339
|
||||
#: ../parser_policy.c:366 ../parser_policy.c:339 ../parser_policy.c:347
|
||||
#, c-format
|
||||
msgid "ERROR processing policydb rules for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_policy.c:396 ../parser_policy.c:369
|
||||
#: ../parser_policy.c:396 ../parser_policy.c:369 ../parser_policy.c:377
|
||||
#, c-format
|
||||
msgid "ERROR replacing aliases for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
@@ -689,51 +736,244 @@ msgstr ""
|
||||
msgid "Error: Could not read cache file '%s', skipping...\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:575
|
||||
#: ../parser_misc.c:575 ../parser_misc.c:768
|
||||
#, c-format
|
||||
msgid "Internal: unexpected %s mode character '%c' in input"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:599
|
||||
#: ../parser_misc.c:599 ../parser_misc.c:792
|
||||
#, c-format
|
||||
msgid "Internal error generated invalid %s perm 0x%x\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:703
|
||||
#: parser_yacc.y:703 parser_yacc.y:784
|
||||
msgid "owner prefix not allowed on mount rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:720
|
||||
#: parser_yacc.y:720 parser_yacc.y:801
|
||||
msgid "owner prefix not allowed on dbus rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:736
|
||||
#: parser_yacc.y:736 parser_yacc.y:817
|
||||
msgid "owner prefix not allowed on signal rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:752
|
||||
#: parser_yacc.y:752 parser_yacc.y:833
|
||||
msgid "owner prefix not allowed on ptrace rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:768
|
||||
#: parser_yacc.y:768 parser_yacc.y:849 parser_yacc.y:869
|
||||
msgid "owner prefix not allowed on unix rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:794
|
||||
#: parser_yacc.y:794 parser_yacc.y:885
|
||||
msgid "owner prefix not allowed on capability rules"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1293
|
||||
#: parser_yacc.y:1293 parser_yacc.y:1377
|
||||
#, c-format
|
||||
msgid "dbus rule: invalid conditional group %s=()"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1371
|
||||
#: parser_yacc.y:1371 parser_yacc.y:1455
|
||||
#, c-format
|
||||
msgid "unix rule: invalid conditional group %s=()"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:368
|
||||
#: ../parser_regex.c:368 ../parser_regex.c:410
|
||||
#, c-format
|
||||
msgid "%s: Regex error: trailing '\\' escape character\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_common.c:112
|
||||
#, c-format
|
||||
msgid "%s from %s (%s%sline %d): %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_common.c:113
|
||||
msgid "Warning converted to Error"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_common.c:113
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:524
|
||||
#, c-format
|
||||
msgid "Unable to open stdout - %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_interface.c:533
|
||||
#, c-format
|
||||
msgid "Unable to open output file - %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_lex.l:326
|
||||
msgid "Failed to process filename\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_lex.l:720
|
||||
#, c-format
|
||||
msgid "Lexer found unexpected character: '%s' (0x%x) in state: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:915
|
||||
#, c-format
|
||||
msgid "Unable to print the cache directory: %m\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:951
|
||||
#, c-format
|
||||
msgid "Error: Could not load profile %s: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:961
|
||||
#, c-format
|
||||
msgid "Error: Could not replace profile %s: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:966
|
||||
#, c-format
|
||||
msgid "Error: Invalid load option specified: %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1077
|
||||
#, c-format
|
||||
msgid "Could not get cachename for '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1434
|
||||
msgid "Kernel features abi not found"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1438
|
||||
msgid "Failed to add kernel capabilities to known capabilities set"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1465
|
||||
#, c-format
|
||||
msgid "Failed to clear cache files (%s): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1474
|
||||
msgid ""
|
||||
"The --create-cache-dir option is deprecated. Please use --write-cache.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_main.c:1479
|
||||
#, c-format
|
||||
msgid "Failed setting up policy cache (%s): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:904
|
||||
#, c-format
|
||||
msgid "Namespace not terminated: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:906
|
||||
#, c-format
|
||||
msgid "Empty namespace: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:908
|
||||
#, c-format
|
||||
msgid "Empty named transition profile name: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_misc.c:910
|
||||
#, c-format
|
||||
msgid "Unknown error while parsing label: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:306
|
||||
msgid "Failed to setup default policy feature abi"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:308
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: File '%s' missing feature abi, falling back to default policy feature "
|
||||
"abi\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:313
|
||||
msgid "Failed to add policy capabilities to known capabilities set"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:350
|
||||
msgid "Profile names must begin with a '/' or a namespace"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:372
|
||||
msgid "Profile attachment must begin with a '/' or variable."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:375
|
||||
#, c-format
|
||||
msgid "profile id: invalid conditional group %s=()"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:404
|
||||
msgid ""
|
||||
"The use of file paths as profile names is deprecated. See man apparmor.d for "
|
||||
"more information\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:573
|
||||
#, c-format
|
||||
msgid "Profile flag '%s' conflicts with '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:954
|
||||
msgid "RLIMIT 'cpu' no units specified using default units of seconds\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:966
|
||||
msgid ""
|
||||
"RLIMIT 'rttime' no units specified using default units of microseconds\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1582
|
||||
msgid "Exec condition is required when unsafe or safe keywords are present"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1584
|
||||
msgid "Exec condition must begin with '/'."
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1643
|
||||
#, c-format
|
||||
msgid "AppArmor parser error at line %d: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1790
|
||||
#, c-format
|
||||
msgid "Could not open '%s': %m"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1795
|
||||
#, c-format
|
||||
msgid "fstat failed for '%s': %m"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1809
|
||||
#, c-format
|
||||
msgid "failed to find features abi '%s': %m"
|
||||
msgstr ""
|
||||
|
||||
#: parser_yacc.y:1813
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: %s features abi '%s' differs from policy declared feature abi, using the "
|
||||
"features abi declared in policy\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:98 ../parser_regex.c:238
|
||||
#, c-format
|
||||
msgid "%s: Invalid glob type %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../parser_regex.c:693
|
||||
#, c-format
|
||||
msgid "The current kernel does not support stacking of named transitions: %s\n"
|
||||
msgstr ""
|
||||
|
@@ -618,6 +618,31 @@ verify_binary_equality "mount rules slash filtering" \
|
||||
"@{FOO}=/foo
|
||||
/t { mount /dev//@{FOO} -> /mnt/bar, }"
|
||||
|
||||
# verify slash filtering for link rules
|
||||
verify_binary_equality "link rules slash filtering" \
|
||||
"/t { link /dev/foo -> /mnt/bar, }" \
|
||||
"/t { link ///dev/foo -> /mnt/bar, }" \
|
||||
"/t { link /dev/foo -> /mnt//bar, }" \
|
||||
"/t { link /dev///foo -> ////mnt/bar, }" \
|
||||
"@{BAR}=/mnt/
|
||||
/t { link /dev///foo -> @{BAR}/bar, }" \
|
||||
"@{FOO}=/dev/
|
||||
/t { link @{FOO}//foo -> /mnt/bar, }" \
|
||||
"@{FOO}=/dev/
|
||||
@{BAR}=/mnt/
|
||||
/t { link @{FOO}/foo -> @{BAR}/bar, }"
|
||||
|
||||
verify_binary_equality "attachment slash filtering" \
|
||||
"/t /bin/foo { }" \
|
||||
"/t /bin//foo { }" \
|
||||
"@{BAR}=/bin/
|
||||
/t @{BAR}/foo { }" \
|
||||
"@{FOO}=/foo
|
||||
/t /bin/@{FOO} { }" \
|
||||
"@{BAR}=/bin/
|
||||
@{FOO}=/foo
|
||||
/t @{BAR}/@{FOO} { }"
|
||||
|
||||
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
|
||||
then
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||
|
7
parser/tst/simple_tests/include_tests/recursive_2.sd
Normal file
7
parser/tst/simple_tests/include_tests/recursive_2.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - recursive include should not fail
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/does/not/exist {
|
||||
#include <includes/recursive.include>
|
||||
}
|
10
parser/tst/simple_tests/include_tests/recursive_3.sd
Normal file
10
parser/tst/simple_tests/include_tests/recursive_3.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - recursive include should not fail
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
#include <includes/recursive.preamble>
|
||||
|
||||
/does/not/exist {
|
||||
/foo r,
|
||||
}
|
6
parser/tst/simple_tests/includes/recursive.include
Normal file
6
parser/tst/simple_tests/includes/recursive.include
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
# helper for include_tests/recursive_2.sd
|
||||
|
||||
/foo rw,
|
||||
#include <includes/recursive.include>
|
||||
/no/such/path r,
|
4
parser/tst/simple_tests/includes/recursive.preamble
Normal file
4
parser/tst/simple_tests/includes/recursive.preamble
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
# helper for include_tests/recursive_3.sd
|
||||
|
||||
#include <includes/recursive.preamble>
|
@@ -17,6 +17,7 @@
|
||||
|
||||
# .ICEauthority files required for X authentication, per user
|
||||
owner @{HOME}/.ICEauthority r,
|
||||
owner @{run}/user/*/ICEauthority r,
|
||||
|
||||
# .Xauthority files required for X connections, per user
|
||||
owner @{HOME}/.Xauthority r,
|
||||
@@ -29,7 +30,7 @@
|
||||
owner @{run}/user/*/xauth_* r,
|
||||
|
||||
# the unix socket to use to connect to the display
|
||||
/tmp/.X11-unix/* r,
|
||||
/tmp/.X11-unix/* rw,
|
||||
unix (connect, receive, send)
|
||||
type=stream
|
||||
peer=(addr="@/tmp/.X11-unix/X[0-9]*"),
|
||||
@@ -51,6 +52,8 @@
|
||||
|
||||
# Xcompose
|
||||
owner @{HOME}/.XCompose r,
|
||||
/var/cache/libx11/compose/* r,
|
||||
deny /var/cache/libx11/compose/* wlk,
|
||||
|
||||
# mouse themes
|
||||
/etc/X11/cursors/ r,
|
||||
|
@@ -15,5 +15,6 @@ abi <abi/3.0>,
|
||||
|
||||
include <abstractions/apparmor_api/find_mountpoint>
|
||||
@{sys}/module/apparmor/parameters/enabled r,
|
||||
@{sys}/module/apparmor/parameters/available r,
|
||||
|
||||
# TODO: add alternate apparmorfs interface for enabled
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2009 Novell/SUSE
|
||||
# Copyright (C) 2009-2012 Canonical Ltd
|
||||
# Copyright (C) 2019 Christian Boltz
|
||||
# Copyright (C) 2019-2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -36,6 +36,8 @@
|
||||
# SuSE's pwdutils are different:
|
||||
@{etc_ro}/default/passwd r,
|
||||
@{etc_ro}/login.defs r,
|
||||
@{etc_ro}/login.defs.d/ r,
|
||||
@{etc_ro}/login.defs.d/*.defs r,
|
||||
|
||||
# nis
|
||||
include <abstractions/nis>
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <abstractions/crypto>
|
||||
|
||||
# (Note that the ldd profile has inlined this file; if you make
|
||||
# modifications here, please consider including them in the ldd
|
||||
|
26
profiles/apparmor.d/abstractions/crypto
Normal file
26
profiles/apparmor.d/abstractions/crypto
Normal file
@@ -0,0 +1,26 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2009 Novell/SUSE
|
||||
# Copyright (C) 2009-2011 Canonical Ltd.
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
@{etc_ro}/gcrypt/random.conf r,
|
||||
@{PROC}/sys/crypto/fips_enabled r,
|
||||
|
||||
# libgcrypt reads some flags from /proc
|
||||
@{PROC}/sys/crypto/* r,
|
||||
|
||||
# crypto policies used by various libraries
|
||||
/etc/crypto-policies/*/*.txt r,
|
||||
/usr/share/crypto-policies/*/*.txt r,
|
||||
|
||||
include if exists <abstractions/crypto.d>
|
@@ -52,6 +52,8 @@
|
||||
owner @{HOME}/.fonts.conf.d/** r,
|
||||
owner @{HOME}/.config/fontconfig/ r,
|
||||
owner @{HOME}/.config/fontconfig/** r,
|
||||
owner @{HOME}/.Fontmatrix/Activated/ r,
|
||||
owner @{HOME}/.Fontmatrix/Activated/** r,
|
||||
|
||||
/usr/local/share/fonts/ r,
|
||||
/usr/local/share/fonts/** r,
|
||||
|
@@ -12,11 +12,18 @@
|
||||
|
||||
# User files
|
||||
owner @{HOME}/.cache/ w, # if user clears all caches
|
||||
owner @{HOME}/.cache/mesa_shader_cache/ w,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/ rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/index rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/??/ w,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/??/* rwk,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/ rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
|
||||
|
||||
# Fallback location when @{HOME}/.cache is not available
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/ rw,
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/index rw,
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/ rw,
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/mesa.d>
|
||||
|
@@ -13,26 +13,26 @@
|
||||
abi <abi/3.0>,
|
||||
|
||||
# shared snippets for config files
|
||||
/etc/php{,5,7}/**/ r,
|
||||
/etc/php{,5,7}/**.ini r,
|
||||
/etc/php{,5,7,8}/**/ r,
|
||||
/etc/php{,5,7,8}/**.ini r,
|
||||
|
||||
# Xlibs
|
||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||
# php extensions
|
||||
/usr/lib{64,}/php{,5,7}/*/*.so mr,
|
||||
/usr/lib{64,}/php{,5,7,8}/*/*.so mr,
|
||||
|
||||
# ICU (unicode support) data tables
|
||||
/usr/share/icu/*/*.dat r,
|
||||
|
||||
# php session mmap socket
|
||||
/var/lib/php{,5,7}/session_mm_* rwlk,
|
||||
/var/lib/php{,5,7,8}/session_mm_* rwlk,
|
||||
# file based session handler
|
||||
/var/lib/php{,5,7}/sess_* rwlk,
|
||||
/var/lib/php{,5,7}/sessions/* rwlk,
|
||||
/var/lib/php{,5,7,8}/sess_* rwlk,
|
||||
/var/lib/php{,5,7,8}/sessions/* rwlk,
|
||||
|
||||
# php libraries
|
||||
/usr/share/php{,5,7}/ r,
|
||||
/usr/share/php{,5,7}/** mr,
|
||||
/usr/share/php{,5,7,8}/ r,
|
||||
/usr/share/php{,5,7,8}/** mr,
|
||||
|
||||
# MySQL extension
|
||||
/usr/share/mysql/** r,
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2015-2018 Canonical, Ltd.
|
||||
# Copyright (C) 2020 Christian Boltz
|
||||
# Copyright (C) 2020-2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -26,6 +26,7 @@
|
||||
/etc/mailname r,
|
||||
/etc/postfix/*.cf r,
|
||||
/etc/postfix/*.db rk,
|
||||
/etc/postfix/*.lmdb rk,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/usr/lib/postfix/*.so mr,
|
||||
/usr/lib{,32,64}/sasl2/* mr,
|
||||
|
@@ -24,7 +24,7 @@
|
||||
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
||||
audit deny @{HOME}/.kde{,4}/share/apps/kmail{,2}/{,**} mrwkl,
|
||||
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
||||
|
||||
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/private-files-strict.d>
|
||||
|
@@ -11,20 +11,16 @@
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
/etc/ssl/ r,
|
||||
/etc/ssl/certs/ r,
|
||||
/etc/ssl/certs/* r,
|
||||
/etc/pki/trust/ r,
|
||||
/etc/pki/trust/* r,
|
||||
/etc/pki/trust/anchors/ r,
|
||||
/etc/pki/trust/anchors/** r,
|
||||
/usr/share/ca-certificates/ r,
|
||||
/usr/share/ca-certificates/** r,
|
||||
/etc/ca-certificates/{,**} r,
|
||||
/etc/{,libre}ssl/ r,
|
||||
/etc/{,libre}ssl/cert.pem r,
|
||||
/etc/{,libre}ssl/certs/{,**} r,
|
||||
/etc/pki/trust/{,*} r,
|
||||
/etc/pki/trust/anchors/{,**} r,
|
||||
/usr/share/ca-certificates/{,**} r,
|
||||
/usr/share/ssl/certs/ca-bundle.crt r,
|
||||
/usr/local/share/ca-certificates/ r,
|
||||
/usr/local/share/ca-certificates/** r,
|
||||
/var/lib/ca-certificates/ r,
|
||||
/var/lib/ca-certificates/** r,
|
||||
/usr/local/share/ca-certificates/{,**} r,
|
||||
/var/lib/ca-certificates/{,**} r,
|
||||
|
||||
# acmetool
|
||||
/var/lib/acme/certs/*/chain r,
|
||||
@@ -45,5 +41,9 @@
|
||||
/etc/certbot/archive/*/chain*.pem r,
|
||||
/etc/certbot/archive/*/fullchain*.pem r,
|
||||
|
||||
# crypto policies used by various libraries
|
||||
/etc/crypto-policies/*/*.txt r,
|
||||
/usr/share/crypto-policies/*/*.txt r,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/ssl_certs.d>
|
||||
|
@@ -38,3 +38,4 @@
|
||||
/usr/lib/icecat-*/icecat Cx -> sanitized_helper,
|
||||
/usr/bin/opera Cx -> sanitized_helper,
|
||||
/opt/google/chrome{,-beta,-unstable}/google-chrome{,-beta,-unstable} Cx -> sanitized_helper,
|
||||
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave-browser{,-beta,-dev,-nightly} Cx -> sanitized_helper,
|
||||
|
@@ -28,10 +28,7 @@
|
||||
/usr/lib/mozilla/kmozillahelper Cxr -> sanitized_helper,
|
||||
|
||||
# Exo-aware applications
|
||||
/usr/bin/exo-open ixr,
|
||||
/usr/lib/@{multiarch}/xfce4/exo-1/exo-helper-1 ixr,
|
||||
/etc/xdg/xdg-xubuntu/xfce4/helpers.rc r,
|
||||
/etc/xdg/xfce4/helpers.rc r,
|
||||
include <abstractions/exo-open>
|
||||
|
||||
# unity webapps integration. Could go in its own abstraction
|
||||
owner /run/user/*/dconf/user rw,
|
||||
|
@@ -14,6 +14,7 @@
|
||||
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
|
||||
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
||||
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
||||
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
|
||||
|
||||
# Comment this out if using gpg plugin/addons
|
||||
audit deny @{HOME}/.gnupg/{,**} mrwkl,
|
||||
|
@@ -74,6 +74,12 @@ profile sanitized_helper {
|
||||
/opt/google/chrome{,-beta,-unstable}/chrome Pixr,
|
||||
/opt/google/chrome{,-beta,-unstable}/{,**/}lib*.so{,.*} m,
|
||||
|
||||
# The same is needed for Brave
|
||||
/opt/brave.com/brave{,-beta,-dev,-nightly}/chrome-sandbox PUxr,
|
||||
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave-browser{,-beta,-dev,-nightly} Pixr,
|
||||
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave Pixr,
|
||||
/opt/brave.com/brave{,-beta,-dev,-nightly}/{,**/}lib*.so{,.*} m,
|
||||
|
||||
# Full access
|
||||
/ r,
|
||||
/** rwkl,
|
||||
|
@@ -14,7 +14,8 @@
|
||||
# some services update wtmp, utmp, and lastlog with per-user
|
||||
# connection information
|
||||
/var/log/lastlog rwk,
|
||||
/var/log/wtmp wk,
|
||||
/var/log/wtmp rwk,
|
||||
/var/log/btmp rwk,
|
||||
@{run}/utmp rwk,
|
||||
|
||||
# Include additions to the abstraction
|
||||
|
@@ -20,6 +20,10 @@ profile dovecot-stats /usr/lib/dovecot/stats {
|
||||
capability setuid,
|
||||
capability sys_chroot,
|
||||
|
||||
# for metrics end-point (Prometheus)
|
||||
network inet stream,
|
||||
network inet6 stream,
|
||||
|
||||
/usr/lib/dovecot/stats mr,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
|
@@ -70,8 +70,6 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
||||
# access to iface mtu needed for Router Advertisement messages in IPv6
|
||||
# Neighbor Discovery protocol (RFC 2461)
|
||||
@{PROC}/sys/net/ipv6/conf/*/mtu r,
|
||||
# closing superfluous file descriptors scans /proc/self/fd/ to find open ones
|
||||
@{PROC}/@{pid}/fd/ r,
|
||||
|
||||
# for the read-only TFTP server
|
||||
@{TFTP_DIR}/ r,
|
||||
|
@@ -33,8 +33,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
capability sys_chroot,
|
||||
capability sys_resource,
|
||||
|
||||
signal send set=(int,quit,term) peer=/usr/lib/dovecot/*,
|
||||
signal send set=(int,quit,term) peer=dovecot-*,
|
||||
signal send set=(int,quit,term,kill) peer=/usr/lib/dovecot/*,
|
||||
signal send set=(int,quit,term,kill) peer=dovecot-*,
|
||||
|
||||
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
|
||||
unix (receive, send) type=stream peer=(label=dovecot-anvil),
|
||||
@@ -64,6 +64,7 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
/usr/lib/dovecot/ssl-params mrPx,
|
||||
/usr/lib/dovecot/stats Px,
|
||||
/usr/{bin,sbin}/dovecot mrix,
|
||||
/usr/share/dovecot/dh.pem r,
|
||||
/usr/share/dovecot/protocols.d/ r,
|
||||
/usr/share/dovecot/protocols.d/** r,
|
||||
/var/lib/dovecot/ w,
|
||||
|
@@ -23,6 +23,7 @@ profile nscd /usr/{bin,sbin}/nscd {
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
/etc/machine-id r,
|
||||
/etc/netgroup r,
|
||||
/etc/nscd.conf r,
|
||||
/usr/{bin,sbin}/nscd rmix,
|
||||
@@ -30,7 +31,7 @@ profile nscd /usr/{bin,sbin}/nscd {
|
||||
@{run}/nscd/ rw,
|
||||
@{run}/nscd/db* rwl,
|
||||
@{run}/nscd/socket wl,
|
||||
/{var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
|
||||
/{var/cache,var/db,var/lib,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
|
||||
@{run}/{nscd/,}nscd.pid rwl,
|
||||
/var/lib/libvirt/dnsmasq/ r,
|
||||
/var/lib/libvirt/dnsmasq/*.status r,
|
||||
|
@@ -17,6 +17,7 @@ profile ntpd /usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/openssl>
|
||||
include <abstractions/ssl_certs>
|
||||
include <abstractions/xad>
|
||||
|
||||
capability dac_override,
|
||||
|
@@ -25,10 +25,12 @@ profile postfix-bounce /usr/lib/postfix/{bin/,sbin/,}bounce {
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/* rwk,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]* rwkl,
|
||||
/{var/spool/postfix/,}bounce/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}bounce/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}bounce/[0-9A-F]/* rwk,
|
||||
/{var/spool/postfix/,}bounce/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}bounce/[0-9A-F]* rwkl,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/* rwkl,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/* rwkl,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 Canonical, Ltd.
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -25,6 +26,7 @@ profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
|
||||
/{var/spool/postfix/,}deferred/[0-9A-F]/[0-9A-F]* rwl,
|
||||
/{var/spool/postfix/,}deferred/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}flush/ rwl,
|
||||
/{var/spool/postfix/,}flush/* w, # filename is based on hostname
|
||||
/{var/spool/postfix/,}flush/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}flush/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}flush/[0-9A-F]/ rwl,
|
||||
@@ -33,7 +35,7 @@ profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}public/qmgr w,
|
||||
/{var/spool/postfix/,}pid/unix.flush rw,
|
||||
/{var/spool/postfix/,}pid/unix.flush rwk,
|
||||
/etc/mtab r,
|
||||
|
||||
@{HOME}/.forward r,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 Canonical, Ltd.
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -31,9 +32,9 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
|
||||
/{usr/,}bin/date mixr,
|
||||
|
||||
/dev/tty rw,
|
||||
/etc/{postfix/,}aliases.db rk,
|
||||
# mailman on SuSE is configed to have its own alias file
|
||||
/var/lib/mailman/data/aliases.db rk,
|
||||
/etc/aliases.{lm,}db rk,
|
||||
# mailman on SuSE is configured to have its own alias file
|
||||
/var/lib/mailman/data/aliases.{lm,}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,
|
||||
@@ -41,9 +42,6 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
|
||||
/{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,
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ profile postfix-qmgr /usr/lib/postfix/{bin/,sbin/,}qmgr {
|
||||
/{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/,}bounce/[0-9A-F]* w,
|
||||
/{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,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 Canonical, Ltd.
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -24,6 +25,7 @@ profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]* r,
|
||||
/{var/spool/postfix/,}defer/ r,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/* r,
|
||||
/{var/spool/postfix/,}defer/[0-9A-F]/[0-9A-F]/ r,
|
||||
@@ -41,6 +43,7 @@ profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}maildrop/ r,
|
||||
/{var/spool/postfix/,}maildrop/[0-9A-F]*[0-9A-F] r,
|
||||
/{var/spool/postfix/,}maildrop/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}pid/unix.showq rwk,
|
||||
owner /{var/spool/postfix,}/defer/[0-9A-F]/[0-9A-F]* r,
|
||||
|
@@ -30,6 +30,7 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/* rwk,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]* rwlk,
|
||||
/{var/spool/postfix/,}private/anvil w,
|
||||
/{var/spool/postfix/,}private/bounce w,
|
||||
/{var/spool/postfix/,}private/defer w,
|
||||
@@ -43,7 +44,5 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
||||
/etc/postfix/{ssl/,}*.pem r,
|
||||
/etc/postfix/prng_exch rw,
|
||||
/usr/share/ssl/certs/ca-bundle.crt r,
|
||||
/etc/postfix/virtual.db r,
|
||||
/etc/postfix/sasl_passwd.db r,
|
||||
/etc/mtab r,
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2018 Canonical, Ltd.
|
||||
# Copyright (C) 2019 Christian Boltz
|
||||
# Copyright (C) 2019-2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -29,12 +29,11 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
|
||||
/usr/sbin/postdrop rPx,
|
||||
|
||||
/dev/urandom r,
|
||||
/etc/aliases.db rk,
|
||||
/etc/aliases.{lm,}db rk,
|
||||
# mailman on SuSE is configured to have its own alias db
|
||||
/var/lib/mailman/data/aliases.db rk,
|
||||
/var/lib/mailman/data/aliases.{lm,}db rk,
|
||||
/etc/mtab r,
|
||||
/etc/fstab r,
|
||||
/etc/postfix/*.db r,
|
||||
/etc/postfix/*.regexp r,
|
||||
/etc/postfix/{ssl/,}*.pem r,
|
||||
/etc/postfix/smtpd_scache.dir r,
|
||||
|
@@ -23,9 +23,6 @@ profile postfix-trivial-rewrite /usr/lib/postfix/{bin/,sbin/,}trivial-rewrite {
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}trivial-rewrite mrix,
|
||||
|
||||
/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,
|
||||
|
@@ -48,6 +48,11 @@ profile dhclient /{usr/,}sbin/dhclient {
|
||||
@{PROC}/interrupts r,
|
||||
@{PROC}/@{pid}/net/dev r,
|
||||
@{PROC}/rtc r,
|
||||
|
||||
# dhcliet wants to update its threads with functional names
|
||||
# see lp1918410
|
||||
owner @{PROC}/@{pid}/task/[0-9]*/comm rw,
|
||||
|
||||
# following rule shouldn't work, self is a symlink
|
||||
@{PROC}/self/status r,
|
||||
/{usr/,}sbin/arp mrix,
|
||||
@@ -58,14 +63,14 @@ profile dhclient /{usr/,}sbin/dhclient {
|
||||
/usr/lib/{NetworkManager/,}nm-dhcp-helper rix,
|
||||
/var/lib/dhclient/dhclient{6,}.leases* rw,
|
||||
/var/lib/dhcp/dhclient*.leases rw,
|
||||
/var/lib/dhcp6/dhclient.leases rw,
|
||||
/var/lib/dhcp{6,}/dhclient.leases rw,
|
||||
/var/lib/NetworkManager/dhclient{6,}-*.conf r,
|
||||
/var/lib/NetworkManager/dhclient{6,}-*.lease rw,
|
||||
/var/log/lastlog r,
|
||||
/var/log/messages r,
|
||||
/var/log/wtmp r,
|
||||
/{,var/}run/dhclient{6,}.pid rw,
|
||||
/{,var/}run/dhclient{6,}-*.pid rw,
|
||||
/{,var/}run/dhclient{6,}{-,.}*.pid rw,
|
||||
/var/spool r,
|
||||
/var/spool/mail r,
|
||||
|
||||
|
@@ -12,13 +12,20 @@ profile dhclient-script /{usr/,}sbin/dhclient-script {
|
||||
include <abstractions/bash>
|
||||
include <abstractions/consoles>
|
||||
|
||||
/{usr/,}bin/dash rix,
|
||||
/{usr/,}bin/bash rix,
|
||||
/{usr/,}bin/grep rix,
|
||||
/{usr/,}bin/sleep rix,
|
||||
/{usr/,}bin/touch rix,
|
||||
/{usr/,}bin/run-parts rix,
|
||||
/{usr/,}bin/logger rix,
|
||||
/dev/.sysconfig/network/** r,
|
||||
/etc/netconfig.d/* mrix,
|
||||
/etc/sysconfig/network/** r,
|
||||
/etc/dhcp/{**,} r,
|
||||
/{usr/,}sbin/dhclient-script r,
|
||||
/{usr/,}sbin/ip rix,
|
||||
/{usr/,}sbin/resolvconf rPUx,
|
||||
|
||||
include if exists <local/sbin.dhclient-script>
|
||||
}
|
||||
|
@@ -123,6 +123,10 @@ include <tunables/global>
|
||||
deny /usr/share/mozilla/extensions/**/ w,
|
||||
deny /usr/share/mozilla/ w,
|
||||
|
||||
# needed by widevine
|
||||
ptrace (trace) peer=@{profile_name},
|
||||
@{HOME}/.mozilla/firefox/*/gmp-widevinecdm/*/lib*so m,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
# Local path is disabled, we only enable them for profiles we promote
|
||||
# out of extras.
|
||||
|
@@ -31,6 +31,7 @@ include <tunables/global>
|
||||
/etc/dhcpd.conf r,
|
||||
/etc/named.d/* r,
|
||||
@{PROC}/net/dev r,
|
||||
@{PROC}/sys/net/ipv4/ip_local_port_range r,
|
||||
/usr/sbin/dhcpd rmix,
|
||||
/var/lib/dhcp/{db/,}dhcpd{6,}.leases* rwl,
|
||||
/var/lib/dhcp/etc/dhcpd.conf r,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -19,11 +20,11 @@ include <tunables/global>
|
||||
include <abstractions/consoles>
|
||||
include <abstractions/postfix-common>
|
||||
/etc/aliases r,
|
||||
/etc/aliases.db rwlk,
|
||||
/etc/aliases.{lm,}db rwlk,
|
||||
/etc/postfix r,
|
||||
/etc/postfix/main.cf r,
|
||||
/etc/postfix/aliases r,
|
||||
/etc/postfix/aliases.db rwl,
|
||||
/etc/postfix/aliases.{lm,}db rwl,
|
||||
/etc/postfix/__db.aliases.db lrw,
|
||||
/etc/__db.aliases.db rwl,
|
||||
/usr/sbin/postalias rmix,
|
||||
@@ -31,7 +32,7 @@ include <tunables/global>
|
||||
# On SuSE, mailman is configured to use its own alias db
|
||||
/var/lib/mailman/data/aliases r,
|
||||
/var/lib/mailman/data/__db.aliases.db rwl,
|
||||
/var/lib/mailman/data/aliases.db rwl,
|
||||
/var/lib/mailman/data/aliases.{lm,}db rwl,
|
||||
/var/spool/postfix r,
|
||||
/var/spool/postfix/pid r,
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -22,6 +23,7 @@ include <tunables/global>
|
||||
/etc/mtab r,
|
||||
/etc/postfix/* r,
|
||||
/etc/postfix/*.db rwlk,
|
||||
/etc/postfix/*.lmdb rwlk,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/usr/share/icu/[0-9]*.[0-9]*/*.dat r,
|
||||
/usr/sbin/postmap rmix,
|
||||
|
@@ -56,7 +56,7 @@ create_cache_files()
|
||||
do
|
||||
cachefile="${cachedir}/${policy}"
|
||||
|
||||
echo "profile $policy { /f r, }" | ${subdomain} -qS > "$cachefile"
|
||||
echo "profile $policy { /f r, }" | ${subdomain} "${parser_config}" -qS > "$cachefile"
|
||||
done
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,8 @@
|
||||
# in the name.
|
||||
#=END
|
||||
|
||||
LANG=C
|
||||
|
||||
pwd=`dirname $0`
|
||||
pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
|
@@ -3,7 +3,8 @@ subdomain=${PWD}/../../../parser/apparmor_parser
|
||||
#subdomain=/sbin/apparmor_parser
|
||||
|
||||
# 2. additional arguments to the apparmor parser
|
||||
parser_args="-q -K"
|
||||
parser_config="--config-file=${PWD}/../../../parser/parser.conf"
|
||||
parser_args="${parser_config} -q -K"
|
||||
|
||||
# 3. directory to be used for temp files
|
||||
# Need to be able to access this directory by the root and nobody users.
|
||||
|
@@ -3,7 +3,9 @@
|
||||
subdomain=/sbin/apparmor_parser
|
||||
|
||||
# 2. additional arguments to the apparmor parser
|
||||
parser_args="-q -K"
|
||||
parser_config=""
|
||||
parser_args="${parser_config} -q -K"
|
||||
|
||||
|
||||
# 3. directory to be used for temp files
|
||||
# Need to be able to access this directory by the root and nobody users.
|
||||
|
@@ -87,12 +87,17 @@ check_severity_db: /usr/include/linux/capability.h severity.db
|
||||
test "$$RC" -eq 0
|
||||
|
||||
# check_pod_files is defined in common/Make.rules
|
||||
.PHONY: check
|
||||
.SILENT: check
|
||||
check: check_severity_db check_pod_files
|
||||
.PHONY: check_lint
|
||||
.SILENT: check_lint
|
||||
check_lint:
|
||||
for i in ${PYTOOLS} apparmor test/*.py; do \
|
||||
echo Checking $$i; \
|
||||
$(PYFLAKES) $$i || exit 1; \
|
||||
done
|
||||
|
||||
# check_pod_files is defined in common/Make.rules
|
||||
.PHONY: check
|
||||
.SILENT: check
|
||||
check: check_severity_db check_pod_files check_lint
|
||||
$(MAKE) -C test check
|
||||
$(MAKE) -C vim check
|
||||
|
@@ -72,20 +72,14 @@ if args.json:
|
||||
aaui.set_json_mode()
|
||||
|
||||
profiling = args.program
|
||||
profiledir = args.dir
|
||||
|
||||
apparmor.init_aa()
|
||||
apparmor.init_aa(profiledir=args.dir)
|
||||
apparmor.set_logfile(args.file)
|
||||
|
||||
aa_mountpoint = apparmor.check_for_apparmor()
|
||||
if not aa_mountpoint:
|
||||
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
|
||||
|
||||
if profiledir:
|
||||
apparmor.profile_dir = apparmor.get_full_path(profiledir)
|
||||
if not os.path.isdir(apparmor.profile_dir):
|
||||
raise apparmor.AppArmorException(_("%s is not a directory.") %profiledir)
|
||||
|
||||
program = None
|
||||
#if os.path.exists(apparmor.which(profiling.strip())):
|
||||
if os.path.exists(profiling):
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import apparmor.aa as apparmor
|
||||
import apparmor.ui as aaui
|
||||
@@ -36,21 +35,16 @@ args = parser.parse_args()
|
||||
if args.json:
|
||||
aaui.set_json_mode()
|
||||
|
||||
profiledir = args.dir
|
||||
logmark = args.mark or ''
|
||||
|
||||
apparmor.init_aa()
|
||||
apparmor.init_aa(profiledir=args.dir)
|
||||
|
||||
apparmor.set_logfile(args.file)
|
||||
|
||||
aa_mountpoint = apparmor.check_for_apparmor()
|
||||
if not aa_mountpoint:
|
||||
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
|
||||
|
||||
if profiledir:
|
||||
apparmor.profile_dir = apparmor.get_full_path(profiledir)
|
||||
if not os.path.isdir(apparmor.profile_dir):
|
||||
raise apparmor.AppArmorException("%s is not a directory."%profiledir)
|
||||
|
||||
apparmor.loadincludes()
|
||||
|
||||
apparmor.read_profiles(True)
|
||||
|
@@ -14,7 +14,6 @@
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import apparmor.aa
|
||||
|
||||
@@ -22,7 +21,6 @@ import apparmor.severity
|
||||
import apparmor.cleanprofile as cleanprofile
|
||||
import apparmor.ui as aaui
|
||||
|
||||
from apparmor.common import AppArmorException
|
||||
|
||||
|
||||
# setup exception handling
|
||||
@@ -41,16 +39,10 @@ args = parser.parse_args()
|
||||
|
||||
args.other = None
|
||||
|
||||
apparmor.aa.init_aa()
|
||||
apparmor.aa.init_aa(profiledir=args.dir)
|
||||
|
||||
profiles = args.files
|
||||
|
||||
profiledir = args.dir
|
||||
if profiledir:
|
||||
apparmor.aa.profile_dir = apparmor.aa.get_full_path(profiledir)
|
||||
if not os.path.isdir(apparmor.aa.profile_dir):
|
||||
raise AppArmorException(_("%s is not a directory.") %profiledir)
|
||||
|
||||
def find_profiles_from_files(files):
|
||||
profile_to_filename = dict()
|
||||
for file_name in files:
|
||||
|
@@ -232,6 +232,27 @@ def follow_apparmor_events(logfile, wait=0):
|
||||
format(int(time.time()) - start_time)
|
||||
)
|
||||
|
||||
(logdata, log_inode, log_size) = reopen_logfile_if_needed(logfile, logdata, log_inode, log_size)
|
||||
|
||||
for event in parse_logdata(logdata):
|
||||
# @TODO Alternatively use os.times()
|
||||
if int(time.time()) - start_time < wait:
|
||||
debug_logger.debug('Omitted an event seen during wait time')
|
||||
continue
|
||||
yield event
|
||||
|
||||
if debug_logger.debugging and debug_logger.debug_level <= 10 and int(time.time()) - start_time > 100:
|
||||
debug_logger.debug('Debug mode detected: aborting notification emitter after 100 seconds.')
|
||||
sys.exit(0)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def reopen_logfile_if_needed(logfile, logdata, log_inode, log_size):
|
||||
retry = True
|
||||
|
||||
while retry:
|
||||
try:
|
||||
# Reopen file if inode has chaneged, e.g. rename by logrotate
|
||||
if os.stat(logfile).st_ino != log_inode:
|
||||
debug_logger.debug('Logfile was renamed, reload to read the new file.')
|
||||
@@ -249,18 +270,14 @@ def follow_apparmor_events(logfile, wait=0):
|
||||
if os.stat(logfile).st_size > log_size:
|
||||
log_size = os.stat(logfile).st_size
|
||||
|
||||
for event in parse_logdata(logdata):
|
||||
# @TODO Alternatively use os.times()
|
||||
if int(time.time()) - start_time < wait:
|
||||
debug_logger.debug('Omitted an event seen during wait time')
|
||||
continue
|
||||
yield event
|
||||
|
||||
if debug_logger.debug_level <= 10 and int(time.time()) - start_time > 100:
|
||||
debug_logger.debug('Debug mode detected: aborting notification emitter after 100 seconds.')
|
||||
sys.exit(0)
|
||||
|
||||
retry = False
|
||||
except FileNotFoundError:
|
||||
# @TODO: switch to epoll/inotify/
|
||||
debug_logger.debug('Logfile not found, retrying.')
|
||||
time.sleep(1)
|
||||
# @TODO: send notification if reopening the log fails too many times
|
||||
|
||||
return (logdata, log_inode, log_size)
|
||||
|
||||
|
||||
def get_apparmor_events(logfile, since=0):
|
||||
@@ -407,7 +424,8 @@ def main():
|
||||
debug_logger.activateStderr()
|
||||
debug_logger.debug('Logging level: {}'.format(debug_logger.debug_level))
|
||||
debug_logger.debug('Running as uid: {0[0]}, euid: {0[1]}, suid: {0[2]}'.format(os.getresuid()))
|
||||
|
||||
if args.poll:
|
||||
debug_logger.debug('Running with --debug and --poll. Will exit in 100s')
|
||||
# Sanity checks
|
||||
user_ids = os.getresuid()
|
||||
groups_ids = os.getresgid()
|
||||
|
@@ -454,7 +454,11 @@ def create_new_profile(localfile, is_stub=False):
|
||||
local_profile = hasher()
|
||||
local_profile[localfile] = ProfileStorage('NEW', localfile, 'create_new_profile()')
|
||||
local_profile[localfile]['flags'] = 'complain'
|
||||
local_profile[localfile]['inc_ie'].add(IncludeRule('abstractions/base', False, True))
|
||||
|
||||
if os.path.join(profile_dir, 'abstractions/base') in include:
|
||||
local_profile[localfile]['inc_ie'].add(IncludeRule('abstractions/base', False, True))
|
||||
else:
|
||||
aaui.UI_Important(_("WARNING: Can't find %s, therefore not adding it to the new profile.") % 'abstractions/base')
|
||||
|
||||
if os.path.exists(localfile) and os.path.isfile(localfile):
|
||||
interpreter_path, abstraction = get_interpreter_and_abstraction(localfile)
|
||||
@@ -464,7 +468,10 @@ def create_new_profile(localfile, is_stub=False):
|
||||
local_profile[localfile]['file'].add(FileRule(interpreter_path, None, 'ix', FileRule.ALL, owner=False))
|
||||
|
||||
if abstraction:
|
||||
local_profile[localfile]['inc_ie'].add(IncludeRule(abstraction, False, True))
|
||||
if os.path.join(profile_dir, abstraction) in include:
|
||||
local_profile[localfile]['inc_ie'].add(IncludeRule(abstraction, False, True))
|
||||
else:
|
||||
aaui.UI_Important(_("WARNING: Can't find %s, therefore not adding it to the new profile.") % abstraction)
|
||||
|
||||
handle_binfmt(local_profile[localfile], interpreter_path)
|
||||
else:
|
||||
@@ -1941,7 +1948,11 @@ def parse_profile_data(data, file, do_include):
|
||||
active_profiles.add_inc_ie(file, rule_obj)
|
||||
|
||||
for incname in rule_obj.get_full_paths(profile_dir):
|
||||
load_include(incname)
|
||||
if incname == file:
|
||||
# warn about endless loop, and don't call load_include() (again) for this file
|
||||
aaui.UI_Important(_('WARNING: endless loop detected: file %s includes itsself' % incname))
|
||||
else:
|
||||
load_include(incname)
|
||||
|
||||
elif NetworkRule.match(line):
|
||||
if not profile:
|
||||
@@ -2511,7 +2522,7 @@ def logger_path():
|
||||
|
||||
######Initialisations######
|
||||
|
||||
def init_aa(confdir="/etc/apparmor"):
|
||||
def init_aa(confdir="/etc/apparmor", profiledir=None):
|
||||
global CONFDIR
|
||||
global conf
|
||||
global cfg
|
||||
@@ -2534,7 +2545,10 @@ def init_aa(confdir="/etc/apparmor"):
|
||||
if cfg['settings'].get('default_owner_prompt', False):
|
||||
cfg['settings']['default_owner_prompt'] = ''
|
||||
|
||||
profile_dir = conf.find_first_dir(cfg['settings'].get('profiledir')) or '/etc/apparmor.d'
|
||||
if profiledir:
|
||||
profile_dir = profiledir
|
||||
else:
|
||||
profile_dir = conf.find_first_dir(cfg['settings'].get('profiledir')) or '/etc/apparmor.d'
|
||||
profile_dir = os.path.abspath(profile_dir)
|
||||
if not os.path.isdir(profile_dir):
|
||||
raise AppArmorException('Can\'t find AppArmor profiles in %s' % (profile_dir))
|
||||
|
@@ -25,10 +25,9 @@ _ = init_translation()
|
||||
|
||||
class aa_tools:
|
||||
def __init__(self, tool_name, args):
|
||||
apparmor.init_aa()
|
||||
apparmor.init_aa(profiledir=args.dir)
|
||||
|
||||
self.name = tool_name
|
||||
self.profiledir = args.dir
|
||||
self.profiling = args.program
|
||||
self.check_profile_dir()
|
||||
self.silent = None
|
||||
@@ -43,11 +42,6 @@ class aa_tools:
|
||||
self.silent = args.silent
|
||||
|
||||
def check_profile_dir(self):
|
||||
if self.profiledir:
|
||||
apparmor.profile_dir = apparmor.get_full_path(self.profiledir)
|
||||
if not os.path.isdir(apparmor.profile_dir):
|
||||
raise apparmor.AppArmorException("%s is not a directory." % self.profiledir)
|
||||
|
||||
if not user_perm(apparmor.profile_dir):
|
||||
raise apparmor.AppArmorException("Cannot write to profile directory: %s" % (apparmor.profile_dir))
|
||||
|
||||
@@ -183,6 +177,7 @@ class aa_tools:
|
||||
|
||||
def cmd_autodep(self):
|
||||
apparmor.read_profiles()
|
||||
apparmor.loadincludes()
|
||||
|
||||
for (program, profile) in self.get_next_to_profile():
|
||||
if not program:
|
||||
|
@@ -1079,11 +1079,11 @@ msgstr "(C)hild sauber ausführen"
|
||||
|
||||
#: ../apparmor/ui.py:239
|
||||
msgid "(N)amed"
|
||||
msgstr "(B)enannt"
|
||||
msgstr "Be(n)annt"
|
||||
|
||||
#: ../apparmor/ui.py:240
|
||||
msgid "(N)amed Clean Exec"
|
||||
msgstr "(B)enannte sauber ausführen"
|
||||
msgstr "Be(n)annte sauber ausführen"
|
||||
|
||||
#: ../apparmor/ui.py:241
|
||||
msgid "(U)nconfined"
|
||||
@@ -1111,11 +1111,11 @@ msgstr "(C)hild vererbt saubere Ausführung"
|
||||
|
||||
#: ../apparmor/ui.py:247
|
||||
msgid "(N)amed Inherit"
|
||||
msgstr "(B)enannte Vererbung"
|
||||
msgstr "Be(n)annte Vererbung"
|
||||
|
||||
#: ../apparmor/ui.py:248
|
||||
msgid "(N)amed Inherit Clean Exec"
|
||||
msgstr "(B)enannte Vererbung sauber ausführen"
|
||||
msgstr "Be(n)annte Vererbung sauber ausführen"
|
||||
|
||||
#: ../apparmor/ui.py:249
|
||||
msgid "(X) ix On"
|
||||
|
@@ -1147,11 +1147,11 @@ msgstr "(B)aru"
|
||||
|
||||
#: ../apparmor/ui.py:254
|
||||
msgid "(G)lob"
|
||||
msgstr "(G)umpal"
|
||||
msgstr "G(u)mpal"
|
||||
|
||||
#: ../apparmor/ui.py:255
|
||||
msgid "Glob with (E)xtension"
|
||||
msgstr "Gumpal dengan (E)kstensi"
|
||||
msgstr "Gumpal dengan E(k)stensi"
|
||||
|
||||
#: ../apparmor/ui.py:256
|
||||
msgid "(A)dd Requested Hat"
|
||||
@@ -1159,7 +1159,7 @@ msgstr "(T)ambahkan Topi yang Diminta"
|
||||
|
||||
#: ../apparmor/ui.py:257
|
||||
msgid "(U)se Default Hat"
|
||||
msgstr "(G)unakan Topi Default"
|
||||
msgstr "Gunakan Topi (D)efault"
|
||||
|
||||
#: ../apparmor/ui.py:258
|
||||
msgid "(S)can system log for AppArmor events"
|
||||
@@ -1175,7 +1175,7 @@ msgstr "(L)ihat Profil"
|
||||
|
||||
#: ../apparmor/ui.py:261
|
||||
msgid "(U)se Profile"
|
||||
msgstr "(G)unakan Profil"
|
||||
msgstr "Gunakan (P)rofil"
|
||||
|
||||
#: ../apparmor/ui.py:262
|
||||
msgid "(C)reate New Profile"
|
||||
|
@@ -1004,7 +1004,7 @@ msgstr ""
|
||||
|
||||
#: ../apparmor/ui.py:223
|
||||
msgid "(A)llow"
|
||||
msgstr "(T)illåt"
|
||||
msgstr "Ti(l)låt"
|
||||
|
||||
#: ../apparmor/ui.py:224
|
||||
msgid "(M)ore"
|
||||
|
@@ -30,6 +30,7 @@
|
||||
CAP_SETUID 9
|
||||
CAP_FOWNER 9
|
||||
CAP_BPF 9
|
||||
CAP_CHECKPOINT_RESTORE 9
|
||||
# Denial of service, bypass audit controls, information leak
|
||||
CAP_SYS_TIME 8
|
||||
CAP_NET_ADMIN 8
|
||||
|
@@ -189,6 +189,7 @@ optional arguments:
|
||||
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_has)
|
||||
self.assertIn(expected_output_has, output, result + output)
|
||||
|
||||
@unittest.skipUnless(os.path.isfile('/var/log/wtmp'), 'Requires wtmp on system')
|
||||
def test_entries_since_login(self):
|
||||
'''Test showing log entries since last login'''
|
||||
|
||||
|
@@ -28,7 +28,7 @@ class TestIs_str_type(AATest):
|
||||
|
||||
class AaTest_split_name(AATest):
|
||||
tests = [
|
||||
# log event path and perms expected proposals
|
||||
# full profile name expected parts
|
||||
('foo', ('foo', 'foo')),
|
||||
('foo//bar', ('foo', 'bar')),
|
||||
('foo//bar//baz', ('foo', 'bar')), # XXX nested child profiles get cut off
|
||||
|
@@ -235,6 +235,11 @@ class TestAdd_alias(AATest):
|
||||
self.pl.add_alias('/etc/apparmor.d/bin.foo', AliasRule('/foo', None)) # target None insteadd of str
|
||||
self.assertEqual(list(self.pl.files.keys()), [])
|
||||
|
||||
def testAdd_alias_error_3(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.add_alias('/etc/apparmor.d/bin.foo', 'alias /foo -> /bar,') # str insteadd of AliasRule
|
||||
self.assertEqual(list(self.pl.files.keys()), [])
|
||||
|
||||
def test_dedup_alias_1(self):
|
||||
self.pl.add_alias('/etc/apparmor.d/bin.foo', AliasRule('/foo', '/bar'))
|
||||
self.pl.add_alias('/etc/apparmor.d/bin.foo', AliasRule('/foo', '/another_target'))
|
||||
|
@@ -594,14 +594,15 @@ class Test_re_match_include_parse_abi(AATest):
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(re_match_include_parse(params, 'abi'), expected)
|
||||
|
||||
class Test_re_match_include_parse_empty_filename(AATest):
|
||||
class Test_re_match_include_parse_errors(AATest):
|
||||
tests = [
|
||||
(('include <>', 'include'), AppArmorException),
|
||||
(('include <>', 'include'), AppArmorException), # various rules with empty filename
|
||||
(('include ""', 'include'), AppArmorException),
|
||||
(('include ', 'include'), AppArmorException),
|
||||
(('abi <>,', 'abi'), AppArmorException),
|
||||
(('abi "",', 'abi'), AppArmorException),
|
||||
(('abi ,', 'abi'), AppArmorException),
|
||||
(('abi <foo>,', 'invalid'), AppArmorBug), # invalid rule name
|
||||
]
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
|
@@ -61,7 +61,7 @@ class TestHotkeyConflicts(AATest):
|
||||
keys = dict()
|
||||
for key in params:
|
||||
text = t.gettext(CMDS[key])
|
||||
hotkey = get_translated_hotkey(text)
|
||||
hotkey = get_translated_hotkey(text).lower()
|
||||
|
||||
if keys.get(hotkey):
|
||||
raise Exception("Hotkey conflict: '%s' and '%s' in language %s" % (keys[hotkey], text, language))
|
||||
|
@@ -189,6 +189,8 @@ syn match sdInclude /\s*include\s<\S*>/ " TODO: doesn't check until $
|
||||
syn match sdInclude /\s*#include\sif\sexists\s<\S*>/ " TODO: doesn't check until $
|
||||
syn match sdInclude /\s*include\sif\sexists\s<\S*>/ " TODO: doesn't check until $
|
||||
|
||||
syn match sdInclude /\s*abi\s<\S*>\s*,/ contains=sdComment " TODO: doesn't check until $
|
||||
|
||||
" basic profile block...
|
||||
" \s+ does not work in end=, therefore using \s\s*
|
||||
syn region Normal start=/\v^(profile\s+)?\S+\s+@@flags@@=\{/ matchgroup=sdProfileEnd end=/^}\s*$/ contains=sdProfileName,Hat,@sdEntry,sdComment,sdError,sdInclude
|
||||
|
Reference in New Issue
Block a user