mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 22:35:35 +00:00
Compare commits
176 Commits
v3.0.3
...
160-the-tr
Author | SHA1 | Date | |
---|---|---|---|
|
3ee4f9c75f | ||
|
a07515bdd4 | ||
|
d9cb8df696 | ||
|
94b7704e56 | ||
|
d270b2c3d0 | ||
|
38c63026a4 | ||
|
6a170ddaa1 | ||
|
4ef975fb97 | ||
|
9494238eec | ||
|
edf52a7531 | ||
|
09dfbb97e5 | ||
|
f9078c4b01 | ||
|
eb1328f18a | ||
|
f931daa771 | ||
|
9aa70ab710 | ||
|
c734839551 | ||
|
c32c970d00 | ||
|
af4800f3b8 | ||
|
f17143b5c3 | ||
|
60e6847e85 | ||
|
277677daf3 | ||
|
4101d74de6 | ||
|
5ad5dd0bcb | ||
|
2852e1ecdf | ||
|
d4e0a94511 | ||
|
fe477af62a | ||
|
855dbd4ac8 | ||
|
3f51877220 | ||
|
aaad284d8d | ||
|
3448127ca6 | ||
|
accc380326 | ||
|
d442620102 | ||
|
089b266c03 | ||
|
55a7c89117 | ||
|
4c77f7193b | ||
|
c2718e2677 | ||
|
447ce37b47 | ||
|
08719eebc1 | ||
|
a07f30e25d | ||
|
32bd2bcec3 | ||
|
cc2d71023b | ||
|
d0693b09b5 | ||
|
bb5ca91e7e | ||
|
0f21ca6173 | ||
|
0f1d5fdba4 | ||
|
d5de9692ab | ||
|
b6fbe10d11 | ||
|
5aab543a3b | ||
|
f7a365f89f | ||
|
7cfda2772d | ||
|
3a87b33af7 | ||
|
7e5c02e3d4 | ||
|
33f2b3692b | ||
|
718fa5b9da | ||
|
ee5303c8a0 | ||
|
656f2103ed | ||
|
681c976550 | ||
|
65ba20b955 | ||
|
136502acd9 | ||
|
d50262cf2c | ||
|
a83f5d7a85 | ||
|
1bd0d8f2ff | ||
|
15e897cad0 | ||
|
0ee0b9a9e8 | ||
|
7bd1f48799 | ||
|
f1c53e125f | ||
|
c5ef2d2f9e | ||
|
63bcad086f | ||
|
cb65ab92d0 | ||
|
cc113f4820 | ||
|
e38be7b14f | ||
|
69c6ac3073 | ||
|
d86b7acd31 | ||
|
7e02f254a3 | ||
|
cc28ebaab4 | ||
|
ca344a3601 | ||
|
d7ce5f0d2e | ||
|
2e6bdc0b64 | ||
|
8d422ff66e | ||
|
70bbc321db | ||
|
c3d3203a60 | ||
|
32b11c0375 | ||
|
f7e6f795c3 | ||
|
a108934091 | ||
|
3f11eebc17 | ||
|
2cbd0d94be | ||
|
20234d240e | ||
|
c43bdf2e8b | ||
|
c2d105f81b | ||
|
c421fcd38a | ||
|
b646bbf21b | ||
|
6e5dba4f49 | ||
|
d26da6c42f | ||
|
4a7b029246 | ||
|
8782f53593 | ||
|
05547ac8f6 | ||
|
8b708d3b45 | ||
|
461d9c2294 | ||
|
7c88f02d6a | ||
|
e0ef309542 | ||
|
44aa30cf2a | ||
|
e5733d726d | ||
|
0af37358e6 | ||
|
af0f16a3bf | ||
|
78bd811e2a | ||
|
dfd7c245cd | ||
|
f6b3de7116 | ||
|
c29357a294 | ||
|
e57174589c | ||
|
7cf54f2cd8 | ||
|
d08d1a00a3 | ||
|
07bd11390e | ||
|
f3a816d6a5 | ||
|
87eec0d62d | ||
|
ab6e9b2de2 | ||
|
53d812cfd2 | ||
|
6b96a9badc | ||
|
9d8e111abe | ||
|
2f9d172c64 | ||
|
11d3218519 | ||
|
d6e18b0db8 | ||
|
0da70b173c | ||
|
0cb35fda84 | ||
|
24855edd11 | ||
|
32d748ab0f | ||
|
1961bb7719 | ||
|
3ff07adda5 | ||
|
dbb1b900b8 | ||
|
1abe101734 | ||
|
9b30f9306d | ||
|
9ff0bbb69e | ||
|
6039d1580a | ||
|
cfc57c08e6 | ||
|
81867f9424 | ||
|
15dc06248c | ||
|
8ea7630b6d | ||
|
43eb54d13c | ||
|
38c611ed31 | ||
|
e0b20a4d2f | ||
|
89fc65592b | ||
|
17cb8f0418 | ||
|
2c2dbdc3a3 | ||
|
4a226637f5 | ||
|
644a473971 | ||
|
71a51fcb18 | ||
|
1033e19171 | ||
|
5ac368bce7 | ||
|
5aa6db68e0 | ||
|
821f9fe42d | ||
|
40b7019d72 | ||
|
21060e802a | ||
|
01f5954b5c | ||
|
ec19ff9f72 | ||
|
042a75a6a5 | ||
|
05acf374b1 | ||
|
0dbcbee700 | ||
|
bd1e22ad07 | ||
|
c343f052c0 | ||
|
2eea414c68 | ||
|
8319bc5dc7 | ||
|
286f071259 | ||
|
6e908f28d6 | ||
|
a2a0d14b9c | ||
|
17c55b3bf8 | ||
|
37b9028499 | ||
|
9b70ef4fb7 | ||
|
6e7d1b6baa | ||
|
1909561150 | ||
|
3f752fac5f | ||
|
37552669d4 | ||
|
e6e54dc9e7 | ||
|
4a89067c1a | ||
|
9a8fee6bf1 | ||
|
c9255a0343 | ||
|
47263a3a74 | ||
|
e0200b1b16 |
@@ -1,7 +1,7 @@
|
||||
---
|
||||
image: ubuntu:latest
|
||||
before_script:
|
||||
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil zlib1g-dev
|
||||
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-coverage python3-notify2 python3-psutil zlib1g-dev
|
||||
- lsb_release -a
|
||||
- uname -a
|
||||
|
||||
@@ -42,6 +42,7 @@ test-all:
|
||||
- make -C parser check
|
||||
- make -C binutils check
|
||||
- make -C utils check
|
||||
- make -C utils/test coverage-regression
|
||||
- make -C changehat/mod_apparmor check
|
||||
- make -C profiles check-parser
|
||||
- make -C profiles check-abstractions.d
|
||||
|
@@ -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>
|
||||
|
73
binutils/po/aa_enabled.pot
Normal file
73
binutils/po/aa_enabled.pot
Normal file
@@ -0,0 +1,73 @@
|
||||
# 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:52-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_enabled.c:21
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: [options]\n"
|
||||
" options:\n"
|
||||
" -x | --exclusive Shared interfaces must be available\n"
|
||||
" -q | --quiet Don't print out any messages\n"
|
||||
" -h | --help Print help\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:37
|
||||
#, c-format
|
||||
msgid "No - not available on this system.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:41
|
||||
#, c-format
|
||||
msgid "No - disabled at boot.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:45
|
||||
#, c-format
|
||||
msgid "Maybe - policy interface not available.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:50
|
||||
#, c-format
|
||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:54
|
||||
#, c-format
|
||||
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:52-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:52-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 ""
|
@@ -412,7 +412,7 @@ register_hooks(unused_ apr_pool_t *p)
|
||||
|
||||
module AP_MODULE_DECLARE_DATA apparmor_module = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
aa_create_dir_config, /* dir config creater */
|
||||
aa_create_dir_config, /* dir config creator */
|
||||
NULL, /* dir merger --- default is to override */
|
||||
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
|
||||
aa_create_srv_config, /* server config */
|
||||
|
@@ -66,8 +66,8 @@ under src/jni_src.
|
||||
cp dist/libJNIChangeHat.so /usr/lib
|
||||
|
||||
[Note: you must ensure that the target directory is passed to tomcat via the
|
||||
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
|
||||
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
|
||||
java.library.path property. This can be accomplished by setting the JAVA_OPTS
|
||||
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
|
||||
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
|
||||
find this library at startup]
|
||||
|
||||
@@ -108,13 +108,13 @@ under src/jni_src.
|
||||
Once the installation steps above have been started you are ready to begin
|
||||
creating a profile for your application. The profile creation tool genprof will
|
||||
guide you through generating a profile and its support for change_hat will
|
||||
prompt you create discrete hats as requested byt the changeHatValve during
|
||||
prompt you create discrete hats as requested by the changeHatValve during
|
||||
tomcat execution.
|
||||
|
||||
1. Create a basic profile for the tomcat server.
|
||||
|
||||
- Run the command "genprof PATH_TO_CATALINA.SH"
|
||||
- In a seperate window start tomcat and then stop tomcat
|
||||
- In a separate window start tomcat and then stop tomcat
|
||||
- In the genprof window press "S" to scan for events
|
||||
- Answer the questions about the initial profile for tomcat
|
||||
|
||||
@@ -124,7 +124,7 @@ tomcat execution.
|
||||
- Stop the tomcat server
|
||||
- Deploy your WAR file or equivalent files under the container.
|
||||
- execute "genprof PATH_TO_CATALINA.SH"
|
||||
- In a seperate window start tomcat and then exercise your web application
|
||||
- In a separate window start tomcat and then exercise your web application
|
||||
- In the genprof window press "S" to scan for events
|
||||
During the prompting you will be asked questions similar to:
|
||||
|
||||
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
|
||||
context).
|
||||
If you choose to use the default hat: genprof will mediate all resource
|
||||
requests in the default hat for the duration of processing this request.
|
||||
When the request processng is complete the valve will change_hat back to the
|
||||
When the request processing is complete the valve will change_hat back to the
|
||||
parent context.
|
||||
|
||||
|
||||
|
@@ -66,8 +66,8 @@ under src/jni_src.
|
||||
cp dist/libJNIChangeHat.so /usr/lib
|
||||
|
||||
[Note: you must ensure that the target directory is passed to tomcat via the
|
||||
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
|
||||
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
|
||||
java.library.path property. This can be accomplished by setting the JAVA_OPTS
|
||||
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
|
||||
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
|
||||
find this library at startup]
|
||||
|
||||
@@ -108,13 +108,13 @@ under src/jni_src.
|
||||
Once the installation steps above have been started you are ready to begin
|
||||
creating a profile for your application. The profile creation tool genprof will
|
||||
guide you through generating a profile and its support for change_hat will
|
||||
prompt you create discrete hats as requested byt the changeHatValve during
|
||||
prompt you create discrete hats as requested by the changeHatValve during
|
||||
tomcat execution.
|
||||
|
||||
1. Create a basic profile for the tomcat server.
|
||||
|
||||
- Run the command "genprof PATH_TO_CATALINA.SH"
|
||||
- In a seperate window start tomcat and then stop tomcat
|
||||
- In a separate window start tomcat and then stop tomcat
|
||||
- In the genprof window press "S" to scan for events
|
||||
- Answer the questions about the initial profile for tomcat
|
||||
|
||||
@@ -124,7 +124,7 @@ tomcat execution.
|
||||
- Stop the tomcat server
|
||||
- Deploy your WAR file or equivalent files under the container.
|
||||
- execute "genprof PATH_TO_CATALINA.SH"
|
||||
- In a seperate window start tomcat and then exercise your web application
|
||||
- In a separate window start tomcat and then exercise your web application
|
||||
- In the genprof window press "S" to scan for events
|
||||
During the prompting you will be asked questions similar to:
|
||||
|
||||
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
|
||||
context).
|
||||
If you choose to use the default hat: genprof will mediate all resource
|
||||
requests in the default hat for the duration of processing this request.
|
||||
When the request processng is complete the valve will change_hat back to the
|
||||
When the request processing is complete the valve will change_hat back to the
|
||||
parent context.
|
||||
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
# the source tree
|
||||
# =====================
|
||||
|
||||
# It doesn't make sence for AppArmor to mediate PF_UNIX, filter it out. Search
|
||||
# It doesn't make sense for AppArmor to mediate PF_UNIX, filter it out. Search
|
||||
# for "PF_" constants since that is what is required in bits/socket.h, but
|
||||
# rewrite as "AF_".
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -125,7 +125,7 @@ layer. Binary policy cache files will be located in the directory
|
||||
returned by this function.
|
||||
|
||||
The aa_policy_cache_dir_levels() function provides access to the number
|
||||
of directories that are being overlayed to create the policy cache.
|
||||
of directories that are being overlaid to create the policy cache.
|
||||
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
@@ -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_CURRENT = 9
|
||||
AA_LIB_REVISION = 0
|
||||
AA_LIB_AGE = 7
|
||||
AA_LIB_AGE = 8
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
|
||||
|
@@ -373,7 +373,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
| TOK_KEY_CAPABILITY TOK_EQUALS TOK_DIGITS
|
||||
{ /* need to reverse map number to string, need to figure out
|
||||
* how to get auto generation of reverse mapping table into
|
||||
* autotools Makefile. For now just drop assumming capname is
|
||||
* autotools Makefile. For now just drop assuming capname is
|
||||
* present which it should be with current kernels */
|
||||
}
|
||||
| TOK_KEY_CAPNAME TOK_EQUALS TOK_QUOTED_STRING
|
||||
@@ -381,7 +381,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
ret_record->name = $3;
|
||||
}
|
||||
| TOK_KEY_OFFSET TOK_EQUALS TOK_DIGITS
|
||||
{ /* offset is used for reporting where an error occured unpacking
|
||||
{ /* offset is used for reporting where an error occurred unpacking
|
||||
* loaded policy. We can just drop this currently
|
||||
*/
|
||||
}
|
||||
|
@@ -227,9 +227,10 @@ 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_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;
|
||||
|
||||
static void proc_attr_base_init_once(void)
|
||||
{
|
||||
@@ -238,17 +239,21 @@ static void proc_attr_base_init_once(void)
|
||||
/* 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 (fd != -1) {
|
||||
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_attr_base = proc_attr_base_unavailable;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* else default to pre-assigned value */
|
||||
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_attr_base = proc_attr_base_unavailable;
|
||||
return;
|
||||
}
|
||||
proc_attr_base = proc_attr_base_old;
|
||||
}
|
||||
|
||||
static char *procattr_path(pid_t pid, const char *attr)
|
||||
@@ -262,6 +267,38 @@ static char *procattr_path(pid_t pid, const char *attr)
|
||||
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 a different interface this is ugly.
|
||||
* If only the old interface is available:
|
||||
* 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 && errno == EACCES && proc_attr_base != proc_attr_base_old && is_enabled()) {
|
||||
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 +408,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 +519,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 +546,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;
|
||||
}
|
||||
|
||||
@@ -1101,9 +1125,9 @@ int aa_query_link_path_len(const char *label, size_t label_len,
|
||||
query[pos] = 0;
|
||||
query[++pos] = AA_CLASS_FILE;
|
||||
memcpy(query + pos + 1, link, link_len);
|
||||
/* The kernel does the query in two parts we could similate this
|
||||
/* The kernel does the query in two parts; we could simulate this
|
||||
* doing the following, however as long as policy is compiled
|
||||
* correctly this isn't requied, and it requires and extra round
|
||||
* correctly this isn't required, and it requires an extra round
|
||||
* trip to the kernel and adds a race on policy replacement between
|
||||
* the two queries.
|
||||
*
|
||||
|
@@ -90,7 +90,7 @@ static int write_buffer(int fd, const char *buffer, int size)
|
||||
|
||||
/**
|
||||
* write_policy_buffer - load compiled policy into the kernel
|
||||
* @fd: kernel iterface to write to
|
||||
* @fd: kernel interface to write to
|
||||
* @atomic: whether to load all policy in buffer atomically (true)
|
||||
* @buffer: buffer of policy to load
|
||||
* @size: the size of the data in the buffer
|
||||
@@ -205,7 +205,7 @@ static int write_policy_file_to_iface(aa_kernel_interface *kernel_interface,
|
||||
* @apparmorfs: path to the apparmor directory of the mounted securityfs (can
|
||||
* be NULL and the path will be auto discovered)
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errnot set and *@kernel_interface
|
||||
* Returns: 0 on success, -1 on error with errno set and *@kernel_interface
|
||||
* pointing to NULL
|
||||
*/
|
||||
int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
|
@@ -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;
|
||||
|
@@ -63,7 +63,7 @@ struct ignored_suffix_t {
|
||||
};
|
||||
|
||||
static struct ignored_suffix_t ignored_suffixes[] = {
|
||||
/* Debian packging files, which are in flux during install
|
||||
/* Debian packaging files, which are in flux during install
|
||||
should be silently ignored. */
|
||||
{ ".dpkg-new", 9, 1 },
|
||||
{ ".dpkg-old", 9, 1 },
|
||||
@@ -147,7 +147,7 @@ int _aa_is_blacklisted(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* automaticly free allocated variables tagged with autofree on fn exit */
|
||||
/* automatically free allocated variables tagged with autofree on fn exit */
|
||||
void _aa_autofree(void *p)
|
||||
{
|
||||
void **_p = (void**)p;
|
||||
@@ -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)"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Runs all tests with the extention "multi" for several times.
|
||||
# Each testprogram <programname>.multi has an own subdirectory
|
||||
# Runs all tests with the extension "multi" for several times.
|
||||
# Each test program <programname>.multi has its own subdirectory
|
||||
# <programmname> in which several testcases are defined for this program
|
||||
# Each testcase has 3 files:
|
||||
#
|
||||
|
@@ -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}
|
||||
|
@@ -37,7 +37,7 @@ static struct supported_cond supported_conds[] = {
|
||||
{ "type", true, false, false, local_cond },
|
||||
{ "protocol", false, false, false, local_cond },
|
||||
{ "label", true, false, false, peer_cond },
|
||||
{ NULL, false, false, false, local_cond }, /* eol sentinal */
|
||||
{ NULL, false, false, false, local_cond }, /* eol sentinel */
|
||||
};
|
||||
|
||||
bool af_rule::cond_check(struct supported_cond *conds, struct cond_entry *ent,
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include "profile.h"
|
||||
#include "af_unix.h"
|
||||
|
||||
/* See unix(7) for autobind address definiation */
|
||||
/* See unix(7) for autobind address definition */
|
||||
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
|
||||
|
||||
int parse_unix_mode(const char *str_mode, int *mode, int fail)
|
||||
@@ -40,7 +40,7 @@ int parse_unix_mode(const char *str_mode, int *mode, int fail)
|
||||
|
||||
static struct supported_cond supported_conds[] = {
|
||||
{ "addr", true, false, false, either_cond },
|
||||
{ NULL, false, false, false, local_cond }, /* sentinal */
|
||||
{ NULL, false, false, false, local_cond }, /* sentinel */
|
||||
};
|
||||
|
||||
void unix_rule::move_conditionals(struct cond_entry *conds)
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,8 +326,9 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||
rule_t::warn_once(prof.name, "downgrading extended network unix socket rule to generic network rule\n");
|
||||
/* TODO: add ability to abort instead of downgrade */
|
||||
return RULE_OK;
|
||||
} else {
|
||||
warn_once(prof.name);
|
||||
}
|
||||
warn_once(prof.name);
|
||||
return RULE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -351,7 +356,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||
/* local label option */
|
||||
if (!write_label(tmp, label))
|
||||
goto fail;
|
||||
/* seperator */
|
||||
/* separator */
|
||||
tmp << "\\x00";
|
||||
|
||||
buf = tmp.str();
|
||||
@@ -372,7 +377,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||
/* local label option */
|
||||
if (!write_label(buffer, label))
|
||||
goto fail;
|
||||
/* seperator */
|
||||
/* separator */
|
||||
buffer << "\\x00";
|
||||
|
||||
/* create already masked off */
|
||||
|
@@ -241,9 +241,6 @@ B<DBUS ACCESS LIST> = Comma separated list of I<DBUS ACCESS>
|
||||
B<DBUS ACCESS> = ( 'send' | 'receive' | 'bind' | 'eavesdrop' | 'r' | 'read' | 'w' | 'write' | 'rw' )
|
||||
Some accesses are incompatible with some rules; see below.
|
||||
|
||||
B<AARE> = B<?*[]{}^>
|
||||
See below for meanings.
|
||||
|
||||
B<UNIX RULE> = [ I<QUALIFIERS> ] 'unix' [ I<UNIX ACCESS EXPR> ] [ I<UNIX RULE CONDS> ] [ I<UNIX LOCAL EXPR> ] [ I<UNIX PEER EXPR> ]
|
||||
|
||||
B<UNIX ACCESS EXPR> = ( I<UNIX ACCESS> | I<UNIX ACCESS LIST> )
|
||||
@@ -300,6 +297,9 @@ B<QUOTED FILEGLOB> = '"' I<UNQUOTED FILEGLOB> '"'
|
||||
|
||||
B<UNQUOTED FILEGLOB> = (must start with '/' (after variable expansion), B<AARE> have special meanings; see below. May include I<VARIABLE>. Rules with embedded spaces or tabs must be quoted. Rules must end with '/' to apply to directories.)
|
||||
|
||||
B<AARE> = B<?*[]{}^>
|
||||
See section "Globbing (AARE)" below for meanings.
|
||||
|
||||
B<ACCESS> = ( 'r' | 'w' | 'a' | 'l' | 'k' | 'm' | I<EXEC TRANSITION> )+ (not all combinations are allowed; see below.)
|
||||
|
||||
B<EXEC TRANSITION> = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' | 'Pix' | 'cix' | 'Cix' | 'pux' | 'PUx' | 'cux' | 'CUx' | 'x' )
|
||||
@@ -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
|
||||
@@ -1513,9 +1513,10 @@ F</etc/apparmor.d/tunables/alias>, which is included by
|
||||
F</etc/apparmor.d/tunables/global>. F</etc/apparmor.d/tunables/global> is
|
||||
typically included at the beginning of an AppArmor profile.
|
||||
|
||||
=head2 Globbing
|
||||
=head2 Globbing (AARE)
|
||||
|
||||
File resources may be specified with a globbing syntax similar to that
|
||||
File resources and other parameters accepting an AARE
|
||||
may be specified with a globbing syntax similar to that
|
||||
used by popular shells, such as csh(1), bash(1), zsh(1).
|
||||
|
||||
=over 4
|
||||
@@ -1548,6 +1549,12 @@ will substitute for any single character not matching a, b or c
|
||||
|
||||
will expand to one rule to match ab, one rule to match cd
|
||||
|
||||
Can also include variables.
|
||||
|
||||
=item B<@{variable}>
|
||||
|
||||
will expand to all values assigned to the given variable.
|
||||
|
||||
=back
|
||||
|
||||
When AppArmor looks up a directory the pathname being looked up will
|
||||
@@ -1752,7 +1759,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
|
||||
|
@@ -98,6 +98,62 @@ cannot call the following system calls:
|
||||
iopl(2) ptrace(2) reboot(2) setdomainname(2)
|
||||
sethostname(2) swapoff(2) swapon(2) sysctl(2)
|
||||
|
||||
=head2 Complain mode
|
||||
|
||||
Instead of denying access to resources the profile does not have a rule for
|
||||
AppArmor can "allow" the access and log a message for the operation
|
||||
that triggers it. This is called I<complain mode>. It is important to
|
||||
note that rules that are present in the profile are still applied, so
|
||||
allow rules will still quiet or force audit messages, and deny rules
|
||||
will still result in denials and quieting of denial messages (see
|
||||
I<Turn off deny audit quieting> if this is a problem).
|
||||
|
||||
Complain mode can be used to develop profiles incrementally as an
|
||||
application is exercised. The logged accesses can be added to the
|
||||
profile and then can the application further excercised to discover further
|
||||
additions that are needed. Because AppArmor allows the accesses the
|
||||
application will behave as it would if AppArmor was not confining it.
|
||||
|
||||
B<Warning> complain mode does not provide any security, only
|
||||
auditing, while it is enabled. It should not be used in a hostile
|
||||
environment or bad behaviors may be logged and added to the profile
|
||||
as if they are resource accesses that should be used by the
|
||||
application.
|
||||
|
||||
B<Note> complain mode can be very noisy with new or empty profiles,
|
||||
but with developed profiles might not log anything if the profile
|
||||
covers the application behavior well. See I<Audit Rate Limiting> if
|
||||
complain mode is generating too many log messages.
|
||||
|
||||
To set a profile and any children or hat profiles the profile may contain
|
||||
into complain mode use
|
||||
|
||||
aa-complain /etc/apparmor.d/<the-application>
|
||||
|
||||
To manually set a specific profile in complain mode, add the
|
||||
C<complain> flag, and then manually reload the profile:
|
||||
|
||||
profile foo flags=(complain) { ... }
|
||||
|
||||
Note that the C<complain> flag must also be added manually to any
|
||||
hats or children profiles of the profile or they will continue to
|
||||
use the previous mode.
|
||||
|
||||
To enable complain mode globally, run:
|
||||
|
||||
echo -n complain > /sys/module/apparmor/parameters/mode
|
||||
|
||||
or to set it on boot add:
|
||||
|
||||
apparmor.mode=complain
|
||||
|
||||
as a kernel boot paramenter.
|
||||
|
||||
B<Warning> Setting complain mode gloabally disables all apparmor
|
||||
security protections. It can be useful during debugging or profile
|
||||
development, but setting it selectively on a per profile basis is
|
||||
safer.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
When a confined process tries to access a file it does not have permission
|
||||
@@ -158,6 +214,12 @@ To enable debug mode, run:
|
||||
|
||||
echo 1 > /sys/module/apparmor/parameters/debug
|
||||
|
||||
or to set it on boot add:
|
||||
|
||||
apparmor.debug=1
|
||||
|
||||
as a kernel boot paramenter.
|
||||
|
||||
=head2 Turn off deny audit quieting
|
||||
|
||||
By default, operations that trigger C<deny> rules are not logged.
|
||||
@@ -167,6 +229,12 @@ To turn off deny audit quieting, run:
|
||||
|
||||
echo -n noquiet >/sys/module/apparmor/parameters/audit
|
||||
|
||||
or to set it on boot add:
|
||||
|
||||
apparmor.audit=noquiet
|
||||
|
||||
as a kernel boot paramenter.
|
||||
|
||||
=head2 Force audit mode
|
||||
|
||||
AppArmor can log a message for every operation that triggers a rule
|
||||
@@ -183,6 +251,14 @@ To enable force audit mode globally, run:
|
||||
|
||||
echo -n all > /sys/module/apparmor/parameters/audit
|
||||
|
||||
or to set it on boot add:
|
||||
|
||||
apparmor.audit=all
|
||||
|
||||
as a kernel boot paramenter.
|
||||
|
||||
B<Audit Rate Limiting>
|
||||
|
||||
If auditd is not running, to avoid losing too many of the extra log
|
||||
messages, you will likely have to turn off rate limiting by doing:
|
||||
|
||||
|
@@ -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
|
||||
@@ -393,6 +396,23 @@ This option tells the parser to not attempt to rebuild the cache on
|
||||
failure, instead the parser continues on with processing the remaining
|
||||
profiles.
|
||||
|
||||
=item --estimated-compile-size
|
||||
Adjust the internal parameter used to estimate how agressive the parser
|
||||
can be when compiling policy. This may include changes to how or when
|
||||
caches are dropped or how many compile units (jobs) are launched. The
|
||||
value should slightly larger than the largest Resident Set Size (RSS)
|
||||
encountered for the type of policy being compiled.
|
||||
|
||||
A value that is too small may result in the parser exhausting system
|
||||
resources when compiling large policy. A value too large may slow
|
||||
policy compiles down.
|
||||
|
||||
The value specified may include a suffix of I<KB>, I<MB>, I<GB>, to
|
||||
make it easier to adjust the size.
|
||||
|
||||
Note: config-file and command line options will override values chosen
|
||||
by tuning affected by the option.
|
||||
|
||||
=item --config-file
|
||||
|
||||
Specify the config file to use instead of
|
||||
|
@@ -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,
|
||||
|
@@ -8,7 +8,7 @@ chfa.{h,cc} - code to build a highly compressed runtime readonly version
|
||||
of an hfa.
|
||||
aare_rules.{h,cc} - code to that binds parse -> expr-tree -> hfa generation
|
||||
-> chfa generation into a basic interface for converting
|
||||
rules to a runtime ready statemachine.
|
||||
rules to a runtime ready state machine.
|
||||
|
||||
Regular Expression Scanner Generator
|
||||
====================================
|
||||
@@ -19,12 +19,12 @@ Notes in the scanner File Format
|
||||
The file format used is based on the GNU flex table file format
|
||||
(--tables-file option; see Table File Format in the flex info pages and
|
||||
the flex sources for documentation). The magic number used in the header
|
||||
is set to 0x1B5E783D insted of 0xF13C57B1 though, which is meant to
|
||||
is set to 0x1B5E783D instead of 0xF13C57B1 though, which is meant to
|
||||
indicate that the file format logically is not the same: the YY_ID_CHK
|
||||
(check) and YY_ID_DEF (default) tables are used differently.
|
||||
|
||||
Flex uses state compression to store only the differences between states
|
||||
for states that are similar. The amount of compresion influences the parse
|
||||
for states that are similar. The amount of compression influences the parse
|
||||
speed.
|
||||
|
||||
The following two states could be stored as in the tables outlined
|
||||
|
@@ -61,12 +61,12 @@ void aare_rules::add_to_rules(Node *tree, Node *perms)
|
||||
expr_map[perms] = tree;
|
||||
}
|
||||
|
||||
static Node *cat_with_null_seperator(Node *l, Node *r)
|
||||
static Node *cat_with_null_separator(Node *l, Node *r)
|
||||
{
|
||||
return new CatNode(new CatNode(l, new CharNode(0)), r);
|
||||
}
|
||||
|
||||
static Node *cat_with_oob_seperator(Node *l, Node *r)
|
||||
static Node *cat_with_oob_separator(Node *l, Node *r)
|
||||
{
|
||||
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
|
||||
}
|
||||
@@ -85,9 +85,9 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
||||
if (regex_parse(&subtree, rulev[i]))
|
||||
goto err;
|
||||
if (oob)
|
||||
tree = cat_with_oob_seperator(tree, subtree);
|
||||
tree = cat_with_oob_separator(tree, subtree);
|
||||
else
|
||||
tree = cat_with_null_seperator(tree, subtree);
|
||||
tree = cat_with_null_separator(tree, subtree);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -97,11 +97,11 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
||||
*/
|
||||
exact_match = 1;
|
||||
for (depth_first_traversal i(tree); i && exact_match; i++) {
|
||||
if (dynamic_cast<StarNode *>(*i) ||
|
||||
dynamic_cast<PlusNode *>(*i) ||
|
||||
dynamic_cast<AnyCharNode *>(*i) ||
|
||||
dynamic_cast<CharSetNode *>(*i) ||
|
||||
dynamic_cast<NotCharSetNode *>(*i))
|
||||
if ((*i)->is_type(NODE_TYPE_STAR) ||
|
||||
(*i)->is_type(NODE_TYPE_PLUS) ||
|
||||
(*i)->is_type(NODE_TYPE_ANYCHAR) ||
|
||||
(*i)->is_type(NODE_TYPE_CHARSET) ||
|
||||
(*i)->is_type(NODE_TYPE_NOTCHARSET))
|
||||
exact_match = 0;
|
||||
}
|
||||
|
||||
@@ -111,15 +111,15 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
||||
accept = unique_perms.insert(deny, perms, audit, exact_match);
|
||||
|
||||
if (flags & DFA_DUMP_RULE_EXPR) {
|
||||
const char *seperator;
|
||||
const char *separator;
|
||||
if (oob)
|
||||
seperator = "\\-x01";
|
||||
separator = "\\-x01";
|
||||
else
|
||||
seperator = "\\x00";
|
||||
separator = "\\x00";
|
||||
cerr << "rule: ";
|
||||
cerr << rulev[0];
|
||||
for (int i = 1; i < count; i++) {
|
||||
cerr << seperator;
|
||||
cerr << separator;
|
||||
cerr << rulev[i];
|
||||
}
|
||||
cerr << " -> ";
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* it can be factored so that the set of important nodes is smaller.
|
||||
* Having a reduced set of important nodes generally results in a dfa that
|
||||
* is closer to minimum (fewer redundant states are created). It also
|
||||
* results in fewer important nodes in a the state set during subset
|
||||
* results in fewer important nodes in the state set during subset
|
||||
* construction resulting in less memory used to create a dfa.
|
||||
*
|
||||
* Generally it is worth doing expression tree simplification before dfa
|
||||
@@ -150,7 +150,7 @@ void Node::dump_syntax_tree(ostream &os)
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize the regex parse tree for factoring and cancelations. Normalization
|
||||
* Normalize the regex parse tree for factoring and cancellations. Normalization
|
||||
* reorganizes internal (alt and cat) nodes into a fixed "normalized" form that
|
||||
* simplifies factoring code, in that it produces a canonicalized form for
|
||||
* the direction being normalized so that the factoring code does not have
|
||||
@@ -172,10 +172,10 @@ void Node::dump_syntax_tree(ostream &os)
|
||||
* dir to !dir. Until no dir direction node meets the criterial.
|
||||
* Then recurse to the children (which will have a different node type)
|
||||
* to make sure they are normalized.
|
||||
* Normalization of a child node is guarenteed to not affect the
|
||||
* Normalization of a child node is guaranteed to not affect the
|
||||
* normalization of the parent.
|
||||
*
|
||||
* For cat nodes the depth first traverse order is guarenteed to be
|
||||
* For cat nodes the depth first traverse order is guaranteed to be
|
||||
* maintained. This is not necessary for altnodes.
|
||||
*
|
||||
* Eg. For left normalization
|
||||
@@ -210,7 +210,7 @@ int TwoChildNode::normalize_eps(int dir)
|
||||
// Test for E | (E | E) and E . (E . E) which will
|
||||
// result in an infinite loop
|
||||
Node *c = child[!dir];
|
||||
if (dynamic_cast<TwoChildNode *>(c) &&
|
||||
if (c->is_type(NODE_TYPE_TWOCHILD) &&
|
||||
&epsnode == c->child[dir] &&
|
||||
&epsnode == c->child[!dir]) {
|
||||
c->release();
|
||||
@@ -229,7 +229,7 @@ void CatNode::normalize(int dir)
|
||||
for (;;) {
|
||||
if (normalize_eps(dir)) {
|
||||
continue;
|
||||
} else if (dynamic_cast<CatNode *>(child[dir])) {
|
||||
} else if (child[dir]->is_type(NODE_TYPE_CAT)) {
|
||||
// (ab)c -> a(bc)
|
||||
rotate_node(this, dir);
|
||||
} else {
|
||||
@@ -248,11 +248,11 @@ void AltNode::normalize(int dir)
|
||||
for (;;) {
|
||||
if (normalize_eps(dir)) {
|
||||
continue;
|
||||
} else if (dynamic_cast<AltNode *>(child[dir])) {
|
||||
} else if (child[dir]->is_type(NODE_TYPE_ALT)) {
|
||||
// (a | b) | c -> a | (b | c)
|
||||
rotate_node(this, dir);
|
||||
} else if (dynamic_cast<CharSetNode *>(child[dir]) &&
|
||||
dynamic_cast<CharNode *>(child[!dir])) {
|
||||
} else if (child[dir]->is_type(NODE_TYPE_CHARSET) &&
|
||||
child[!dir]->is_type(NODE_TYPE_CHAR)) {
|
||||
// [a] | b -> b | [a]
|
||||
Node *c = child[dir];
|
||||
child[dir] = child[!dir];
|
||||
@@ -344,7 +344,7 @@ static Node *alt_to_charsets(Node *t, int dir)
|
||||
|
||||
static Node *basic_alt_factor(Node *t, int dir)
|
||||
{
|
||||
if (!dynamic_cast<AltNode *>(t))
|
||||
if (!t->is_type(NODE_TYPE_ALT))
|
||||
return t;
|
||||
|
||||
if (t->child[dir]->eq(t->child[!dir])) {
|
||||
@@ -355,8 +355,8 @@ static Node *basic_alt_factor(Node *t, int dir)
|
||||
return tmp;
|
||||
}
|
||||
// (ab) | (ac) -> a(b|c)
|
||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
||||
dynamic_cast<CatNode *>(t->child[!dir]) &&
|
||||
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||
t->child[dir]->child[dir]->eq(t->child[!dir]->child[dir])) {
|
||||
// (ab) | (ac) -> a(b|c)
|
||||
Node *left = t->child[dir];
|
||||
@@ -369,7 +369,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
||||
return left;
|
||||
}
|
||||
// a | (ab) -> a (E | b) -> a (b | E)
|
||||
if (dynamic_cast<CatNode *>(t->child[!dir]) &&
|
||||
if (t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||
t->child[dir]->eq(t->child[!dir]->child[dir])) {
|
||||
Node *c = t->child[!dir];
|
||||
t->child[dir]->release();
|
||||
@@ -379,7 +379,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
||||
return c;
|
||||
}
|
||||
// ab | (a) -> a (b | E)
|
||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
||||
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
t->child[dir]->child[dir]->eq(t->child[!dir])) {
|
||||
Node *c = t->child[dir];
|
||||
t->child[!dir]->release();
|
||||
@@ -394,7 +394,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
||||
|
||||
static Node *basic_simplify(Node *t, int dir)
|
||||
{
|
||||
if (dynamic_cast<CatNode *>(t) && &epsnode == t->child[!dir]) {
|
||||
if (t->is_type(NODE_TYPE_CAT) && &epsnode == t->child[!dir]) {
|
||||
// aE -> a
|
||||
Node *tmp = t->child[dir];
|
||||
t->child[dir] = NULL;
|
||||
@@ -419,7 +419,7 @@ static Node *basic_simplify(Node *t, int dir)
|
||||
*/
|
||||
Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||
{
|
||||
if (dynamic_cast<ImportantNode *>(t))
|
||||
if (t->is_type(NODE_TYPE_IMPORTANT))
|
||||
return t;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@@ -442,15 +442,15 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||
}
|
||||
|
||||
/* all tests after this must meet 2 alt node condition */
|
||||
if (!dynamic_cast<AltNode *>(t) ||
|
||||
!dynamic_cast<AltNode *>(t->child[!dir]))
|
||||
if (!t->is_type(NODE_TYPE_ALT) ||
|
||||
!t->child[!dir]->is_type(NODE_TYPE_ALT))
|
||||
break;
|
||||
|
||||
// a | (a | b) -> (a | b)
|
||||
// a | (b | (c | a)) -> (b | (c | a))
|
||||
Node *p = t;
|
||||
Node *i = t->child[!dir];
|
||||
for (; dynamic_cast<AltNode *>(i); p = i, i = i->child[!dir]) {
|
||||
for (; i->is_type(NODE_TYPE_ALT); p = i, i = i->child[!dir]) {
|
||||
if (t->child[dir]->eq(i->child[dir])) {
|
||||
Node *tmp = t->child[!dir];
|
||||
t->child[!dir] = NULL;
|
||||
@@ -475,19 +475,19 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||
int count = 0;
|
||||
Node *subject = t->child[dir];
|
||||
Node *a = subject;
|
||||
if (dynamic_cast<CatNode *>(subject))
|
||||
if (subject->is_type(NODE_TYPE_CAT))
|
||||
a = subject->child[dir];
|
||||
|
||||
for (pp = p = t, i = t->child[!dir];
|
||||
dynamic_cast<AltNode *>(i);) {
|
||||
if ((dynamic_cast<CatNode *>(i->child[dir]) &&
|
||||
i->is_type(NODE_TYPE_ALT);) {
|
||||
if ((i->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
a->eq(i->child[dir]->child[dir])) ||
|
||||
(a->eq(i->child[dir]))) {
|
||||
// extract matching alt node
|
||||
p->child[!dir] = i->child[!dir];
|
||||
i->child[!dir] = subject;
|
||||
subject = basic_simplify(i, dir);
|
||||
if (dynamic_cast<CatNode *>(subject))
|
||||
if (subject->is_type(NODE_TYPE_CAT))
|
||||
a = subject->child[dir];
|
||||
else
|
||||
a = subject;
|
||||
@@ -502,7 +502,7 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||
}
|
||||
|
||||
// last altnode in chain check other dir as well
|
||||
if ((dynamic_cast<CatNode *>(i) &&
|
||||
if ((i->is_type(NODE_TYPE_CAT) &&
|
||||
a->eq(i->child[dir])) || (a->eq(i))) {
|
||||
count++;
|
||||
if (t == p) {
|
||||
@@ -528,7 +528,7 @@ int debug_tree(Node *t)
|
||||
{
|
||||
int nodes = 1;
|
||||
|
||||
if (!dynamic_cast<ImportantNode *>(t)) {
|
||||
if (!t->is_type(NODE_TYPE_IMPORTANT)) {
|
||||
if (t->child[0])
|
||||
nodes += debug_tree(t->child[0]);
|
||||
if (t->child[1])
|
||||
@@ -539,30 +539,30 @@ int debug_tree(Node *t)
|
||||
|
||||
static void count_tree_nodes(Node *t, struct node_counts *counts)
|
||||
{
|
||||
if (dynamic_cast<AltNode *>(t)) {
|
||||
if (t->is_type(NODE_TYPE_ALT)) {
|
||||
counts->alt++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
count_tree_nodes(t->child[1], counts);
|
||||
} else if (dynamic_cast<CatNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_CAT)) {
|
||||
counts->cat++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
count_tree_nodes(t->child[1], counts);
|
||||
} else if (dynamic_cast<PlusNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_PLUS)) {
|
||||
counts->plus++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (dynamic_cast<StarNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_STAR)) {
|
||||
counts->star++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (dynamic_cast<OptionalNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_OPTIONAL)) {
|
||||
counts->optional++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (dynamic_cast<CharNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_CHAR)) {
|
||||
counts->charnode++;
|
||||
} else if (dynamic_cast<AnyCharNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_ANYCHAR)) {
|
||||
counts->any++;
|
||||
} else if (dynamic_cast<CharSetNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_CHARSET)) {
|
||||
counts->charset++;
|
||||
} else if (dynamic_cast<NotCharSetNode *>(t)) {
|
||||
} else if (t->is_type(NODE_TYPE_NOTCHARSET)) {
|
||||
counts->notcharset++;
|
||||
}
|
||||
}
|
||||
@@ -635,7 +635,8 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
||||
void flip_tree(Node *node)
|
||||
{
|
||||
for (depth_first_traversal i(node); i; i++) {
|
||||
if (CatNode *cat = dynamic_cast<CatNode *>(*i)) {
|
||||
if ((*i)->is_type(NODE_TYPE_CAT)) {
|
||||
CatNode *cat = static_cast<CatNode *>(*i);
|
||||
swap(cat->child[0], cat->child[1]);
|
||||
}
|
||||
}
|
||||
|
@@ -222,16 +222,43 @@ typedef struct Cases {
|
||||
|
||||
ostream &operator<<(ostream &os, Node &node);
|
||||
|
||||
#define NODE_TYPE_NODE 0
|
||||
#define NODE_TYPE_INNER (1 << 0)
|
||||
#define NODE_TYPE_ONECHILD (1 << 1)
|
||||
#define NODE_TYPE_TWOCHILD (1 << 2)
|
||||
#define NODE_TYPE_LEAF (1 << 3)
|
||||
#define NODE_TYPE_EPS (1 << 4)
|
||||
#define NODE_TYPE_IMPORTANT (1 << 5)
|
||||
#define NODE_TYPE_C (1 << 6)
|
||||
#define NODE_TYPE_CHAR (1 << 7)
|
||||
#define NODE_TYPE_CHARSET (1 << 8)
|
||||
#define NODE_TYPE_NOTCHARSET (1 << 9)
|
||||
#define NODE_TYPE_ANYCHAR (1 << 10)
|
||||
#define NODE_TYPE_STAR (1 << 11)
|
||||
#define NODE_TYPE_OPTIONAL (1 << 12)
|
||||
#define NODE_TYPE_PLUS (1 << 13)
|
||||
#define NODE_TYPE_CAT (1 << 14)
|
||||
#define NODE_TYPE_ALT (1 << 15)
|
||||
#define NODE_TYPE_SHARED (1 << 16)
|
||||
#define NODE_TYPE_ACCEPT (1 << 17)
|
||||
#define NODE_TYPE_MATCHFLAG (1 << 18)
|
||||
#define NODE_TYPE_EXACTMATCHFLAG (1 << 19)
|
||||
#define NODE_TYPE_DENYMATCHFLAG (1 << 20)
|
||||
|
||||
/* An abstract node in the syntax tree. */
|
||||
class Node {
|
||||
public:
|
||||
Node(): nullable(false), label(0) { child[0] = child[1] = 0; }
|
||||
Node(Node *left): nullable(false), label(0)
|
||||
Node(): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
|
||||
{
|
||||
child[0] = child[1] = 0;
|
||||
}
|
||||
Node(Node *left): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
|
||||
{
|
||||
child[0] = left;
|
||||
child[1] = 0;
|
||||
}
|
||||
Node(Node *left, Node *right): nullable(false), label(0)
|
||||
Node(Node *left, Node *right): nullable(false),
|
||||
type_flags(NODE_TYPE_NODE), label(0)
|
||||
{
|
||||
child[0] = left;
|
||||
child[1] = right;
|
||||
@@ -302,6 +329,13 @@ public:
|
||||
NodeSet firstpos, lastpos, followpos;
|
||||
/* child 0 is left, child 1 is right */
|
||||
Node *child[2];
|
||||
/*
|
||||
* Bitmap that stores supported pointer casts for the Node, composed
|
||||
* by the NODE_TYPE_* flags. This is used by is_type() as a substitute
|
||||
* of costly dynamic_cast calls.
|
||||
*/
|
||||
unsigned type_flags;
|
||||
bool is_type(unsigned type) { return type_flags & type; }
|
||||
|
||||
unsigned int label; /* unique number for debug etc */
|
||||
/**
|
||||
@@ -315,25 +349,34 @@ public:
|
||||
|
||||
class InnerNode: public Node {
|
||||
public:
|
||||
InnerNode(): Node() { };
|
||||
InnerNode(Node *left): Node(left) { };
|
||||
InnerNode(Node *left, Node *right): Node(left, right) { };
|
||||
InnerNode(): Node() { type_flags |= NODE_TYPE_INNER; };
|
||||
InnerNode(Node *left): Node(left) { type_flags |= NODE_TYPE_INNER; };
|
||||
InnerNode(Node *left, Node *right): Node(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_INNER;
|
||||
};
|
||||
};
|
||||
|
||||
class OneChildNode: public InnerNode {
|
||||
public:
|
||||
OneChildNode(Node *left): InnerNode(left) { };
|
||||
OneChildNode(Node *left): InnerNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_ONECHILD;
|
||||
};
|
||||
};
|
||||
|
||||
class TwoChildNode: public InnerNode {
|
||||
public:
|
||||
TwoChildNode(Node *left, Node *right): InnerNode(left, right) { };
|
||||
TwoChildNode(Node *left, Node *right): InnerNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_TWOCHILD;
|
||||
};
|
||||
virtual int normalize_eps(int dir);
|
||||
};
|
||||
|
||||
class LeafNode: public Node {
|
||||
public:
|
||||
LeafNode(): Node() { };
|
||||
LeafNode(): Node() { type_flags |= NODE_TYPE_LEAF; };
|
||||
virtual void normalize(int dir __attribute__((unused))) { return; }
|
||||
};
|
||||
|
||||
@@ -342,6 +385,7 @@ class EpsNode: public LeafNode {
|
||||
public:
|
||||
EpsNode(): LeafNode()
|
||||
{
|
||||
type_flags |= NODE_TYPE_EPS;
|
||||
nullable = true;
|
||||
label = 0;
|
||||
}
|
||||
@@ -356,7 +400,7 @@ public:
|
||||
void compute_lastpos() { }
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<EpsNode *>(other))
|
||||
if (other->is_type(NODE_TYPE_EPS))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -373,7 +417,7 @@ public:
|
||||
*/
|
||||
class ImportantNode: public LeafNode {
|
||||
public:
|
||||
ImportantNode(): LeafNode() { }
|
||||
ImportantNode(): LeafNode() { type_flags |= NODE_TYPE_IMPORTANT; }
|
||||
void compute_firstpos() { firstpos.insert(this); }
|
||||
void compute_lastpos() { lastpos.insert(this); }
|
||||
virtual void follow(Cases &cases) = 0;
|
||||
@@ -386,7 +430,7 @@ public:
|
||||
*/
|
||||
class CNode: public ImportantNode {
|
||||
public:
|
||||
CNode(): ImportantNode() { }
|
||||
CNode(): ImportantNode() { type_flags |= NODE_TYPE_C; }
|
||||
int is_accept(void) { return false; }
|
||||
int is_postprocess(void) { return false; }
|
||||
};
|
||||
@@ -394,7 +438,7 @@ public:
|
||||
/* Match one specific character (/c/). */
|
||||
class CharNode: public CNode {
|
||||
public:
|
||||
CharNode(transchar c): c(c) { }
|
||||
CharNode(transchar c): c(c) { type_flags |= NODE_TYPE_CHAR; }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
NodeSet **x = &cases.cases[c];
|
||||
@@ -408,8 +452,8 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
CharNode *o = dynamic_cast<CharNode *>(other);
|
||||
if (o) {
|
||||
if (other->is_type(NODE_TYPE_CHAR)) {
|
||||
CharNode *o = static_cast<CharNode *>(other);
|
||||
return c == o->c;
|
||||
}
|
||||
return 0;
|
||||
@@ -439,7 +483,10 @@ public:
|
||||
/* Match a set of characters (/[abc]/). */
|
||||
class CharSetNode: public CNode {
|
||||
public:
|
||||
CharSetNode(Chars &chars): chars(chars) { }
|
||||
CharSetNode(Chars &chars): chars(chars)
|
||||
{
|
||||
type_flags |= NODE_TYPE_CHARSET;
|
||||
}
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
|
||||
@@ -455,8 +502,11 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
CharSetNode *o = dynamic_cast<CharSetNode *>(other);
|
||||
if (!o || chars.size() != o->chars.size())
|
||||
if (!other->is_type(NODE_TYPE_CHARSET))
|
||||
return 0;
|
||||
|
||||
CharSetNode *o = static_cast<CharSetNode *>(other);
|
||||
if (chars.size() != o->chars.size())
|
||||
return 0;
|
||||
|
||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||
@@ -498,7 +548,10 @@ public:
|
||||
/* Match all except one character (/[^abc]/). */
|
||||
class NotCharSetNode: public CNode {
|
||||
public:
|
||||
NotCharSetNode(Chars &chars): chars(chars) { }
|
||||
NotCharSetNode(Chars &chars): chars(chars)
|
||||
{
|
||||
type_flags |= NODE_TYPE_NOTCHARSET;
|
||||
}
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
if (!cases.otherwise)
|
||||
@@ -522,8 +575,11 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
NotCharSetNode *o = dynamic_cast<NotCharSetNode *>(other);
|
||||
if (!o || chars.size() != o->chars.size())
|
||||
if (!other->is_type(NODE_TYPE_NOTCHARSET))
|
||||
return 0;
|
||||
|
||||
NotCharSetNode *o = static_cast<NotCharSetNode *>(other);
|
||||
if (chars.size() != o->chars.size())
|
||||
return 0;
|
||||
|
||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||
@@ -565,7 +621,7 @@ public:
|
||||
/* Match any character (/./). */
|
||||
class AnyCharNode: public CNode {
|
||||
public:
|
||||
AnyCharNode() { }
|
||||
AnyCharNode() { type_flags |= NODE_TYPE_ANYCHAR; }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
if (!cases.otherwise)
|
||||
@@ -579,7 +635,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<AnyCharNode *>(other))
|
||||
if (other->is_type(NODE_TYPE_ANYCHAR))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -589,7 +645,11 @@ public:
|
||||
/* Match a node zero or more times. (This is a unary operator.) */
|
||||
class StarNode: public OneChildNode {
|
||||
public:
|
||||
StarNode(Node *left): OneChildNode(left) { nullable = true; }
|
||||
StarNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_STAR;
|
||||
nullable = true;
|
||||
}
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||
void compute_followpos()
|
||||
@@ -601,7 +661,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<StarNode *>(other))
|
||||
if (other->is_type(NODE_TYPE_STAR))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -618,12 +678,16 @@ public:
|
||||
/* Match a node zero or one times. */
|
||||
class OptionalNode: public OneChildNode {
|
||||
public:
|
||||
OptionalNode(Node *left): OneChildNode(left) { nullable = true; }
|
||||
OptionalNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_OPTIONAL;
|
||||
nullable = true;
|
||||
}
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<OptionalNode *>(other))
|
||||
if (other->is_type(NODE_TYPE_OPTIONAL))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -638,7 +702,9 @@ public:
|
||||
/* Match a node one or more times. (This is a unary operator.) */
|
||||
class PlusNode: public OneChildNode {
|
||||
public:
|
||||
PlusNode(Node *left): OneChildNode(left) {
|
||||
PlusNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_PLUS;
|
||||
}
|
||||
void compute_nullable() { nullable = child[0]->nullable; }
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
@@ -651,7 +717,7 @@ public:
|
||||
}
|
||||
}
|
||||
int eq(Node *other) {
|
||||
if (dynamic_cast<PlusNode *>(other))
|
||||
if (other->is_type(NODE_TYPE_PLUS))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -667,7 +733,10 @@ public:
|
||||
/* Match a pair of consecutive nodes. */
|
||||
class CatNode: public TwoChildNode {
|
||||
public:
|
||||
CatNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
||||
CatNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_CAT;
|
||||
}
|
||||
void compute_nullable()
|
||||
{
|
||||
nullable = child[0]->nullable && child[1]->nullable;
|
||||
@@ -695,7 +764,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<CatNode *>(other)) {
|
||||
if (other->is_type(NODE_TYPE_CAT)) {
|
||||
if (!child[0]->eq(other->child[0]))
|
||||
return 0;
|
||||
return child[1]->eq(other->child[1]);
|
||||
@@ -730,7 +799,10 @@ public:
|
||||
/* Match one of two alternative nodes. */
|
||||
class AltNode: public TwoChildNode {
|
||||
public:
|
||||
AltNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
||||
AltNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_ALT;
|
||||
}
|
||||
void compute_nullable()
|
||||
{
|
||||
nullable = child[0]->nullable || child[1]->nullable;
|
||||
@@ -745,7 +817,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (dynamic_cast<AltNode *>(other)) {
|
||||
if (other->is_type(NODE_TYPE_ALT)) {
|
||||
if (!child[0]->eq(other->child[0]))
|
||||
return 0;
|
||||
return child[1]->eq(other->child[1]);
|
||||
@@ -780,7 +852,10 @@ public:
|
||||
|
||||
class SharedNode: public ImportantNode {
|
||||
public:
|
||||
SharedNode() { }
|
||||
SharedNode()
|
||||
{
|
||||
type_flags |= NODE_TYPE_SHARED;
|
||||
}
|
||||
void release(void)
|
||||
{
|
||||
/* don't delete SharedNodes via release as they are shared, and
|
||||
@@ -803,14 +878,17 @@ public:
|
||||
*/
|
||||
class AcceptNode: public SharedNode {
|
||||
public:
|
||||
AcceptNode() { }
|
||||
AcceptNode() { type_flags |= NODE_TYPE_ACCEPT; }
|
||||
int is_accept(void) { return true; }
|
||||
int is_postprocess(void) { return false; }
|
||||
};
|
||||
|
||||
class MatchFlag: public AcceptNode {
|
||||
public:
|
||||
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
|
||||
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit)
|
||||
{
|
||||
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||
}
|
||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << flag << '>'; }
|
||||
|
||||
uint32_t flag;
|
||||
@@ -819,12 +897,18 @@ public:
|
||||
|
||||
class ExactMatchFlag: public MatchFlag {
|
||||
public:
|
||||
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
|
||||
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit)
|
||||
{
|
||||
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
|
||||
}
|
||||
};
|
||||
|
||||
class DenyMatchFlag: public MatchFlag {
|
||||
public:
|
||||
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
|
||||
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet)
|
||||
{
|
||||
type_flags |= NODE_TYPE_DENYMATCHFLAG;
|
||||
}
|
||||
};
|
||||
|
||||
/* Traverse the syntax tree depth-first in an iterator-like manner. */
|
||||
@@ -833,7 +917,7 @@ class depth_first_traversal {
|
||||
void push_left(Node *node) {
|
||||
pos.push(node);
|
||||
|
||||
while (dynamic_cast<InnerNode *>(node)) {
|
||||
while (node->is_type(NODE_TYPE_INNER)) {
|
||||
pos.push(node->child[0]);
|
||||
node = node->child[0];
|
||||
}
|
||||
|
@@ -651,13 +651,13 @@ void DFA::minimize(dfaflags_t flags)
|
||||
list<Partition *> partitions;
|
||||
|
||||
/* Set up the initial partitions
|
||||
* minimium of - 1 non accepting, and 1 accepting
|
||||
* minimum of - 1 non accepting, and 1 accepting
|
||||
* if trans hashing is used the accepting and non-accepting partitions
|
||||
* can be further split based on the number and type of transitions
|
||||
* a state makes.
|
||||
* If permission hashing is enabled the accepting partitions can
|
||||
* be further divided by permissions. This can result in not
|
||||
* obtaining a truely minimized dfa but comes close, and can speedup
|
||||
* obtaining a truly minimized dfa but comes close, and can speedup
|
||||
* minimization.
|
||||
*/
|
||||
int accept_count = 0;
|
||||
@@ -753,7 +753,7 @@ void DFA::minimize(dfaflags_t flags)
|
||||
|
||||
/* Remap the dfa so it uses the representative states
|
||||
* Use the first state of a partition as the representative state
|
||||
* At this point all states with in a partion have transitions
|
||||
* At this point all states with in a partition have transitions
|
||||
* to states within the same partitions, however this can slow
|
||||
* down compressed dfa compression as there are more states,
|
||||
*/
|
||||
@@ -813,7 +813,7 @@ void DFA::minimize(dfaflags_t flags)
|
||||
}
|
||||
|
||||
/* Now that the states have been remapped, remove all states
|
||||
* that are not the representive states for their partition, they
|
||||
* that are not the representative states for their partition, they
|
||||
* will have a label == -1
|
||||
*/
|
||||
for (Partition::iterator i = states.begin(); i != states.end();) {
|
||||
@@ -875,7 +875,7 @@ static int diff_partition(State *state, Partition &part, int max_range, int uppe
|
||||
|
||||
/**
|
||||
* diff_encode - compress dfa by differentially encoding state transitions
|
||||
* @dfa_flags: flags controling dfa creation
|
||||
* @dfa_flags: flags controlling dfa creation
|
||||
*
|
||||
* This function reduces the number of transitions that need to be stored
|
||||
* by encoding transitions as the difference between the state and a
|
||||
@@ -889,7 +889,7 @@ static int diff_partition(State *state, Partition &part, int max_range, int uppe
|
||||
* - The number of state transitions needed to match an input of length
|
||||
* m will be 2m
|
||||
*
|
||||
* To guarentee this the ordering and distance calculation is done in the
|
||||
* To guarantee this the ordering and distance calculation is done in the
|
||||
* following manner.
|
||||
* - A DAG of the DFA is created starting with the start state(s).
|
||||
* - A state can only be relative (have a differential encoding) to
|
||||
@@ -1352,17 +1352,18 @@ int accept_perms(NodeSet *state, perms_t &perms, bool filedfa)
|
||||
return error;
|
||||
|
||||
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
||||
MatchFlag *match;
|
||||
if (!(match = dynamic_cast<MatchFlag *>(*i)))
|
||||
if (!(*i)->is_type(NODE_TYPE_MATCHFLAG))
|
||||
continue;
|
||||
if (dynamic_cast<ExactMatchFlag *>(match)) {
|
||||
|
||||
MatchFlag *match = static_cast<MatchFlag *>(*i);
|
||||
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
|
||||
/* exact match only ever happens with x */
|
||||
if (filedfa && !is_merged_x_consistent(exact_match_allow,
|
||||
match->flag))
|
||||
error = 1;;
|
||||
exact_match_allow |= match->flag;
|
||||
exact_audit |= match->audit;
|
||||
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
|
||||
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
||||
perms.deny |= match->flag;
|
||||
perms.quiet |= match->audit;
|
||||
} else {
|
||||
|
@@ -189,7 +189,7 @@ struct DiffDag {
|
||||
* accept: the accept permissions for the state
|
||||
* trans: set of transitions from this state
|
||||
* otherwise: the default state for transitions not in @trans
|
||||
* parition: Is a temporary work variable used during dfa minimization.
|
||||
* partition: Is a temporary work variable used during dfa minimization.
|
||||
* it can be replaced with a map, but that is slower and uses more
|
||||
* memory.
|
||||
* proto: Is a temporary work variable used during dfa creation. It can
|
||||
|
@@ -76,7 +76,7 @@ static inline Chars* insert_char_range(Chars* cset, transchar a, transchar b)
|
||||
%%
|
||||
|
||||
/* FIXME: Does not parse "[--]", "[---]", "[^^-x]". I don't actually know
|
||||
which precise grammer Perl regexs use, and rediscovering that
|
||||
which precise grammar Perl regexs use, and rediscovering that
|
||||
is proving to be painful. */
|
||||
|
||||
regex : /* empty */ { *root = $$ = &epsnode; }
|
||||
|
@@ -206,7 +206,7 @@
|
||||
* AppArmor mount rule encoding
|
||||
*
|
||||
* TODO:
|
||||
* add semantic checking of options against specified filesytem types
|
||||
* add semantic checking of options against specified filesystem types
|
||||
* to catch mount options that can't be covered.
|
||||
*
|
||||
*
|
||||
@@ -457,7 +457,7 @@ ostream &mnt_rule::dump(ostream &os)
|
||||
else if (allow & AA_MAY_PIVOTROOT)
|
||||
os << "pivotroot";
|
||||
else
|
||||
os << "error: unknonwn mount perm";
|
||||
os << "error: unknown mount perm";
|
||||
|
||||
os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
|
||||
if (dev_type) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# parser.conf is a global AppArmor config file for the apparmor_parser
|
||||
#
|
||||
# It can be used to specify the default options for the parser, which
|
||||
# can then be overriden by options passed on the command line.
|
||||
# can then be overridden by options passed on the command line.
|
||||
#
|
||||
# Leading whitespace is ignored and lines that begin with # are treated
|
||||
# as comments.
|
||||
@@ -43,7 +43,7 @@
|
||||
#skip-read-cache
|
||||
|
||||
|
||||
#### Set Optimizaions. Multiple Optimizations can be set, one per line ####
|
||||
#### Set Optimizations. Multiple Optimizations can be set, one per line ####
|
||||
# For supported optimizations see
|
||||
# apparmor_parser --help=O
|
||||
|
||||
@@ -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
|
||||
|
@@ -373,7 +373,6 @@ extern int skip_mode_force;
|
||||
extern int abort_on_error;
|
||||
extern int skip_bad_cache_rebuild;
|
||||
extern int mru_skip_cache;
|
||||
extern int debug_cache;
|
||||
|
||||
/* provided by parser_lex.l (cannot be used in tst builds) */
|
||||
extern FILE *yyin;
|
||||
|
@@ -23,7 +23,7 @@
|
||||
|
||||
We support 2 types of includes
|
||||
|
||||
#include <name> which searches for the first occurance of name in the
|
||||
#include <name> which searches for the first occurrence of name in the
|
||||
apparmor directory path.
|
||||
|
||||
#include "name" which will search for a relative or absolute pathed
|
||||
@@ -60,7 +60,7 @@
|
||||
static char *path[MAX_PATH] = { NULL };
|
||||
static int npath = 0;
|
||||
|
||||
/* default base directory is /etc/apparmor.d, it can be overriden
|
||||
/* default base directory is /etc/apparmor.d, it can be overridden
|
||||
with the -b option. */
|
||||
|
||||
const char *basedir;
|
||||
|
@@ -359,7 +359,7 @@ void sd_serialize_xtable(std::ostringstream &buf, char **table)
|
||||
int len = strlen(table[i]) + 1;
|
||||
|
||||
/* if its a namespace make sure the second : is overwritten
|
||||
* with 0, so that the namespace and name are \0 seperated
|
||||
* with 0, so that the namespace and name are \0 separated
|
||||
*/
|
||||
if (*table[i] == ':') {
|
||||
char *tmp = table[i] + 1;
|
||||
|
@@ -87,7 +87,10 @@ int mru_skip_cache = 1;
|
||||
* n : use that number of processes/threads to compile policy
|
||||
*/
|
||||
#define JOBS_AUTO LONG_MIN
|
||||
long jobs_max = -8; /* 8 * cpus */
|
||||
#define DEFAULT_JOBS_MAX -8
|
||||
#define DEFAULT_ESTIMATED_JOB_SIZE (50 * 1024 * 1024)
|
||||
long estimated_job_size = DEFAULT_ESTIMATED_JOB_SIZE;
|
||||
long jobs_max = -DEFAULT_JOBS_MAX; /* 8 * cpus */
|
||||
long jobs = JOBS_AUTO; /* default: number of processor cores */
|
||||
long njobs = 0;
|
||||
long jobs_scale = 0; /* number of chance to resample online
|
||||
@@ -129,6 +132,7 @@ static const char *config_file = "/etc/apparmor/parser.conf";
|
||||
#define ARG_OVERRIDE_POLICY_ABI 141
|
||||
#define EARLY_ARG_CONFIG_FILE 142
|
||||
#define ARG_WERROR 143
|
||||
#define ARG_ESTIMATED_COMPILE_SIZE 144
|
||||
|
||||
/* Make sure to update BOTH the short and long_options */
|
||||
static const char *short_options = "ad::f:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:j:";
|
||||
@@ -183,6 +187,7 @@ struct option long_options[] = {
|
||||
{"print-config-file", 0, 0, ARG_PRINT_CONFIG_FILE}, /* no short option */
|
||||
{"override-policy-abi", 1, 0, ARG_OVERRIDE_POLICY_ABI}, /* no short option */
|
||||
{"config-file", 1, 0, EARLY_ARG_CONFIG_FILE}, /* early option, no short option */
|
||||
{"estimated-compile-size", 1, 0, ARG_ESTIMATED_COMPILE_SIZE}, /* no short option, not in help */
|
||||
|
||||
{NULL, 0, 0, 0},
|
||||
};
|
||||
@@ -259,7 +264,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 },
|
||||
@@ -413,6 +418,19 @@ static long process_jobs_arg(const char *arg, const char *val) {
|
||||
return n;
|
||||
}
|
||||
|
||||
static long str_to_size(const char *s)
|
||||
{
|
||||
if (*s == '\0')
|
||||
return 1;
|
||||
else if (strcmp(s, "KB") == 0)
|
||||
return 1024;
|
||||
else if (strcmp(s, "MB") == 0)
|
||||
return 1024*1024;
|
||||
else if (strcmp(s, "GB") == 0)
|
||||
return 1024*1024*1024;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define EARLY_ARG 1
|
||||
#define LATE_ARG 2
|
||||
#define TWOPASS_ARG (EARLY_ARG | LATE_ARG)
|
||||
@@ -433,7 +451,7 @@ int arg_pass(int c) {
|
||||
return LATE_ARG;
|
||||
}
|
||||
|
||||
/* process a single argment from getopt_long
|
||||
/* process a single argument from getopt_long
|
||||
* Returns: 1 if an action arg, else 0
|
||||
*/
|
||||
#define DUMP_HEADER " variables \tDump variables\n" \
|
||||
@@ -730,6 +748,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);
|
||||
@@ -748,6 +768,21 @@ static int process_arg(int c, char *optarg)
|
||||
case ARG_PRINT_CONFIG_FILE:
|
||||
printf("%s\n", config_file);
|
||||
break;
|
||||
case ARG_ESTIMATED_COMPILE_SIZE:
|
||||
/* used to auto tune parser on low resource systems */
|
||||
{
|
||||
char *end;
|
||||
long mult;
|
||||
long long tmp = strtoll(optarg, &end, 0);
|
||||
if (end == optarg ||
|
||||
(errno == ERANGE && (tmp == LLONG_MIN || tmp == LLONG_MAX)) ||
|
||||
(mult = str_to_size(end)) == -1) {
|
||||
PERROR("%s: --estimated-compile-size invalid size '%s'", progname, optarg);
|
||||
exit(1);
|
||||
}
|
||||
estimated_job_size = tmp * mult;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* 'unrecognized option' error message gets printed by getopt_long() */
|
||||
exit(1);
|
||||
@@ -1159,9 +1194,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);
|
||||
@@ -1256,7 +1293,7 @@ do { \
|
||||
* from work_spawn and work_sync. We could throw a C++ exception, is it
|
||||
* worth doing it to avoid the exit here.
|
||||
*
|
||||
* atm not all resources maybe cleanedup at exit
|
||||
* atm not all resources may be cleaned up at exit
|
||||
*/
|
||||
int last_error = 0;
|
||||
void handle_work_result(int retval)
|
||||
@@ -1284,33 +1321,120 @@ static long compute_jobs(long n, long j)
|
||||
return j;
|
||||
}
|
||||
|
||||
static void setup_parallel_compile(void)
|
||||
static void setup_parallel_compile(long ncpus, long maxcpus)
|
||||
{
|
||||
/* jobs and paralell_max set by default, config or args */
|
||||
long n = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
long maxn = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (n == -1)
|
||||
/* unable to determine number of processors, default to 1 */
|
||||
n = 1;
|
||||
if (maxn == -1)
|
||||
/* unable to determine number of processors, default to 1 */
|
||||
maxn = 1;
|
||||
jobs = compute_jobs(n, jobs);
|
||||
jobs_max = compute_jobs(maxn, jobs_max);
|
||||
/* jobs and parallel_max set by default, config or args */
|
||||
if (jobs < 0 || jobs == JOBS_AUTO)
|
||||
jobs_scale = 1;
|
||||
jobs = compute_jobs(ncpus, jobs);
|
||||
jobs_max = compute_jobs(maxcpus, jobs_max);
|
||||
|
||||
if (jobs > jobs_max) {
|
||||
pwarn(WARN_JOBS, "%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
||||
pwarn(WARN_JOBS, "%s: 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;
|
||||
jobs_scale = jobs_max + 1 - ncpus;
|
||||
|
||||
njobs = 0;
|
||||
if (debug_jobs)
|
||||
fprintf(stderr, "jobs: %ld\n", jobs);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tune parameters to adjust the parser to adapt to low memory, low power
|
||||
* systems.
|
||||
* with a profile compile taking up to 10s of MB, launching a lot of
|
||||
* parallel compiles is a bad idea on lauch 16 parallel compiles with
|
||||
* only 50 MB free.
|
||||
*
|
||||
*/
|
||||
#define PREFIX_TOTAL "MemTotal:"
|
||||
#define PREFIX_FREE "MemFree:"
|
||||
#define PREFIX_CACHE "Cached:"
|
||||
|
||||
static bool get_memstat(long long &mem_total, long long &mem_free,
|
||||
long long &mem_cache)
|
||||
{
|
||||
char *line, buf[256];
|
||||
autofclose FILE *f = NULL;
|
||||
|
||||
mem_total = mem_free = mem_cache = -1;
|
||||
|
||||
/* parse /proc/meminfo to get a rough idea of available mem,
|
||||
look into libstatgrab as alternative */
|
||||
f = fopen("/proc/meminfo", "r");
|
||||
if (f == NULL) {
|
||||
PDEBUG("Failed to open /proc/meminfo");
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((line = fgets(buf, sizeof(buf), f)) != NULL) {
|
||||
long long value;
|
||||
if (sscanf(buf, "%*s %lld kB", &value) != 1)
|
||||
continue;
|
||||
|
||||
if (strncmp(buf, PREFIX_FREE, strlen(PREFIX_FREE)) == 0)
|
||||
mem_free = value * 1024;
|
||||
else if (strncmp(buf, PREFIX_TOTAL, strlen(PREFIX_TOTAL)) == 0)
|
||||
mem_total = value * 1024;
|
||||
else if (strncmp(buf, PREFIX_CACHE, strlen(PREFIX_CACHE)) == 0)
|
||||
mem_cache = value * 1024;
|
||||
}
|
||||
|
||||
if (mem_free == -1 || mem_total == -1 || mem_cache == -1) {
|
||||
PDEBUG("Failed to parse mem value");
|
||||
return false;
|
||||
}
|
||||
mem_free += mem_cache;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void auto_tune_parameters(void)
|
||||
{
|
||||
long long mem_total, mem_free, mem_cache;
|
||||
long ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
long maxcpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (ncpus == -1) {
|
||||
PDEBUG("Unable to determine number of processors, default to 1");
|
||||
ncpus = 1;
|
||||
}
|
||||
if (maxcpus == -1) {
|
||||
PDEBUG("Unable to determine number of processors, default to 1");
|
||||
maxcpus = 1;
|
||||
}
|
||||
/* only override if config or param hasn't overridden */
|
||||
if (get_memstat(mem_total, mem_free, mem_cache) == true &&
|
||||
jobs == JOBS_AUTO) {
|
||||
long estimated_jobs = (long) (mem_free / estimated_job_size);
|
||||
|
||||
if (mem_free < 2) {
|
||||
/* -j0 - no workers */
|
||||
jobs = jobs_max = 0;
|
||||
PDEBUG("Auto tune: --jobs=0");
|
||||
} else if (estimated_jobs < ncpus) {
|
||||
/* --jobs=estimate_jobs */
|
||||
jobs = estimated_jobs;
|
||||
PDEBUG("Auto tune: --jobs=%d", estimate_jobs);
|
||||
} else {
|
||||
long long n = estimated_jobs / ncpus;
|
||||
|
||||
if (n < -DEFAULT_JOBS_MAX) {
|
||||
/* --jobs=cpus*n */
|
||||
jobs = -n;
|
||||
PDEBUG("Auto tune: --jobs=%d", jobs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PDEBUG("Unable to get meminfo, using defaults");
|
||||
}
|
||||
|
||||
setup_parallel_compile(ncpus, maxcpus);
|
||||
}
|
||||
|
||||
struct dir_cb_data {
|
||||
aa_kernel_interface *kernel_interface;
|
||||
const char *dirname; /* name of the parent dir */
|
||||
@@ -1414,7 +1538,7 @@ int main(int argc, char *argv[])
|
||||
process_config_file(config_file);
|
||||
optind = process_args(argc, argv);
|
||||
|
||||
setup_parallel_compile();
|
||||
auto_tune_parameters();
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
|
@@ -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);
|
||||
|
@@ -534,7 +534,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
int len;
|
||||
tbuf.clear();
|
||||
/* prepend \x00 to every value. This is
|
||||
* done to separate the existance of the
|
||||
* done to separate the existence of the
|
||||
* xattr from a null value match.
|
||||
*
|
||||
* if an xattr exists, a single \x00 will
|
||||
@@ -642,6 +642,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;
|
||||
|
@@ -847,13 +847,13 @@ int main(void)
|
||||
MY_TEST(retval == 0, "get boolean variable 2");
|
||||
|
||||
retval = get_boolean_var("non_existant");
|
||||
MY_TEST(retval < 0, "get nonexistant boolean variable");
|
||||
MY_TEST(retval < 0, "get nonexistent boolean variable");
|
||||
|
||||
retval = get_boolean_var("stereopuff");
|
||||
MY_TEST(retval < 0, "get boolean variable that's declared a set var");
|
||||
|
||||
retptr = get_set_var("daves_not_here_man");
|
||||
MY_TEST(retptr == NULL, "get non-existent set variable");
|
||||
MY_TEST(retptr == NULL, "get nonexistent set variable");
|
||||
|
||||
retptr = get_set_var("abuse");
|
||||
MY_TEST(retptr == NULL, "get set variable that's declared a boolean");
|
||||
|
@@ -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 03:51-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 ""
|
||||
|
@@ -179,7 +179,7 @@ void install_cache(const char *cachetmpname, const char *cachename)
|
||||
}
|
||||
|
||||
if (rename(cachetmpname, cachename) < 0) {
|
||||
pwarn(WARN_CACHE, "Warning failed to write cache: %s\n", cachename);
|
||||
pwarn(WARN_CACHE, "Failed to write cache: %s\n", cachename);
|
||||
unlink(cachetmpname);
|
||||
}
|
||||
else if (show_cache) {
|
||||
|
@@ -36,7 +36,6 @@ extern int cond_clear_cache; /* only applies if write is set */
|
||||
extern int force_clear_cache; /* force clearing regargless of state */
|
||||
extern int create_cache_dir; /* create the cache dir if missing? */
|
||||
extern int mru_skip_cache;
|
||||
extern int debug_cache;
|
||||
|
||||
void set_cache_tstamp(struct timespec t);
|
||||
void update_mru_tstamp(FILE *file, const char *path);
|
||||
|
@@ -112,7 +112,7 @@ static const char *const sig_names[MAXMAPPED_SIG + 1] = {
|
||||
"lost",
|
||||
"unused",
|
||||
|
||||
"exists", /* always last existance test mapped to MAXMAPPED_SIG */
|
||||
"exists", /* always last existence test mapped to MAXMAPPED_SIG */
|
||||
};
|
||||
|
||||
|
||||
|
@@ -240,7 +240,7 @@ and may grant confined processes specific mount operations.
|
||||
|
||||
The security model of the various versions of NFS is that files are
|
||||
looked up by name as usual, but after that lookup, each file is only
|
||||
identified by a file handle in successive acesses. The file handle at a
|
||||
identified by a file handle in successive accesses. The file handle at a
|
||||
minimum includes some sort of filesystem identifier and the file's inode
|
||||
number. In Linux, the file handles used by most filesystems also
|
||||
include the inode number of the parent directory; this may change in the
|
||||
@@ -816,7 +816,7 @@ one (this option may be used even if no profile by that name exists):
|
||||
|
||||
\subsection{Anatomy of a Profile}
|
||||
|
||||
AppArmor profiles use a simple declaritive language, fully described in
|
||||
AppArmor profiles use a simple declarative language, fully described in
|
||||
the apparmor.d(5) manual page. By convention, profiles are stored in
|
||||
/etc/{\H}apparmor.d/. The AppArmor parser supports a simple cpp-style
|
||||
include mechanism to allow sharing pieces of policy. A simple profile
|
||||
|
@@ -23,7 +23,7 @@ tests: error_output caching minimize equality parser_sanity
|
||||
GEN_TRANS_DIRS=simple_tests/generated_x/ simple_tests/generated_perms_leading/ simple_tests/generated_perms_safe/ simple_tests/generated_dbus
|
||||
|
||||
gen_xtrans: $(GEN_TRANS_DIRS)
|
||||
./gen-xtrans.pl
|
||||
./gen-xtrans.py
|
||||
|
||||
$(GEN_TRANS_DIRS):
|
||||
mkdir $@
|
||||
|
@@ -10,7 +10,7 @@ against a different parser, or use a different set of profiles for the
|
||||
simple.pl test, you can change those settings in 'uservars.conf'.
|
||||
|
||||
You can also override which parser is used through make by specifying
|
||||
the PARSER veriable. For example, to run the tests on the system parser,
|
||||
the PARSER variable. For example, to run the tests on the system parser,
|
||||
run 'make PARSER=/sbin/apparmor_parser'.
|
||||
|
||||
Adding to the testsuite
|
||||
@@ -61,7 +61,7 @@ The simple script looks for a few special comments in the profile,
|
||||
expected parse result of PASS.
|
||||
|
||||
- #=TODO -- marks the test as being for a future item to implement and
|
||||
thus are expected testsuite failures and hsould be ignored.
|
||||
thus are expected testsuite failures and should be ignored.
|
||||
|
||||
- #=DISABLED -- skips the test, and marks it as a failed TODO task.
|
||||
Useful if the particular testcase causes the parser to infinite
|
||||
|
@@ -568,7 +568,7 @@ verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||
# Unfortunately we can not just compare an empty profile and hat to a
|
||||
# ie. "/t { ^test { /f r, }}"
|
||||
# to the second profile with the equivalent rule inserted manually
|
||||
# because policy write permission "w" actually expands to mutiple permissions
|
||||
# because policy write permission "w" actually expands to multiple permissions
|
||||
# under the hood, and the parser is not adding those permissions
|
||||
# to the rules it auto generates
|
||||
# So we insert the rule with "append" permissions, and rely on the parser
|
||||
@@ -618,6 +618,20 @@ 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, }" \
|
||||
|
||||
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
|
||||
then
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||
|
@@ -26,7 +26,7 @@ class AAErrorTests(testlib.AATestTemplate):
|
||||
self.maxDiff = None
|
||||
self.cmd_prefix = [config.parser, '--config-file=./parser.conf', '-S', '-I', 'errors']
|
||||
|
||||
def _run_test(self, profile, message=None, is_error=True):
|
||||
def _run_test(self, profile, message='', is_error=True):
|
||||
cmd = self.cmd_prefix + [profile]
|
||||
|
||||
(rc, out, outerr) = self._run_cmd(cmd, stdout=subprocess.DEVNULL)
|
||||
@@ -36,8 +36,14 @@ class AAErrorTests(testlib.AATestTemplate):
|
||||
else:
|
||||
self.assertEqual(rc, 0, report)
|
||||
|
||||
if message:
|
||||
self.assertIn(message, outerr, report)
|
||||
ignore_messages = [
|
||||
'Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)\n',
|
||||
]
|
||||
for ign in ignore_messages:
|
||||
if ign in outerr:
|
||||
outerr = outerr.replace(ign, '')
|
||||
|
||||
self.assertEqual(message, outerr, report)
|
||||
|
||||
def test_okay(self):
|
||||
self._run_test('errors/okay.sd', is_error=False)
|
||||
@@ -45,32 +51,32 @@ class AAErrorTests(testlib.AATestTemplate):
|
||||
def test_single(self):
|
||||
self._run_test(
|
||||
'errors/single.sd',
|
||||
"AppArmor parser error for errors/single.sd in profile errors/single.sd at line 3: Could not open 'failure'",
|
||||
"AppArmor parser error for errors/single.sd in profile errors/single.sd at line 3: Could not open 'failure'\n",
|
||||
)
|
||||
|
||||
def test_double(self):
|
||||
self._run_test(
|
||||
'errors/double.sd',
|
||||
"AppArmor parser error for errors/double.sd in profile errors/includes/busted at line 66: Could not open 'does-not-exist'",
|
||||
"AppArmor parser error for errors/double.sd in profile errors/includes/busted at line 66: Could not open 'does-not-exist'\n",
|
||||
)
|
||||
|
||||
def test_modefail(self):
|
||||
self._run_test(
|
||||
'errors/modefail.sd',
|
||||
"AppArmor parser error for errors/modefail.sd in profile errors/modefail.sd at line 6: syntax error, unexpected TOK_ID, expecting TOK_MODE",
|
||||
"AppArmor parser error for errors/modefail.sd in profile errors/modefail.sd at line 6: syntax error, unexpected TOK_ID, expecting TOK_MODE\n",
|
||||
)
|
||||
|
||||
def test_multi_include(self):
|
||||
self._run_test(
|
||||
'errors/multi_include.sd',
|
||||
"AppArmor parser error for errors/multi_include.sd in profile errors/multi_include.sd at line 12: Could not open 'failure'",
|
||||
"AppArmor parser error for errors/multi_include.sd in profile errors/multi_include.sd at line 12: Could not open 'failure'\n",
|
||||
)
|
||||
|
||||
def test_deprecation1(self):
|
||||
self.cmd_prefix.extend(['--warn=deprecated'])
|
||||
self._run_test(
|
||||
'errors/deprecation1.sd',
|
||||
"Warning from errors/deprecation1.sd (errors/deprecation1.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information",
|
||||
"Warning from errors/deprecation1.sd (errors/deprecation1.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information\n",
|
||||
is_error=False
|
||||
)
|
||||
|
||||
@@ -78,7 +84,7 @@ class AAErrorTests(testlib.AATestTemplate):
|
||||
self.cmd_prefix.extend(['--warn=deprecated'])
|
||||
self._run_test(
|
||||
'errors/deprecation2.sd',
|
||||
"Warning from errors/deprecation2.sd (errors/deprecation2.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information",
|
||||
"Warning from errors/deprecation2.sd (errors/deprecation2.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information\n",
|
||||
is_error=False
|
||||
)
|
||||
|
||||
|
@@ -1,235 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
|
||||
my $prefix="simple_tests/generated_x";
|
||||
my $prefix_leading="simple_tests/generated_perms_leading";
|
||||
my $prefix_safe="simple_tests/generated_perms_safe";
|
||||
|
||||
my @trans_types = ("p", "P", "c", "C", "u", "i");
|
||||
my @modifiers = ("i", "u");
|
||||
my %trans_modifiers = (
|
||||
"p" => \@modifiers,
|
||||
"P" => \@modifiers,
|
||||
"c" => \@modifiers,
|
||||
"C" => \@modifiers,
|
||||
);
|
||||
|
||||
my @targets = ("", "target", "target2");
|
||||
my @null_target = ("");
|
||||
|
||||
my %named_trans = (
|
||||
"p" => \@targets,
|
||||
"P" => \@targets,
|
||||
"c" => \@targets,
|
||||
"C" => \@targets,
|
||||
"u" => \@null_target,
|
||||
"i" => \@null_target,
|
||||
);
|
||||
|
||||
my %safe_map = (
|
||||
"p" => "unsafe",
|
||||
"P" => "safe",
|
||||
"c" => "unsafe",
|
||||
"C" => "safe",
|
||||
"u" => "",
|
||||
"i" => "",
|
||||
);
|
||||
|
||||
my %invert_safe = (
|
||||
"safe" => "unsafe",
|
||||
"unsafe" => "safe",
|
||||
);
|
||||
|
||||
# audit qualifier disabled for now it really shouldn't affect the conflict
|
||||
# test but it may be worth checking every once in awhile
|
||||
#my @qualifiers = ("", "owner", "audit", "audit owner");
|
||||
my @qualifiers = ("", "owner");
|
||||
|
||||
my $count = 0;
|
||||
|
||||
gen_conflicting_x();
|
||||
gen_overlap_re_exact();
|
||||
gen_dominate_re_re();
|
||||
gen_ambiguous_re_re();
|
||||
gen_leading_perms("exact", "/bin/cat", "/bin/cat");
|
||||
gen_leading_perms("exact-re", "/bin/*", "/bin/*");
|
||||
gen_leading_perms("overlap", "/*", "/bin/cat");
|
||||
gen_leading_perms("dominate", "/**", "/*");
|
||||
gen_leading_perms("ambiguous", "/a*", "/*b");
|
||||
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat");
|
||||
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*");
|
||||
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat");
|
||||
gen_safe_perms("dominate", "PASS", "", "/**", "/*");
|
||||
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b");
|
||||
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat");
|
||||
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*");
|
||||
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat");
|
||||
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*");
|
||||
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b");
|
||||
|
||||
print "Generated $count xtransition interaction tests\n";
|
||||
|
||||
sub gen_list {
|
||||
my @output;
|
||||
foreach my $trans (@trans_types) {
|
||||
if ($trans_modifiers{$trans}) {
|
||||
foreach my $mod (@{$trans_modifiers{$trans}}) {
|
||||
push @output, "${trans}${mod}x";
|
||||
}
|
||||
}
|
||||
push @output, "${trans}x";
|
||||
}
|
||||
return @output;
|
||||
}
|
||||
|
||||
sub print_rule($$$$$$) {
|
||||
my ($file, $leading, $qual, $name, $perm, $target) = @_;
|
||||
if ($leading) {
|
||||
print $file "\t${qual} ${perm} ${name}";
|
||||
} else {
|
||||
print $file "\t${qual} ${name} ${perm}";
|
||||
}
|
||||
if ($target ne "") {
|
||||
print $file " -> $target";
|
||||
}
|
||||
print $file ",\n";
|
||||
}
|
||||
|
||||
sub gen_file($$$$$$$$$$$$) {
|
||||
my ($name, $xres, $leading1, $qual1, $rule1, $perm1, $target1, $leading2, $qual2, $rule2, $perm2, $target2) = @_;
|
||||
|
||||
# print "$xres $rule1 $perm1 $target1 $rule2 $perm2 $target2\n";
|
||||
|
||||
my $file;
|
||||
unless (open $file, ">$name") {
|
||||
print("couldn't open $name\n");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print $file "#\n";
|
||||
print $file "#=DESCRIPTION ${name}\n";
|
||||
print $file "#=EXRESULT ${xres}\n";
|
||||
print $file "#\n";
|
||||
print $file "/usr/bin/foo {\n";
|
||||
print_rule($file, $leading1, $qual1, $rule1, $perm1, $target1);
|
||||
print_rule($file, $leading2, $qual2, $rule2, $perm2, $target2);
|
||||
print $file "}\n";
|
||||
close($file);
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
#NOTE: currently we don't do px to cx, or cx to px conversion
|
||||
# so
|
||||
# /foo {
|
||||
# /* px -> /foo//bar,
|
||||
# /* cx -> bar,
|
||||
#
|
||||
# will conflict
|
||||
#
|
||||
#NOTE: conflict tests don't tests leading permissions or using unsafe keywords
|
||||
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
|
||||
sub gen_files($$$$) {
|
||||
my ($name, $rule1, $rule2, $default) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
# print "@perms\n";
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
foreach my $j (@perms) {
|
||||
foreach my $u (@{$named_trans{substr($j, 0, 1)}}) {
|
||||
foreach my $r (@qualifiers) {
|
||||
my $file="${prefix}/${name}-$q$i$t-$r$j$u.sd";
|
||||
# print "$file\n";
|
||||
|
||||
#override failures when transitions are the same
|
||||
my $xres = ${default};
|
||||
if ($i eq $j && $t eq $u) {
|
||||
$xres = "PASS";
|
||||
}
|
||||
|
||||
|
||||
# print "foo $xres $rule1 $i $t $rule2 $j $u\n";
|
||||
gen_file($file, $xres, 0, $q, $rule1, $i, $t, 0, $r, $rule2, $j, $u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub gen_conflicting_x {
|
||||
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL");
|
||||
}
|
||||
|
||||
sub gen_overlap_re_exact {
|
||||
|
||||
gen_files("exact", "/bin/cat", "/bin/*", "PASS");
|
||||
}
|
||||
|
||||
# we currently don't support this, once supported change to "PASS"
|
||||
sub gen_dominate_re_re {
|
||||
gen_files("dominate", "/bin/*", "/bin/**", "FAIL");
|
||||
}
|
||||
|
||||
sub gen_ambiguous_re_re {
|
||||
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL");
|
||||
}
|
||||
|
||||
|
||||
# test that rules that lead with permissions don't conflict with
|
||||
# the same rule using trailing permissions.
|
||||
sub gen_leading_perms($$$) {
|
||||
my ($name, $rule1, $rule2) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
my $file="${prefix_leading}/${name}-$q$i$t.sd";
|
||||
# print "$file\n";
|
||||
|
||||
gen_file($file, "PASS", 0, $q, $rule1, $i, $t, 1, $q, $rule2, $i, $t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# test for rules with leading safe or unsafe keywords.
|
||||
# check they are equivalent to their counter part,
|
||||
# or if $invert that they properly conflict with their counterpart
|
||||
sub gen_safe_perms($$$$$) {
|
||||
my ($name, $xres, $invert, $rule1, $rule2) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
my $qual = $safe_map{substr($i, 0, 1)};
|
||||
if ($invert) {
|
||||
$qual = $invert_safe{$qual};
|
||||
}
|
||||
if (! $invert || $qual) {
|
||||
my $file="${prefix_safe}/${name}-$invert-$q${qual}-rule-$i$t.sd";
|
||||
# print "$file\n";
|
||||
gen_file($file, $xres, 0, "$q $qual", $rule1, $i, $t, 1, $q, $rule2, $i, $t);
|
||||
$file="${prefix_safe}/${name}-$invert-$q$qual${i}-rule-$t.sd";
|
||||
gen_file($file, $xres, 0, $q, $rule1, $i, $t, 1, "$q $qual", $rule2, $i, $t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
219
parser/tst/gen-xtrans.py
Executable file
219
parser/tst/gen-xtrans.py
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2010-2011 Canonical Ltd.
|
||||
# Copyright (C) 2020 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
from testlib import write_file
|
||||
|
||||
prefix = "simple_tests/generated_x"
|
||||
prefix_leading = "simple_tests/generated_perms_leading"
|
||||
prefix_safe = "simple_tests/generated_perms_safe"
|
||||
|
||||
trans_types = ("p", "P", "c", "C", "u", "i")
|
||||
modifiers = ("i", "u")
|
||||
trans_modifiers = {
|
||||
"p": modifiers,
|
||||
"P": modifiers,
|
||||
"c": modifiers,
|
||||
"C": modifiers,
|
||||
}
|
||||
|
||||
targets = ("", "target", "target2")
|
||||
# null_target uses "_" instead of "" because "" gets skipped in some for loops. Replace with "" when actually using the value.
|
||||
null_target = ("_")
|
||||
|
||||
named_trans = {
|
||||
"p": targets,
|
||||
"P": targets,
|
||||
"c": targets,
|
||||
"C": targets,
|
||||
"u": null_target,
|
||||
"i": null_target,
|
||||
}
|
||||
|
||||
safe_map = {
|
||||
"p": "unsafe",
|
||||
"P": "safe",
|
||||
"c": "unsafe",
|
||||
"C": "safe",
|
||||
"u": "",
|
||||
"i": "",
|
||||
}
|
||||
|
||||
invert_safe = {
|
||||
"safe": "unsafe",
|
||||
"unsafe": "safe",
|
||||
'': '',
|
||||
}
|
||||
|
||||
# audit qualifier disabled for now it really shouldn't affect the conflict
|
||||
# test but it may be worth checking every once in awhile
|
||||
# qualifiers = ("", "owner", "audit", "audit owner")
|
||||
qualifiers = ("", "owner")
|
||||
|
||||
count = 0
|
||||
|
||||
def gen_list():
|
||||
output = []
|
||||
for trans in trans_types:
|
||||
if trans in trans_modifiers:
|
||||
for mod in trans_modifiers[trans]:
|
||||
output.append("%s%sx" % (trans, mod))
|
||||
|
||||
output.append("%sx" % trans)
|
||||
|
||||
return output
|
||||
|
||||
def test_gen_list():
|
||||
''' test if gen_list returns the expected output '''
|
||||
|
||||
expected = "pix pux px Pix Pux Px cix cux cx Cix Cux Cx ux ix".split()
|
||||
actual = gen_list()
|
||||
|
||||
if actual != expected:
|
||||
raise Exception("gen_list produced unexpected result, expected %s, got %s" % (expected, actual))
|
||||
|
||||
def build_rule(leading, qual, name, perm, target):
|
||||
rule = ''
|
||||
|
||||
if leading:
|
||||
rule += "\t%s %s %s" % (qual, perm, name)
|
||||
else:
|
||||
rule += "\t%s %s %s" % (qual, name, perm)
|
||||
|
||||
if target != "":
|
||||
rule += " -> %s" % target
|
||||
|
||||
rule += ",\n"
|
||||
|
||||
return rule
|
||||
|
||||
def gen_file (name, xres, leading1, qual1, rule1, perm1, target1, leading2, qual2, rule2, perm2, target2):
|
||||
global count
|
||||
count += 1
|
||||
|
||||
content = ''
|
||||
content += "#\n"
|
||||
content += "#=DESCRIPTION %s\n" % name
|
||||
content += "#=EXRESULT %s\n" % xres
|
||||
content += "#\n"
|
||||
content += "/usr/bin/foo {\n"
|
||||
content += build_rule(leading1, qual1, rule1, perm1, target1)
|
||||
content += build_rule(leading2, qual2, rule2, perm2, target2)
|
||||
content += "}\n"
|
||||
|
||||
write_file('', name, content)
|
||||
|
||||
|
||||
# NOTE: currently we don't do px to cx, or cx to px conversion
|
||||
# so
|
||||
# /foo {
|
||||
# /* px -> /foo//bar,
|
||||
# /* cx -> bar,
|
||||
#
|
||||
# will conflict
|
||||
#
|
||||
# NOTE: conflict tests don't tests leading permissions or using unsafe keywords
|
||||
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
|
||||
def gen_files(name, rule1, rule2, default):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
for j in perms:
|
||||
for u in named_trans[j[0]]:
|
||||
if u == '_':
|
||||
u = ''
|
||||
for r in qualifiers:
|
||||
file = prefix + '/' + name + '-' + q + i + t + '-' + r + j + u + '.sd'
|
||||
|
||||
# override failures when transitions are the same
|
||||
xres = default
|
||||
if (i == j and t == u):
|
||||
xres = "PASS"
|
||||
|
||||
gen_file(file, xres, 0, q, rule1, i, t, 0, r, rule2, j, u)
|
||||
|
||||
def gen_conflicting_x():
|
||||
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL")
|
||||
|
||||
def gen_overlap_re_exact():
|
||||
gen_files("exact", "/bin/cat", "/bin/*", "PASS")
|
||||
|
||||
# we currently don't support this, once supported change to "PASS"
|
||||
def gen_dominate_re_re():
|
||||
gen_files("dominate", "/bin/*", "/bin/**", "FAIL")
|
||||
|
||||
def gen_ambiguous_re_re():
|
||||
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL")
|
||||
|
||||
|
||||
# test that rules that lead with permissions don't conflict with
|
||||
# the same rule using trailing permissions.
|
||||
def gen_leading_perms (name, rule1, rule2):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
file = prefix_leading + '/' + name + '-' + q + i + t + ".sd"
|
||||
gen_file(file, "PASS", 0, q, rule1, i, t, 1, q, rule2, i, t)
|
||||
|
||||
# test for rules with leading safe or unsafe keywords.
|
||||
# check they are equivalent to their counter part,
|
||||
# or if $invert that they properly conflict with their counterpart
|
||||
def gen_safe_perms(name, xres, invert, rule1, rule2):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
qual = safe_map[i[0]]
|
||||
if invert:
|
||||
qual = invert_safe[qual]
|
||||
|
||||
if (not invert or qual):
|
||||
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + '-' + 'rule-' + i + t + '.sd'
|
||||
gen_file(file, xres, 0, '%s %s' % (q, qual), rule1, i, t, 1, q, rule2, i, t)
|
||||
|
||||
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + i + '-' + 'rule-' + t + '.sd'
|
||||
gen_file(file, xres, 0, q, rule1, i, t, 1, '%s %s' % (q, qual), rule2, i, t)
|
||||
|
||||
|
||||
test_gen_list()
|
||||
|
||||
gen_conflicting_x()
|
||||
gen_overlap_re_exact()
|
||||
gen_dominate_re_re()
|
||||
gen_ambiguous_re_re()
|
||||
gen_leading_perms("exact", "/bin/cat", "/bin/cat")
|
||||
gen_leading_perms("exact-re", "/bin/*", "/bin/*")
|
||||
gen_leading_perms("overlap", "/*", "/bin/cat")
|
||||
gen_leading_perms("dominate", "/**", "/*")
|
||||
gen_leading_perms("ambiguous", "/a*", "/*b")
|
||||
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat")
|
||||
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*")
|
||||
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat")
|
||||
gen_safe_perms("dominate", "PASS", "", "/**", "/*")
|
||||
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b")
|
||||
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat")
|
||||
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*")
|
||||
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat")
|
||||
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*")
|
||||
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b")
|
||||
|
||||
print ("Generated %s xtransition interaction tests" % count)
|
@@ -5,7 +5,7 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
|
||||
|
||||
# Format of -D dfa-states
|
||||
# dfa-states output is split into 2 parts:
|
||||
# the accept state infomation
|
||||
# the accept state information
|
||||
# {state} (allow deny audit XXX) ignore XXX for now
|
||||
# followed by the transition table information
|
||||
# {Y} -> {Z}: 0xXX Char #0xXX is the hex dump of Char
|
||||
@@ -43,7 +43,7 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
|
||||
# These tests currently only look at the accept state permissions
|
||||
#
|
||||
# To view any of these DFAs as graphs replace --D dfa-states with -D dfa-graph
|
||||
# strip of the test stuff around the parser command and use the the dot
|
||||
# strip of the test stuff around the parser command and use the dot
|
||||
# command to convert
|
||||
# Eg.
|
||||
# echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ./apparmor_parser -QT -O minimize -D dfa-graph --quiet 2>min.graph
|
||||
@@ -100,7 +100,7 @@ fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with deny 'w' perm added to /**, this does not
|
||||
# elimnates the states with 'w' and 'a' because the quiet information is
|
||||
# eliminates the states with 'w' and 'a' because the quiet information is
|
||||
# being carried
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
@@ -119,7 +119,7 @@ fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with audit deny 'w' perm added to /**, with the
|
||||
# parameter this elimnates the states with 'w' and 'a' because
|
||||
# parameter this eliminates the states with 'w' and 'a' because
|
||||
# the quiet information is NOT being carried
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
@@ -139,7 +139,7 @@ echo "ok"
|
||||
|
||||
# The x transition test profile is setup so that there are 3 conflicting x
|
||||
# permissions, two are on paths that won't collide during dfa creation. The
|
||||
# 3rd is a generic permission that should be overriden during dfa creation.
|
||||
# 3rd is a generic permission that should be overridden during dfa creation.
|
||||
#
|
||||
# This should result in a dfa that specifies transitions on 'a' and 'b' to
|
||||
# unique states that store the alternate accept information. However
|
||||
@@ -190,7 +190,7 @@ fi
|
||||
echo "ok"
|
||||
|
||||
# now try audit + denying x and make sure perms are cleared
|
||||
# notice that the deny info is being carried, by an artifical trap state
|
||||
# notice that the deny info is being carried, by an artificial trap state
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/fe17f85/0/0)
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=EXRESULT FAIL
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#=DESCRIPTION conditional else in invlaid locations
|
||||
#=DESCRIPTION conditional else in invalid locations
|
||||
#=EXRESULT FAIL
|
||||
|
||||
$BAR = false
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION netdomain tcp connect w/multiple from statments
|
||||
#=DESCRIPTION netdomain tcp connect w/multiple from statements
|
||||
#=EXRESULT FAIL
|
||||
/tmp/tcp/tcp_client {
|
||||
tcp_connect from 10.0.0.17/16:50-100 from 127.0.0.1 via eth1,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# $Id$
|
||||
#=DESCRIPTION Basic namespace test wit named profile, duplicate mode bits
|
||||
#=DESCRIPTION Basic namespace test with named profile, duplicate mode bits
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION simple max virtual memory szie rlimit test
|
||||
#=DESCRIPTION simple max virtual memory size rlimit test
|
||||
#=EXRESULT PASS
|
||||
|
||||
profile rlimit {
|
||||
|
@@ -47,10 +47,10 @@ else
|
||||
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
|
||||
PARSER?=../parser/apparmor_parser
|
||||
# use ../utils logprof
|
||||
LOGPROF?=LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) PYTHONPATH=$(PYTHONPATH) $(PYTHON) ../utils/aa-logprof
|
||||
LOGPROF?=LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) PYTHONPATH=$(PYTHONPATH) $(PYTHON) ../utils/aa-logprof --configdir ../utils/test/
|
||||
endif
|
||||
|
||||
# $(PWD) is wrong when using "make -C profiles" - explicitely set it here to get the right value
|
||||
# $(PWD) is wrong when using "make -C profiles" - explicitly set it here to get the right value
|
||||
PWD=$(shell pwd)
|
||||
|
||||
.PHONY: test-dependencies
|
||||
|
@@ -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,
|
||||
|
@@ -29,8 +29,8 @@
|
||||
# include <abstractions/ubuntu-browsers>
|
||||
# include <abstractions/ubuntu-email>
|
||||
#
|
||||
# # Add if accesibility access is considered as required
|
||||
# # (for message boxe in case exo-open fails)
|
||||
# # Add if accessibility access is considered as required
|
||||
# # (for message box in case exo-open fails)
|
||||
# include <abstractions/dbus-accessibility>
|
||||
#
|
||||
# # < add additional allowed applications here >
|
||||
|
@@ -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,
|
||||
|
@@ -29,8 +29,8 @@
|
||||
# include <abstractions/ubuntu-browsers>
|
||||
# include <abstractions/ubuntu-email>
|
||||
#
|
||||
# # Add if accesibility access is considered as required
|
||||
# # (for message boxe in case exo-open fails)
|
||||
# # Add if accessibility access is considered as required
|
||||
# # (for message box in case exo-open fails)
|
||||
# include <abstractions/dbus-accessibility>
|
||||
#
|
||||
# # Add if audio support for message box is
|
||||
|
@@ -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>
|
||||
|
@@ -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,
|
||||
|
@@ -14,7 +14,7 @@
|
||||
# it is intended to be included in profiles for svnserve/apache2 and maybe
|
||||
# some repository viewers like trac/viewvc
|
||||
|
||||
# no hooks exec by default; please define whatever you need explicitely.
|
||||
# no hooks exec by default; please define whatever you need explicitly.
|
||||
|
||||
/srv/svn/**/conf/* r,
|
||||
/srv/svn/**/format r,
|
||||
|
@@ -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,5 +14,8 @@
|
||||
owner @{run}/user/*/wayland-[0-9]* rw,
|
||||
owner @{run}/user/*/{mesa,mutter,sdl,wayland-cursor,weston,xwayland}-shared-* rw,
|
||||
|
||||
#For compositors based on wlroots
|
||||
owner /dev/shm/wlroots-* rw,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/wayland.d>
|
||||
|
@@ -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
|
||||
|
@@ -41,7 +41,7 @@
|
||||
|
||||
include <abstractions/base>
|
||||
|
||||
# for openin with `exo-open`
|
||||
# for opening with `exo-open`
|
||||
include <abstractions/exo-open>
|
||||
|
||||
# for opening with `gio open <uri>`
|
||||
|
27
profiles/apparmor.d/usr.lib.dovecot.director
Normal file
27
profiles/apparmor.d/usr.lib.dovecot.director
Normal file
@@ -0,0 +1,27 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2020 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim: ft=apparmor
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile dovecot-director /usr/lib/dovecot/director flags=(attach_disconnected) {
|
||||
include <abstractions/base>
|
||||
include <abstractions/dovecot-common>
|
||||
include <abstractions/nameservice>
|
||||
|
||||
capability setuid,
|
||||
capability sys_chroot,
|
||||
|
||||
/run/dovecot/login/proxy-notify rw,
|
||||
/usr/lib/dovecot/director mr,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/usr.lib.dovecot.director>
|
||||
}
|
22
profiles/apparmor.d/usr.lib.dovecot.doveadm-server
Normal file
22
profiles/apparmor.d/usr.lib.dovecot.doveadm-server
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2020 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim: ft=apparmor
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile dovecot-doveadm-server /usr/lib/dovecot/doveadm-server flags=(attach_disconnected) {
|
||||
include <abstractions/base>
|
||||
include <abstractions/dovecot-common>
|
||||
|
||||
/usr/lib/dovecot/doveadm-server mr,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/usr.lib.dovecot.doveadm-server>
|
||||
}
|
@@ -21,7 +21,6 @@ profile dovecot-imap /usr/lib/dovecot/imap {
|
||||
include <abstractions/dovecot-common>
|
||||
|
||||
capability setuid,
|
||||
deny capability block_suspend,
|
||||
|
||||
network unix stream,
|
||||
|
||||
|
36
profiles/apparmor.d/usr.lib.dovecot.replicator
Normal file
36
profiles/apparmor.d/usr.lib.dovecot.replicator
Normal file
@@ -0,0 +1,36 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2020 SUSE LLC
|
||||
# Copyright (C) 2009-2010 Canonical Ltd.
|
||||
# Copyright (C) 2011-2013 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim: ft=apparmor
|
||||
# for https://wiki.dovecot.org/Replication
|
||||
|
||||
include <tunables/dovecot>
|
||||
include <tunables/global>
|
||||
|
||||
profile dovecot-replicator /usr/lib/dovecot/replicator {
|
||||
include <abstractions/base>
|
||||
include <abstractions/dovecot-common>
|
||||
include <abstractions/nameservice>
|
||||
|
||||
network unix stream,
|
||||
|
||||
/etc/dovecot/conf.d/ r,
|
||||
/etc/dovecot/conf.d/** r,
|
||||
/etc/dovecot/dovecot.conf r,
|
||||
/usr/lib/dovecot/replicator mr,
|
||||
/usr/share/dovecot/** r,
|
||||
/{,var/}run/dovecot/auth-master rw,
|
||||
@{DOVECOT_MAILSTORE}/ rw,
|
||||
@{DOVECOT_MAILSTORE}/** rwlk,
|
||||
/var/lib/dovecot/replicator.db rw,
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/usr.lib.dovecot.replicator>
|
||||
}
|
@@ -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),
|
||||
@@ -50,6 +50,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
/usr/lib/dovecot/auth mrPx,
|
||||
/usr/lib/dovecot/config mrPx,
|
||||
/usr/lib/dovecot/dict mrPx,
|
||||
/usr/lib/dovecot/director mrPx,
|
||||
/usr/lib/dovecot/doveadm-server mrPx,
|
||||
/usr/lib/dovecot/dovecot-auth Pxmr,
|
||||
/usr/lib/dovecot/imap Pxmr,
|
||||
/usr/lib/dovecot/imap-login Pxmr,
|
||||
@@ -59,11 +61,13 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
/usr/lib/dovecot/managesieve-login Pxmr,
|
||||
/usr/lib/dovecot/pop3 mrPx,
|
||||
/usr/lib/dovecot/pop3-login Pxmr,
|
||||
/usr/lib/dovecot/replicator mrPx,
|
||||
/usr/lib/dovecot/script-login Px,
|
||||
/usr/lib/dovecot/ssl-build-param rix,
|
||||
/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,
|
||||
|
@@ -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,
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user