mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 06:45:38 +00:00
Compare commits
133 Commits
check-if-s
...
v3.0.4
Author | SHA1 | Date | |
---|---|---|---|
|
939530b2b8 | ||
|
b4fc4c3c14 | ||
|
59a22c5786 | ||
|
f3ee5a1849 | ||
|
2c25ed160e | ||
|
edf59286e5 | ||
|
1e9e0e40a9 | ||
|
5049cdb45f | ||
|
aa82f874e2 | ||
|
fa98c9aafa | ||
|
033ed7837c | ||
|
5ca5b3879f | ||
|
ab4cfb5e84 | ||
|
d1e2ab6a77 | ||
|
b4cc405b80 | ||
|
c2c2cf005c | ||
|
0e4d3e6b30 | ||
|
af8d5021a5 | ||
|
8c63d75a20 | ||
|
7371119f28 | ||
|
e8041a7f48 | ||
|
b23de50180 | ||
|
9aac5e09d7 | ||
|
cb285b0cdd | ||
|
609a262447 | ||
|
e186512671 | ||
|
ca6f239790 | ||
|
c903b36d05 | ||
|
66ede4ae7a | ||
|
663b9636ed | ||
|
73e2f0cd8c | ||
|
37f5326d0e | ||
|
06dc32a9f3 | ||
|
b1a6f9c86e | ||
|
dc00e28558 | ||
|
6cfc6eeec2 | ||
|
4fbd6468ac | ||
|
e9e9340eff | ||
|
1a6c042ac6 | ||
|
5a5f969a5e | ||
|
59ec31bcb3 | ||
|
b1b046f4b6 | ||
|
53e34f9d53 | ||
|
93f080fe8e | ||
|
79d03f4279 | ||
|
d01bfaefc7 | ||
|
4d8bbf97fc | ||
|
5d030f7765 | ||
|
bcef865116 | ||
|
b86bb506ef | ||
|
64fbb1e25b | ||
|
2cedb8794c | ||
|
37e691bd8a | ||
|
5af298855f | ||
|
071eb797ef | ||
|
c7d426255b | ||
|
0729b13293 | ||
|
3396bf8d77 | ||
|
debe35adf5 | ||
|
ec44a2c46b | ||
|
4ba0e3897a | ||
|
4a9d52c7e6 | ||
|
27c931f089 | ||
|
9e22a6e1e3 | ||
|
fe64edc828 | ||
|
7ab110df19 | ||
|
244334eab3 | ||
|
4831e933f0 | ||
|
b5a2a1ec13 | ||
|
4ee00aa076 | ||
|
55da3a19c2 | ||
|
e58742c028 | ||
|
7f84e8bc4e | ||
|
8b939b8dd4 | ||
|
4c6f8352b1 | ||
|
f79ea041a4 | ||
|
4983fda88b | ||
|
3db5d76282 | ||
|
1cd34e5ce6 | ||
|
06b56e2511 | ||
|
377613433f | ||
|
6e8df906bf | ||
|
f65572d847 | ||
|
b35b15ae70 | ||
|
acf97383ae | ||
|
88acc4006d | ||
|
42c12930a3 | ||
|
9d24cef8d5 | ||
|
e35e838034 | ||
|
c848e8e270 | ||
|
f5c0fe6dce | ||
|
49f3b6649b | ||
|
543da0cee9 | ||
|
c4a2f5d9b1 | ||
|
b0f08aa9d6 | ||
|
f8cdac9017 | ||
|
4c7042c1fc | ||
|
900b595cab | ||
|
4992a6ab86 | ||
|
dd7f1817b4 | ||
|
ec93821b54 | ||
|
7497ff4353 | ||
|
c4150a1659 | ||
|
cd464446b6 | ||
|
ba23532a59 | ||
|
11d1f3812f | ||
|
51144b5cbb | ||
|
3e18c0785a | ||
|
15595eb51d | ||
|
ad30555a96 | ||
|
b0e12a5788 | ||
|
1ba978b65c | ||
|
3c2ddc2ede | ||
|
805cb2c796 | ||
|
8cb1f8f4f6 | ||
|
ff72ea9a56 | ||
|
eab43b5358 | ||
|
bf75381287 | ||
|
80efc15e18 | ||
|
49db93a79d | ||
|
935003883e | ||
|
5ee729331a | ||
|
d89478794e | ||
|
738c7c60ba | ||
|
e142376368 | ||
|
8f39da5501 | ||
|
2f774431cb | ||
|
b64bf7771a | ||
|
848664b47b | ||
|
526c902ba2 | ||
|
b73b8ed432 | ||
|
59589308eb | ||
|
2ef17fa972 |
21
.gitignore
vendored
21
.gitignore
vendored
@@ -216,11 +216,7 @@ utils/vim/apparmor.vim
|
||||
utils/vim/apparmor.vim.5
|
||||
utils/vim/apparmor.vim.5.html
|
||||
utils/vim/pod2htmd.tmp
|
||||
tests/regression/apparmor/*.o
|
||||
tests/regression/apparmor/aa_policy_cache
|
||||
tests/regression/apparmor/access
|
||||
tests/regression/apparmor/at_secure
|
||||
tests/regression/apparmor/attach_disconnected
|
||||
tests/regression/apparmor/changehat
|
||||
tests/regression/apparmor/changehat_fail
|
||||
tests/regression/apparmor/changehat_fork
|
||||
@@ -235,10 +231,6 @@ tests/regression/apparmor/chgrp
|
||||
tests/regression/apparmor/chmod
|
||||
tests/regression/apparmor/chown
|
||||
tests/regression/apparmor/clone
|
||||
tests/regression/apparmor/dbus_eavesdrop
|
||||
tests/regression/apparmor/dbus_message
|
||||
tests/regression/apparmor/dbus_service
|
||||
tests/regression/apparmor/dbus_unrequested_reply
|
||||
tests/regression/apparmor/deleted
|
||||
tests/regression/apparmor/env_check
|
||||
tests/regression/apparmor/environ
|
||||
@@ -249,10 +241,7 @@ tests/regression/apparmor/fchdir
|
||||
tests/regression/apparmor/fchgrp
|
||||
tests/regression/apparmor/fchmod
|
||||
tests/regression/apparmor/fchown
|
||||
tests/regression/apparmor/fd_inheritance
|
||||
tests/regression/apparmor/fd_inheritor
|
||||
tests/regression/apparmor/fork
|
||||
tests/regression/apparmor/introspect
|
||||
tests/regression/apparmor/link
|
||||
tests/regression/apparmor/link_subset
|
||||
tests/regression/apparmor/mkdir
|
||||
@@ -263,20 +252,15 @@ tests/regression/apparmor/net_raw
|
||||
tests/regression/apparmor/open
|
||||
tests/regression/apparmor/openat
|
||||
tests/regression/apparmor/pipe
|
||||
tests/regression/apparmor/pivot_root
|
||||
tests/regression/apparmor/ptrace
|
||||
tests/regression/apparmor/ptrace_helper
|
||||
tests/regression/apparmor/pwrite
|
||||
tests/regression/apparmor/query_label
|
||||
tests/regression/apparmor/readdir
|
||||
tests/regression/apparmor/rename
|
||||
tests/regression/apparmor/rw
|
||||
tests/regression/apparmor/socketpair
|
||||
tests/regression/apparmor/swap
|
||||
tests/regression/apparmor/symlink
|
||||
tests/regression/apparmor/syscall_chroot
|
||||
tests/regression/apparmor/syscall_ioperm
|
||||
tests/regression/apparmor/syscall_iopl
|
||||
tests/regression/apparmor/syscall_mknod
|
||||
tests/regression/apparmor/syscall_mlockall
|
||||
tests/regression/apparmor/syscall_ptrace
|
||||
@@ -288,15 +272,10 @@ tests/regression/apparmor/syscall_setscheduler
|
||||
tests/regression/apparmor/syscall_sysctl
|
||||
tests/regression/apparmor/sysctl_proc
|
||||
tests/regression/apparmor/tcp
|
||||
tests/regression/apparmor/transition
|
||||
tests/regression/apparmor/unix_fd_client
|
||||
tests/regression/apparmor/unix_fd_server
|
||||
tests/regression/apparmor/unix_socket
|
||||
tests/regression/apparmor/unix_socket_client
|
||||
tests/regression/apparmor/unlink
|
||||
tests/regression/apparmor/uservars.inc
|
||||
tests/regression/apparmor/xattrs
|
||||
tests/regression/apparmor/xattrs_profile
|
||||
tests/regression/apparmor/coredump
|
||||
**/__pycache__/
|
||||
*.orig
|
||||
|
137
.gitlab-ci.yml
137
.gitlab-ci.yml
@@ -1,5 +1,9 @@
|
||||
---
|
||||
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 python3-setuptools zlib1g-dev
|
||||
- lsb_release -a
|
||||
- uname -a
|
||||
|
||||
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
||||
# reports
|
||||
@@ -8,131 +12,44 @@ stages:
|
||||
- build
|
||||
- test
|
||||
|
||||
.ubuntu-before_script:
|
||||
before_script:
|
||||
- export DEBIAN_FRONTEND=noninteractive
|
||||
- apt-get update -qq
|
||||
- apt-get install --no-install-recommends -y gcc perl liblocale-gettext-perl linux-libc-dev lsb-release make
|
||||
- lsb_release -a
|
||||
- uname -a
|
||||
|
||||
.install-c-build-deps: &install-c-build-deps
|
||||
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
|
||||
|
||||
build-all:
|
||||
stage: build
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
artifacts:
|
||||
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
expire_in: 30 days
|
||||
untracked: true
|
||||
paths:
|
||||
- libraries/libapparmor/
|
||||
- parser/
|
||||
- binutils/
|
||||
- utils/
|
||||
- changehat/mod_apparmor/
|
||||
- changehat/pam_apparmor/
|
||||
- profiles/
|
||||
- libraries/libapparmor/
|
||||
- parser/
|
||||
- binutils/
|
||||
- utils/
|
||||
- changehat/mod_apparmor/
|
||||
- changehat/pam_apparmor/
|
||||
- profiles/
|
||||
script:
|
||||
- *install-c-build-deps
|
||||
- cd libraries/libapparmor && ./autogen.sh && ./configure --with-perl --with-python --prefix=/usr && make && cd ../.. || { cat config.log ; exit 1 ; }
|
||||
- make -C parser
|
||||
- make -C binutils
|
||||
- make -C utils
|
||||
- make -C changehat/mod_apparmor
|
||||
- make -C changehat/pam_apparmor
|
||||
- make -C profiles
|
||||
- cd libraries/libapparmor && ./autogen.sh && ./configure --with-perl --with-python --prefix=/usr && make && cd ../.. || { cat config.log ; exit 1 ; }
|
||||
- make -C parser
|
||||
- make -C binutils
|
||||
- make -C utils
|
||||
- make -C changehat/mod_apparmor
|
||||
- make -C changehat/pam_apparmor
|
||||
- make -C profiles
|
||||
|
||||
test-libapparmor:
|
||||
test-all:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- *install-c-build-deps
|
||||
- make -C libraries/libapparmor check
|
||||
|
||||
test-parser:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- *install-c-build-deps
|
||||
- make -C parser check
|
||||
|
||||
test-binutils:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- make -C binutils check
|
||||
|
||||
test-utils:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter pyflakes3 python3-coverage python3-notify2 python3-psutil
|
||||
# See apparmor/apparmor#221
|
||||
- make -C parser/tst gen_dbus
|
||||
- make -C parser/tst gen_xtrans
|
||||
- make -C utils check
|
||||
- make -C utils/test coverage-regression
|
||||
artifacts:
|
||||
paths:
|
||||
- utils/test/htmlcov/
|
||||
when: always
|
||||
|
||||
test-mod-apparmor:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- make -C changehat/mod_apparmor check
|
||||
|
||||
test-profiles:
|
||||
stage: test
|
||||
needs: ["build-all"]
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- make -C profiles check-parser
|
||||
- make -C profiles check-abstractions.d
|
||||
|
||||
shellcheck:
|
||||
stage: test
|
||||
needs: []
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- apt-get install --no-install-recommends -y file shellcheck xmlstarlet
|
||||
- shellcheck --version
|
||||
- './tests/bin/shellcheck-tree --format=checkstyle
|
||||
| xmlstarlet tr tests/checkstyle2junit.xslt
|
||||
> shellcheck.xml'
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit: shellcheck.xml
|
||||
- make -C libraries/libapparmor check
|
||||
- make -C parser check
|
||||
- make -C binutils check
|
||||
- make -C utils check
|
||||
- make -C changehat/mod_apparmor check
|
||||
- make -C profiles check-parser
|
||||
- make -C profiles check-abstractions.d
|
||||
|
||||
# Disabled due to aa-logprof dependency on /sbin/apparmor_parser existing
|
||||
# - make -C profiles check-profiles
|
||||
# - make -C profiles check-profiles
|
||||
|
||||
# test-pam_apparmor:
|
||||
# - stage: test
|
||||
# - script:
|
||||
# - cd changehat/pam_apparmor && make check
|
||||
|
||||
include:
|
||||
- template: SAST.gitlab-ci.yml
|
||||
- template: Secret-Detection.gitlab-ci.yml
|
||||
|
||||
variables:
|
||||
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
||||
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
||||
|
@@ -1,10 +0,0 @@
|
||||
# Don't follow source'd scripts
|
||||
disable=SC1090
|
||||
disable=SC1091
|
||||
|
||||
# dash supports 'local'
|
||||
disable=SC2039
|
||||
disable=SC3043
|
||||
|
||||
# dash supports 'echo -n'
|
||||
disable=SC3037
|
@@ -1,66 +0,0 @@
|
||||
# Copyright (C) 2015 Canonical Ltd
|
||||
# This file is distributed under the same license as the AppArmor package.
|
||||
# John Johansen <john.johansen@canonical.com>, 2015.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||
"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:26
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: [options]\n"
|
||||
" options:\n"
|
||||
" -q | --quiet Don't print out any messages\n"
|
||||
" -h | --help Print help\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:45
|
||||
#, c-format
|
||||
msgid "unknown or incompatible options\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:55
|
||||
#, c-format
|
||||
msgid "unknown option '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:64
|
||||
#, c-format
|
||||
msgid "Yes\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:71
|
||||
#, c-format
|
||||
msgid "No - not available on this system.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:74
|
||||
#, c-format
|
||||
msgid "No - disabled at boot.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:77
|
||||
#, c-format
|
||||
msgid "Maybe - policy interface not available.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:81
|
||||
#, c-format
|
||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../aa_enabled.c:84
|
||||
#, c-format
|
||||
msgid "Error - '%s'\n"
|
||||
msgstr ""
|
@@ -8,7 +8,7 @@ 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"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -22,7 +22,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"%s: [options]\n"
|
||||
" options:\n"
|
||||
" -x | --exclusive Shared interfaces must be available\n"
|
||||
" -x | --exclusive Shared interfaces must be availabe\n"
|
||||
" -q | --quiet Don't print out any messages\n"
|
||||
" -h | --help Print help\n"
|
||||
msgstr ""
|
||||
|
@@ -8,7 +8,7 @@ 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"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@@ -8,7 +8,7 @@ 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"
|
||||
"POT-Creation-Date: 2020-10-14 03:58-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@@ -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 creator */
|
||||
aa_create_dir_config, /* dir config creater */
|
||||
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 property. This can be accomplished by setting the JAVA_OPTS
|
||||
environment variable, export JAVA_OPTS=-Djava.library.path, or set 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
|
||||
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 by the changeHatValve during
|
||||
prompt you create discrete hats as requested byt the changeHatValve during
|
||||
tomcat execution.
|
||||
|
||||
1. Create a basic profile for the tomcat server.
|
||||
|
||||
- Run the command "genprof PATH_TO_CATALINA.SH"
|
||||
- In a separate window start tomcat and then stop tomcat
|
||||
- In a seperate 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 separate window start tomcat and then exercise your web application
|
||||
- In a seperate 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 processing is complete the valve will change_hat back to the
|
||||
When the request processng 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 property. This can be accomplished by setting the JAVA_OPTS
|
||||
environment variable, export JAVA_OPTS=-Djava.library.path, or set 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
|
||||
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 by the changeHatValve during
|
||||
prompt you create discrete hats as requested byt the changeHatValve during
|
||||
tomcat execution.
|
||||
|
||||
1. Create a basic profile for the tomcat server.
|
||||
|
||||
- Run the command "genprof PATH_TO_CATALINA.SH"
|
||||
- In a separate window start tomcat and then stop tomcat
|
||||
- In a seperate 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 separate window start tomcat and then exercise your web application
|
||||
- In a seperate 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 processing is complete the valve will change_hat back to the
|
||||
When the request processng is complete the valve will change_hat back to the
|
||||
parent context.
|
||||
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
3.0.98
|
||||
3.0.4
|
||||
|
@@ -6,7 +6,7 @@
|
||||
# the source tree
|
||||
# =====================
|
||||
|
||||
# It doesn't make sense for AppArmor to mediate PF_UNIX, filter it out. Search
|
||||
# It doesn't make sence 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_".
|
||||
|
||||
|
@@ -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 overlaid to create the policy cache.
|
||||
of directories that are being overlayed to create the policy cache.
|
||||
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
@@ -194,8 +194,6 @@ static int features_dir_cb(int dirfd, const char *name, struct stat *st,
|
||||
if (features_snprintf(fst, "%s {", name) == -1)
|
||||
return -1;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
ssize_t len;
|
||||
size_t remaining;
|
||||
@@ -666,7 +664,7 @@ static const char *features_lookup(aa_features *features, const char *str)
|
||||
|
||||
/* Empty strings are not accepted. Neither are leading '/' chars. */
|
||||
if (!str || str[0] == '/')
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
/**
|
||||
* Break @str into an array of components. For example,
|
||||
@@ -679,7 +677,7 @@ static const char *features_lookup(aa_features *features, const char *str)
|
||||
|
||||
/* At least one valid token is required */
|
||||
if (!num_components)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
/* Ensure that all components are valid and found */
|
||||
for (i = 0; i < num_components; i++) {
|
||||
|
@@ -378,7 +378,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 assuming capname is
|
||||
* autotools Makefile. For now just drop assumming capname is
|
||||
* present which it should be with current kernels */
|
||||
}
|
||||
| TOK_KEY_CAPNAME TOK_EQUALS TOK_QUOTED_STRING
|
||||
@@ -386,7 +386,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 occurred unpacking
|
||||
{ /* offset is used for reporting where an error occured unpacking
|
||||
* loaded policy. We can just drop this currently
|
||||
*/
|
||||
}
|
||||
|
@@ -1319,9 +1319,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 simulate this
|
||||
/* The kernel does the query in two parts we could similate this
|
||||
* doing the following, however as long as policy is compiled
|
||||
* correctly this isn't required, and it requires an extra round
|
||||
* correctly this isn't requied, and it requires and 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 interface to write to
|
||||
* @fd: kernel iterface 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 errno set and *@kernel_interface
|
||||
* Returns: 0 on success, -1 on error with errnot set and *@kernel_interface
|
||||
* pointing to NULL
|
||||
*/
|
||||
int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
|
@@ -45,8 +45,6 @@ struct aa_policy_cache {
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
/* remove regular files */
|
||||
return unlinkat(dirfd, path, 0);
|
||||
|
@@ -63,7 +63,7 @@ struct ignored_suffix_t {
|
||||
};
|
||||
|
||||
static struct ignored_suffix_t ignored_suffixes[] = {
|
||||
/* Debian packaging files, which are in flux during install
|
||||
/* Debian packging 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;
|
||||
}
|
||||
|
||||
/* automatically free allocated variables tagged with autofree on fn exit */
|
||||
/* automaticly free allocated variables tagged with autofree on fn exit */
|
||||
void _aa_autofree(void *p)
|
||||
{
|
||||
void **_p = (void**)p;
|
||||
@@ -452,8 +452,7 @@ int _aa_overlaydirat_for_each(int dirfd[], int n, void *data,
|
||||
*
|
||||
* The cb function is called with the DIR in use and the name of the
|
||||
* file in that directory. If the file is to be opened it should
|
||||
* use the openat, fstatat, and related fns. If the file is a symlink
|
||||
* _aa_dirat_for_each currently tries to traverse it for the caller
|
||||
* use the openat, fstatat, and related fns.
|
||||
*
|
||||
* Returns: 0 on success, else -1 and errno is set to the error code
|
||||
*/
|
||||
@@ -486,34 +485,14 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
autofree struct dirent *dir = namelist[i];
|
||||
struct stat my_stat;
|
||||
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, AT_SYMLINK_NOFOLLOW)) {
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
/* currently none of the callers handle symlinks, and this
|
||||
* same basic code was applied to each. So for this patch
|
||||
* just drop it here.
|
||||
*
|
||||
* Going forward we need to start handling symlinks as
|
||||
* they have meaning.
|
||||
* In the case of
|
||||
* cache: they act as a place holder for files that have been
|
||||
* combined into a single binary. This enables the
|
||||
* file based cache lookup time find that relation
|
||||
* and dedup, so multiple loads aren't done.
|
||||
* profiles: just a profile in an alternate location, but
|
||||
* should do dedup detection when doing dir reads
|
||||
* so we don't double process.
|
||||
*/
|
||||
if (S_ISLNK(my_stat.st_mode)) {
|
||||
/* just traverse the symlink */
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
PDEBUG("symlink target stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
# Runs all tests with the extension "multi" for several times.
|
||||
# Each test program <programname>.multi has its own subdirectory
|
||||
# Runs all tests with the extention "multi" for several times.
|
||||
# Each testprogram <programname>.multi has an own subdirectory
|
||||
# <programmname> in which several testcases are defined for this program
|
||||
# Each testcase has 3 files:
|
||||
#
|
||||
|
@@ -60,7 +60,7 @@ WARNINGS = -Wall
|
||||
CXX_WARNINGS = ${WARNINGS} ${EXTRA_WARNINGS}
|
||||
CPP_WARNINGS =
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -g -O2 -pipe -flto-partition=none
|
||||
CFLAGS = -g -O2 -pipe
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -pg -D DEBUG
|
||||
@@ -419,7 +419,6 @@ install-indep: indep
|
||||
install -m 755 -d ${DESTDIR}/var/lib/apparmor
|
||||
install -m 755 -d $(APPARMOR_BIN_PREFIX)
|
||||
install -m 755 rc.apparmor.functions $(APPARMOR_BIN_PREFIX)
|
||||
install -m 755 profile-load $(APPARMOR_BIN_PREFIX)
|
||||
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
|
||||
$(MAKE) install_manpages DESTDIR=${DESTDIR}
|
||||
|
||||
|
@@ -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 sentinel */
|
||||
{ NULL, false, false, false, local_cond }, /* eol sentinal */
|
||||
};
|
||||
|
||||
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 definition */
|
||||
/* See unix(7) for autobind address definiation */
|
||||
#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 }, /* sentinel */
|
||||
{ NULL, false, false, false, local_cond }, /* sentinal */
|
||||
};
|
||||
|
||||
void unix_rule::move_conditionals(struct cond_entry *conds)
|
||||
@@ -326,9 +326,8 @@ 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;
|
||||
}
|
||||
|
||||
@@ -356,7 +355,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||
/* local label option */
|
||||
if (!write_label(tmp, label))
|
||||
goto fail;
|
||||
/* separator */
|
||||
/* seperator */
|
||||
tmp << "\\x00";
|
||||
|
||||
buf = tmp.str();
|
||||
@@ -377,7 +376,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||
/* local label option */
|
||||
if (!write_label(buffer, label))
|
||||
goto fail;
|
||||
/* separator */
|
||||
/* seperator */
|
||||
buffer << "\\x00";
|
||||
|
||||
/* create already masked off */
|
||||
|
@@ -241,6 +241,9 @@ 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> )
|
||||
@@ -297,9 +300,6 @@ 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' )
|
||||
@@ -1513,10 +1513,9 @@ 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 (AARE)
|
||||
=head2 Globbing
|
||||
|
||||
File resources and other parameters accepting an AARE
|
||||
may be specified with a globbing syntax similar to that
|
||||
File resources may be specified with a globbing syntax similar to that
|
||||
used by popular shells, such as csh(1), bash(1), zsh(1).
|
||||
|
||||
=over 4
|
||||
@@ -1549,12 +1548,6 @@ 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
|
||||
|
@@ -98,62 +98,6 @@ 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
|
||||
@@ -214,12 +158,6 @@ 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.
|
||||
@@ -229,12 +167,6 @@ 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
|
||||
@@ -251,14 +183,6 @@ 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:
|
||||
|
||||
|
@@ -71,13 +71,6 @@ fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
systemd-detect-virt --quiet --container && \
|
||||
! is_container_with_internal_policy; then
|
||||
aa_log_daemon_msg "Not starting AppArmor in container"
|
||||
aa_log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
apparmor_start
|
||||
rc=$?
|
||||
;;
|
||||
@@ -86,13 +79,6 @@ case "$1" in
|
||||
rc=$?
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
systemd-detect-virt --quiet --container && \
|
||||
! is_container_with_internal_policy; then
|
||||
aa_log_daemon_msg "Not starting AppArmor in container"
|
||||
aa_log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
apparmor_restart
|
||||
rc=$?
|
||||
;;
|
||||
|
@@ -396,23 +396,6 @@ 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
|
||||
|
@@ -19,29 +19,8 @@
|
||||
#ifndef __AA_CAPABILITY_H
|
||||
#define __AA_CAPABILITY_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <linux/capability.h>
|
||||
|
||||
#define NO_BACKMAP_CAP 0xff
|
||||
|
||||
|
||||
#ifndef CAP_AUDIT_WRITE
|
||||
#define CAP_AUDIT_WRITE 29
|
||||
#endif
|
||||
#ifndef CAP_AUDIT_CONTROL
|
||||
#define CAP_AUDIT_CONTROL 30
|
||||
#endif
|
||||
#ifndef CAP_SETFCAP
|
||||
#define CAP_SETFCAP 31
|
||||
#endif
|
||||
#ifndef CAP_MAC_OVERRIDE
|
||||
#define CAP_MAC_OVERRIDE 32
|
||||
#endif
|
||||
|
||||
#ifndef CAP_AUDIT_READ
|
||||
#define CAP_AUDIT_READ 37
|
||||
#endif
|
||||
|
||||
#ifndef CAP_PERFMON
|
||||
#define CAP_PERFMON 38
|
||||
#endif
|
||||
|
@@ -183,7 +183,7 @@ int strn_escseq(const char **pos, const char *chrs, size_t n)
|
||||
if (strchr(chrs, c))
|
||||
return c;
|
||||
|
||||
/* unsupported escape sequence, backup to return that char */
|
||||
/* unsupported escap sequence, backup to return that char */
|
||||
pos--;
|
||||
return -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 state machine.
|
||||
rules to a runtime ready statemachine.
|
||||
|
||||
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 instead of 0xF13C57B1 though, which is meant to
|
||||
is set to 0x1B5E783D insted 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 compression influences the parse
|
||||
for states that are similar. The amount of compresion 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_separator(Node *l, Node *r)
|
||||
static Node *cat_with_null_seperator(Node *l, Node *r)
|
||||
{
|
||||
return new CatNode(new CatNode(l, new CharNode(0)), r);
|
||||
}
|
||||
|
||||
static Node *cat_with_oob_separator(Node *l, Node *r)
|
||||
static Node *cat_with_oob_seperator(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_separator(tree, subtree);
|
||||
tree = cat_with_oob_seperator(tree, subtree);
|
||||
else
|
||||
tree = cat_with_null_separator(tree, subtree);
|
||||
tree = cat_with_null_seperator(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 ((*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))
|
||||
if (dynamic_cast<StarNode *>(*i) ||
|
||||
dynamic_cast<PlusNode *>(*i) ||
|
||||
dynamic_cast<AnyCharNode *>(*i) ||
|
||||
dynamic_cast<CharSetNode *>(*i) ||
|
||||
dynamic_cast<NotCharSetNode *>(*i))
|
||||
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 *separator;
|
||||
const char *seperator;
|
||||
if (oob)
|
||||
separator = "\\-x01";
|
||||
seperator = "\\-x01";
|
||||
else
|
||||
separator = "\\x00";
|
||||
seperator = "\\x00";
|
||||
cerr << "rule: ";
|
||||
cerr << rulev[0];
|
||||
for (int i = 1; i < count; i++) {
|
||||
cerr << separator;
|
||||
cerr << seperator;
|
||||
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 the state set during subset
|
||||
* results in fewer important nodes in a 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 cancellations. Normalization
|
||||
* Normalize the regex parse tree for factoring and cancelations. 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 guaranteed to not affect the
|
||||
* Normalization of a child node is guarenteed to not affect the
|
||||
* normalization of the parent.
|
||||
*
|
||||
* For cat nodes the depth first traverse order is guaranteed to be
|
||||
* For cat nodes the depth first traverse order is guarenteed 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 (c->is_type(NODE_TYPE_TWOCHILD) &&
|
||||
if (dynamic_cast<TwoChildNode *>(c) &&
|
||||
&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 (child[dir]->is_type(NODE_TYPE_CAT)) {
|
||||
} else if (dynamic_cast<CatNode *>(child[dir])) {
|
||||
// (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 (child[dir]->is_type(NODE_TYPE_ALT)) {
|
||||
} else if (dynamic_cast<AltNode *>(child[dir])) {
|
||||
// (a | b) | c -> a | (b | c)
|
||||
rotate_node(this, dir);
|
||||
} else if (child[dir]->is_type(NODE_TYPE_CHARSET) &&
|
||||
child[!dir]->is_type(NODE_TYPE_CHAR)) {
|
||||
} else if (dynamic_cast<CharSetNode *>(child[dir]) &&
|
||||
dynamic_cast<CharNode *>(child[!dir])) {
|
||||
// [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 (!t->is_type(NODE_TYPE_ALT))
|
||||
if (!dynamic_cast<AltNode *>(t))
|
||||
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 (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
||||
dynamic_cast<CatNode *>(t->child[!dir]) &&
|
||||
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 (t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||
if (dynamic_cast<CatNode *>(t->child[!dir]) &&
|
||||
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 (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
||||
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 (t->is_type(NODE_TYPE_CAT) && &epsnode == t->child[!dir]) {
|
||||
if (dynamic_cast<CatNode *>(t) && &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 (t->is_type(NODE_TYPE_IMPORTANT))
|
||||
if (dynamic_cast<ImportantNode *>(t))
|
||||
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 (!t->is_type(NODE_TYPE_ALT) ||
|
||||
!t->child[!dir]->is_type(NODE_TYPE_ALT))
|
||||
if (!dynamic_cast<AltNode *>(t) ||
|
||||
!dynamic_cast<AltNode *>(t->child[!dir]))
|
||||
break;
|
||||
|
||||
// a | (a | b) -> (a | b)
|
||||
// a | (b | (c | a)) -> (b | (c | a))
|
||||
Node *p = t;
|
||||
Node *i = t->child[!dir];
|
||||
for (; i->is_type(NODE_TYPE_ALT); p = i, i = i->child[!dir]) {
|
||||
for (; dynamic_cast<AltNode *>(i); 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 (subject->is_type(NODE_TYPE_CAT))
|
||||
if (dynamic_cast<CatNode *>(subject))
|
||||
a = subject->child[dir];
|
||||
|
||||
for (pp = p = t, i = t->child[!dir];
|
||||
i->is_type(NODE_TYPE_ALT);) {
|
||||
if ((i->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||
dynamic_cast<AltNode *>(i);) {
|
||||
if ((dynamic_cast<CatNode *>(i->child[dir]) &&
|
||||
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 (subject->is_type(NODE_TYPE_CAT))
|
||||
if (dynamic_cast<CatNode *>(subject))
|
||||
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 ((i->is_type(NODE_TYPE_CAT) &&
|
||||
if ((dynamic_cast<CatNode *>(i) &&
|
||||
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 (!t->is_type(NODE_TYPE_IMPORTANT)) {
|
||||
if (!dynamic_cast<ImportantNode *>(t)) {
|
||||
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 (t->is_type(NODE_TYPE_ALT)) {
|
||||
if (dynamic_cast<AltNode *>(t)) {
|
||||
counts->alt++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
count_tree_nodes(t->child[1], counts);
|
||||
} else if (t->is_type(NODE_TYPE_CAT)) {
|
||||
} else if (dynamic_cast<CatNode *>(t)) {
|
||||
counts->cat++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
count_tree_nodes(t->child[1], counts);
|
||||
} else if (t->is_type(NODE_TYPE_PLUS)) {
|
||||
} else if (dynamic_cast<PlusNode *>(t)) {
|
||||
counts->plus++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (t->is_type(NODE_TYPE_STAR)) {
|
||||
} else if (dynamic_cast<StarNode *>(t)) {
|
||||
counts->star++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (t->is_type(NODE_TYPE_OPTIONAL)) {
|
||||
} else if (dynamic_cast<OptionalNode *>(t)) {
|
||||
counts->optional++;
|
||||
count_tree_nodes(t->child[0], counts);
|
||||
} else if (t->is_type(NODE_TYPE_CHAR)) {
|
||||
} else if (dynamic_cast<CharNode *>(t)) {
|
||||
counts->charnode++;
|
||||
} else if (t->is_type(NODE_TYPE_ANYCHAR)) {
|
||||
} else if (dynamic_cast<AnyCharNode *>(t)) {
|
||||
counts->any++;
|
||||
} else if (t->is_type(NODE_TYPE_CHARSET)) {
|
||||
} else if (dynamic_cast<CharSetNode *>(t)) {
|
||||
counts->charset++;
|
||||
} else if (t->is_type(NODE_TYPE_NOTCHARSET)) {
|
||||
} else if (dynamic_cast<NotCharSetNode *>(t)) {
|
||||
counts->notcharset++;
|
||||
}
|
||||
}
|
||||
@@ -635,8 +635,7 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
||||
void flip_tree(Node *node)
|
||||
{
|
||||
for (depth_first_traversal i(node); i; i++) {
|
||||
if ((*i)->is_type(NODE_TYPE_CAT)) {
|
||||
CatNode *cat = static_cast<CatNode *>(*i);
|
||||
if (CatNode *cat = dynamic_cast<CatNode *>(*i)) {
|
||||
swap(cat->child[0], cat->child[1]);
|
||||
}
|
||||
}
|
||||
|
@@ -222,43 +222,16 @@ 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), type_flags(NODE_TYPE_NODE), label(0)
|
||||
{
|
||||
child[0] = child[1] = 0;
|
||||
}
|
||||
Node(Node *left): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
|
||||
Node(): nullable(false), label(0) { child[0] = child[1] = 0; }
|
||||
Node(Node *left): nullable(false), label(0)
|
||||
{
|
||||
child[0] = left;
|
||||
child[1] = 0;
|
||||
}
|
||||
Node(Node *left, Node *right): nullable(false),
|
||||
type_flags(NODE_TYPE_NODE), label(0)
|
||||
Node(Node *left, Node *right): nullable(false), label(0)
|
||||
{
|
||||
child[0] = left;
|
||||
child[1] = right;
|
||||
@@ -329,13 +302,6 @@ 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 */
|
||||
/**
|
||||
@@ -349,34 +315,25 @@ public:
|
||||
|
||||
class InnerNode: public Node {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
InnerNode(): Node() { };
|
||||
InnerNode(Node *left): Node(left) { };
|
||||
InnerNode(Node *left, Node *right): Node(left, right) { };
|
||||
};
|
||||
|
||||
class OneChildNode: public InnerNode {
|
||||
public:
|
||||
OneChildNode(Node *left): InnerNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_ONECHILD;
|
||||
};
|
||||
OneChildNode(Node *left): InnerNode(left) { };
|
||||
};
|
||||
|
||||
class TwoChildNode: public InnerNode {
|
||||
public:
|
||||
TwoChildNode(Node *left, Node *right): InnerNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_TWOCHILD;
|
||||
};
|
||||
TwoChildNode(Node *left, Node *right): InnerNode(left, right) { };
|
||||
virtual int normalize_eps(int dir);
|
||||
};
|
||||
|
||||
class LeafNode: public Node {
|
||||
public:
|
||||
LeafNode(): Node() { type_flags |= NODE_TYPE_LEAF; };
|
||||
LeafNode(): Node() { };
|
||||
virtual void normalize(int dir __attribute__((unused))) { return; }
|
||||
};
|
||||
|
||||
@@ -385,7 +342,6 @@ class EpsNode: public LeafNode {
|
||||
public:
|
||||
EpsNode(): LeafNode()
|
||||
{
|
||||
type_flags |= NODE_TYPE_EPS;
|
||||
nullable = true;
|
||||
label = 0;
|
||||
}
|
||||
@@ -400,7 +356,7 @@ public:
|
||||
void compute_lastpos() { }
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_EPS))
|
||||
if (dynamic_cast<EpsNode *>(other))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -417,7 +373,7 @@ public:
|
||||
*/
|
||||
class ImportantNode: public LeafNode {
|
||||
public:
|
||||
ImportantNode(): LeafNode() { type_flags |= NODE_TYPE_IMPORTANT; }
|
||||
ImportantNode(): LeafNode() { }
|
||||
void compute_firstpos() { firstpos.insert(this); }
|
||||
void compute_lastpos() { lastpos.insert(this); }
|
||||
virtual void follow(Cases &cases) = 0;
|
||||
@@ -430,7 +386,7 @@ public:
|
||||
*/
|
||||
class CNode: public ImportantNode {
|
||||
public:
|
||||
CNode(): ImportantNode() { type_flags |= NODE_TYPE_C; }
|
||||
CNode(): ImportantNode() { }
|
||||
int is_accept(void) { return false; }
|
||||
int is_postprocess(void) { return false; }
|
||||
};
|
||||
@@ -438,7 +394,7 @@ public:
|
||||
/* Match one specific character (/c/). */
|
||||
class CharNode: public CNode {
|
||||
public:
|
||||
CharNode(transchar c): c(c) { type_flags |= NODE_TYPE_CHAR; }
|
||||
CharNode(transchar c): c(c) { }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
NodeSet **x = &cases.cases[c];
|
||||
@@ -452,8 +408,8 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_CHAR)) {
|
||||
CharNode *o = static_cast<CharNode *>(other);
|
||||
CharNode *o = dynamic_cast<CharNode *>(other);
|
||||
if (o) {
|
||||
return c == o->c;
|
||||
}
|
||||
return 0;
|
||||
@@ -483,10 +439,7 @@ public:
|
||||
/* Match a set of characters (/[abc]/). */
|
||||
class CharSetNode: public CNode {
|
||||
public:
|
||||
CharSetNode(Chars &chars): chars(chars)
|
||||
{
|
||||
type_flags |= NODE_TYPE_CHARSET;
|
||||
}
|
||||
CharSetNode(Chars &chars): chars(chars) { }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
|
||||
@@ -502,11 +455,8 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (!other->is_type(NODE_TYPE_CHARSET))
|
||||
return 0;
|
||||
|
||||
CharSetNode *o = static_cast<CharSetNode *>(other);
|
||||
if (chars.size() != o->chars.size())
|
||||
CharSetNode *o = dynamic_cast<CharSetNode *>(other);
|
||||
if (!o || chars.size() != o->chars.size())
|
||||
return 0;
|
||||
|
||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||
@@ -548,10 +498,7 @@ public:
|
||||
/* Match all except one character (/[^abc]/). */
|
||||
class NotCharSetNode: public CNode {
|
||||
public:
|
||||
NotCharSetNode(Chars &chars): chars(chars)
|
||||
{
|
||||
type_flags |= NODE_TYPE_NOTCHARSET;
|
||||
}
|
||||
NotCharSetNode(Chars &chars): chars(chars) { }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
if (!cases.otherwise)
|
||||
@@ -575,11 +522,8 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (!other->is_type(NODE_TYPE_NOTCHARSET))
|
||||
return 0;
|
||||
|
||||
NotCharSetNode *o = static_cast<NotCharSetNode *>(other);
|
||||
if (chars.size() != o->chars.size())
|
||||
NotCharSetNode *o = dynamic_cast<NotCharSetNode *>(other);
|
||||
if (!o || chars.size() != o->chars.size())
|
||||
return 0;
|
||||
|
||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||
@@ -599,9 +543,9 @@ public:
|
||||
|
||||
int min_match_len()
|
||||
{
|
||||
/* Inverse match does not match any oob char at this time
|
||||
* so only count characters
|
||||
*/
|
||||
if (contains_oob()) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -621,7 +565,7 @@ public:
|
||||
/* Match any character (/./). */
|
||||
class AnyCharNode: public CNode {
|
||||
public:
|
||||
AnyCharNode() { type_flags |= NODE_TYPE_ANYCHAR; }
|
||||
AnyCharNode() { }
|
||||
void follow(Cases &cases)
|
||||
{
|
||||
if (!cases.otherwise)
|
||||
@@ -635,7 +579,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_ANYCHAR))
|
||||
if (dynamic_cast<AnyCharNode *>(other))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -645,11 +589,7 @@ public:
|
||||
/* Match a node zero or more times. (This is a unary operator.) */
|
||||
class StarNode: public OneChildNode {
|
||||
public:
|
||||
StarNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_STAR;
|
||||
nullable = true;
|
||||
}
|
||||
StarNode(Node *left): OneChildNode(left) { nullable = true; }
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||
void compute_followpos()
|
||||
@@ -661,7 +601,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_STAR))
|
||||
if (dynamic_cast<StarNode *>(other))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -678,16 +618,12 @@ public:
|
||||
/* Match a node zero or one times. */
|
||||
class OptionalNode: public OneChildNode {
|
||||
public:
|
||||
OptionalNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_OPTIONAL;
|
||||
nullable = true;
|
||||
}
|
||||
OptionalNode(Node *left): OneChildNode(left) { nullable = true; }
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_OPTIONAL))
|
||||
if (dynamic_cast<OptionalNode *>(other))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -702,9 +638,7 @@ public:
|
||||
/* Match a node one or more times. (This is a unary operator.) */
|
||||
class PlusNode: public OneChildNode {
|
||||
public:
|
||||
PlusNode(Node *left): OneChildNode(left)
|
||||
{
|
||||
type_flags |= NODE_TYPE_PLUS;
|
||||
PlusNode(Node *left): OneChildNode(left) {
|
||||
}
|
||||
void compute_nullable() { nullable = child[0]->nullable; }
|
||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||
@@ -717,7 +651,7 @@ public:
|
||||
}
|
||||
}
|
||||
int eq(Node *other) {
|
||||
if (other->is_type(NODE_TYPE_PLUS))
|
||||
if (dynamic_cast<PlusNode *>(other))
|
||||
return child[0]->eq(other->child[0]);
|
||||
return 0;
|
||||
}
|
||||
@@ -733,10 +667,7 @@ public:
|
||||
/* Match a pair of consecutive nodes. */
|
||||
class CatNode: public TwoChildNode {
|
||||
public:
|
||||
CatNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_CAT;
|
||||
}
|
||||
CatNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
||||
void compute_nullable()
|
||||
{
|
||||
nullable = child[0]->nullable && child[1]->nullable;
|
||||
@@ -764,7 +695,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_CAT)) {
|
||||
if (dynamic_cast<CatNode *>(other)) {
|
||||
if (!child[0]->eq(other->child[0]))
|
||||
return 0;
|
||||
return child[1]->eq(other->child[1]);
|
||||
@@ -799,10 +730,7 @@ public:
|
||||
/* Match one of two alternative nodes. */
|
||||
class AltNode: public TwoChildNode {
|
||||
public:
|
||||
AltNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||
{
|
||||
type_flags |= NODE_TYPE_ALT;
|
||||
}
|
||||
AltNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
||||
void compute_nullable()
|
||||
{
|
||||
nullable = child[0]->nullable || child[1]->nullable;
|
||||
@@ -817,7 +745,7 @@ public:
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
if (other->is_type(NODE_TYPE_ALT)) {
|
||||
if (dynamic_cast<AltNode *>(other)) {
|
||||
if (!child[0]->eq(other->child[0]))
|
||||
return 0;
|
||||
return child[1]->eq(other->child[1]);
|
||||
@@ -852,10 +780,7 @@ public:
|
||||
|
||||
class SharedNode: public ImportantNode {
|
||||
public:
|
||||
SharedNode()
|
||||
{
|
||||
type_flags |= NODE_TYPE_SHARED;
|
||||
}
|
||||
SharedNode() { }
|
||||
void release(void)
|
||||
{
|
||||
/* don't delete SharedNodes via release as they are shared, and
|
||||
@@ -878,17 +803,14 @@ public:
|
||||
*/
|
||||
class AcceptNode: public SharedNode {
|
||||
public:
|
||||
AcceptNode() { type_flags |= NODE_TYPE_ACCEPT; }
|
||||
AcceptNode() { }
|
||||
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)
|
||||
{
|
||||
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||
}
|
||||
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
|
||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << flag << '>'; }
|
||||
|
||||
uint32_t flag;
|
||||
@@ -897,18 +819,12 @@ public:
|
||||
|
||||
class ExactMatchFlag: public MatchFlag {
|
||||
public:
|
||||
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit)
|
||||
{
|
||||
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
|
||||
}
|
||||
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
|
||||
};
|
||||
|
||||
class DenyMatchFlag: public MatchFlag {
|
||||
public:
|
||||
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet)
|
||||
{
|
||||
type_flags |= NODE_TYPE_DENYMATCHFLAG;
|
||||
}
|
||||
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
|
||||
};
|
||||
|
||||
/* Traverse the syntax tree depth-first in an iterator-like manner. */
|
||||
@@ -917,7 +833,7 @@ class depth_first_traversal {
|
||||
void push_left(Node *node) {
|
||||
pos.push(node);
|
||||
|
||||
while (node->is_type(NODE_TYPE_INNER)) {
|
||||
while (dynamic_cast<InnerNode *>(node)) {
|
||||
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
|
||||
* minimum of - 1 non accepting, and 1 accepting
|
||||
* minimium 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 truly minimized dfa but comes close, and can speedup
|
||||
* obtaining a truely 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 partition have transitions
|
||||
* At this point all states with in a partion 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 representative states for their partition, they
|
||||
* that are not the representive 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 controlling dfa creation
|
||||
* @dfa_flags: flags controling 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 guarantee this the ordering and distance calculation is done in the
|
||||
* To guarentee 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,18 +1352,17 @@ int accept_perms(NodeSet *state, perms_t &perms, bool filedfa)
|
||||
return error;
|
||||
|
||||
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
||||
if (!(*i)->is_type(NODE_TYPE_MATCHFLAG))
|
||||
MatchFlag *match;
|
||||
if (!(match = dynamic_cast<MatchFlag *>(*i)))
|
||||
continue;
|
||||
|
||||
MatchFlag *match = static_cast<MatchFlag *>(*i);
|
||||
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
|
||||
if (dynamic_cast<ExactMatchFlag *>(match)) {
|
||||
/* 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 (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
||||
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
|
||||
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
|
||||
* partition: Is a temporary work variable used during dfa minimization.
|
||||
* parition: 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 grammar Perl regexs use, and rediscovering that
|
||||
which precise grammer 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 filesystem types
|
||||
* add semantic checking of options against specified filesytem 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: unknown mount perm";
|
||||
os << "error: unknonwn 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 overridden by options passed on the command line.
|
||||
# can then be overriden 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 Optimizations. Multiple Optimizations can be set, one per line ####
|
||||
#### Set Optimizaions. Multiple Optimizations can be set, one per line ####
|
||||
# For supported optimizations see
|
||||
# apparmor_parser --help=O
|
||||
|
||||
|
@@ -376,6 +376,7 @@ 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 occurrence of name in the
|
||||
#include <name> which searches for the first occurance 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 overridden
|
||||
/* default base directory is /etc/apparmor.d, it can be overriden
|
||||
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 separated
|
||||
* with 0, so that the namespace and name are \0 seperated
|
||||
*/
|
||||
if (*table[i] == ':') {
|
||||
char *tmp = table[i] + 1;
|
||||
|
@@ -141,8 +141,6 @@ static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
if (!(yyin = fopen(path,"r")))
|
||||
yyerror(_("Could not open '%s' in '%s'"), path, d->filename);
|
||||
|
@@ -85,13 +85,10 @@ int mru_skip_cache = 1;
|
||||
/* for jobs_max and jobs
|
||||
* LONG_MAX : no limit
|
||||
* LONG_MIN : auto = detect system processing cores
|
||||
* -n : multiply by the number of CPUs to compile policy
|
||||
* n : use that number of processes/threads to compile policy
|
||||
*/
|
||||
#define JOBS_AUTO LONG_MIN
|
||||
#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_max = -8; /* 8 * cpus */
|
||||
long jobs = JOBS_AUTO; /* default: number of processor cores */
|
||||
long njobs = 0;
|
||||
long jobs_scale = 0; /* number of chance to resample online
|
||||
@@ -133,7 +130,6 @@ 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:";
|
||||
@@ -188,7 +184,6 @@ 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},
|
||||
};
|
||||
@@ -419,19 +414,6 @@ 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)
|
||||
@@ -452,7 +434,7 @@ int arg_pass(int c) {
|
||||
return LATE_ARG;
|
||||
}
|
||||
|
||||
/* process a single argument from getopt_long
|
||||
/* process a single argment from getopt_long
|
||||
* Returns: 1 if an action arg, else 0
|
||||
*/
|
||||
#define DUMP_HEADER " variables \tDump variables\n" \
|
||||
@@ -769,21 +751,6 @@ 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);
|
||||
@@ -1296,7 +1263,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 may be cleaned up at exit
|
||||
* atm not all resources maybe cleanedup at exit
|
||||
*/
|
||||
int last_error = 0;
|
||||
void handle_work_result(int retval)
|
||||
@@ -1324,120 +1291,35 @@ static long compute_jobs(long n, long j)
|
||||
return j;
|
||||
}
|
||||
|
||||
static void setup_parallel_compile(long ncpus, long maxcpus)
|
||||
static void setup_parallel_compile(void)
|
||||
{
|
||||
/* jobs and parallel_max set by default, config or args */
|
||||
/* 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;
|
||||
if (jobs < 0 || jobs == JOBS_AUTO)
|
||||
jobs_scale = 1;
|
||||
jobs = compute_jobs(ncpus, jobs);
|
||||
jobs_max = compute_jobs(maxcpus, jobs_max);
|
||||
jobs = compute_jobs(n, jobs);
|
||||
jobs_max = compute_jobs(maxn, jobs_max);
|
||||
|
||||
if (jobs > jobs_max) {
|
||||
pwarn(WARN_JOBS, "%s: Capping number of jobs to %ld * # of cpus == '%ld'",
|
||||
pwarn(WARN_JOBS, "%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
||||
progname, jobs_max, jobs);
|
||||
jobs = jobs_max;
|
||||
} else if (jobs_scale && jobs < jobs_max)
|
||||
/* the bigger the difference the more sample chances given */
|
||||
jobs_scale = jobs_max + 1 - ncpus;
|
||||
jobs_scale = jobs_max + 1 - n;
|
||||
|
||||
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=%ld", estimated_jobs);
|
||||
} else {
|
||||
long long n = estimated_jobs / ncpus;
|
||||
|
||||
if (n < -DEFAULT_JOBS_MAX) {
|
||||
/* --jobs=cpus*n */
|
||||
jobs = -n;
|
||||
PDEBUG("Auto tune: --jobs=%ld", 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 */
|
||||
@@ -1450,8 +1332,6 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||
autofree char *path = NULL;
|
||||
@@ -1474,8 +1354,6 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||
autofree char *path = NULL;
|
||||
@@ -1545,7 +1423,7 @@ int main(int argc, char *argv[])
|
||||
process_config_file(config_file);
|
||||
optind = process_args(argc, argv);
|
||||
|
||||
auto_tune_parameters();
|
||||
setup_parallel_compile();
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
@@ -1668,7 +1546,7 @@ int main(int argc, char *argv[])
|
||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||
&cb_data, cb))) {
|
||||
last_error = errno;
|
||||
PERROR("There was an error while loading profiles from %s\n",
|
||||
PDEBUG("Failed loading profiles from %s\n",
|
||||
profilename);
|
||||
if (abort_on_error)
|
||||
break;
|
||||
|
@@ -541,7 +541,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
int len;
|
||||
tbuf.clear();
|
||||
/* prepend \x00 to every value. This is
|
||||
* done to separate the existence of the
|
||||
* done to separate the existance of the
|
||||
* xattr from a null value match.
|
||||
*
|
||||
* if an xattr exists, a single \x00 will
|
||||
|
@@ -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 nonexistent boolean variable");
|
||||
MY_TEST(retval < 0, "get nonexistant 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 nonexistent set variable");
|
||||
MY_TEST(retptr == NULL, "get non-existent set variable");
|
||||
|
||||
retptr = get_set_var("abuse");
|
||||
MY_TEST(retptr == NULL, "get set variable that's declared a boolean");
|
||||
|
@@ -44,6 +44,20 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <linux/capability.h>
|
||||
|
||||
#ifndef CAP_AUDIT_WRITE
|
||||
#define CAP_AUDIT_WRITE 29
|
||||
#endif
|
||||
#ifndef CAP_AUDIT_CONTROL
|
||||
#define CAP_AUDIT_CONTROL 30
|
||||
#endif
|
||||
#ifndef CAP_SETFCAP
|
||||
#define CAP_SETFCAP 31
|
||||
#endif
|
||||
#ifndef CAP_MAC_OVERRIDE
|
||||
#define CAP_MAC_OVERRIDE 32
|
||||
#endif
|
||||
|
||||
#define CIDR_32 htonl(0xffffffff)
|
||||
#define CIDR_24 htonl(0xffffff00)
|
||||
|
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||
"POT-Creation-Date: 2020-10-14 03:51-0700\n"
|
||||
"POT-Creation-Date: 2020-10-14 04:04-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@@ -179,7 +179,7 @@ void install_cache(const char *cachetmpname, const char *cachename)
|
||||
}
|
||||
|
||||
if (rename(cachetmpname, cachename) < 0) {
|
||||
pwarn(WARN_CACHE, "Failed to write cache: %s\n", cachename);
|
||||
pwarn(WARN_CACHE, "Warning failed to write cache: %s\n", cachename);
|
||||
unlink(cachetmpname);
|
||||
}
|
||||
else if (show_cache) {
|
||||
|
@@ -36,6 +36,7 @@ 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);
|
||||
|
@@ -1,52 +0,0 @@
|
||||
#!/bin/sh
|
||||
# profile-load
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2010-2015 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical, Ltd.
|
||||
# ----------------------------------------------------------------------
|
||||
#
|
||||
# Helper for loading an AppArmor profile in pre-start scripts.
|
||||
|
||||
[ -z "$1" ] && exit 1 # require a profile name
|
||||
|
||||
. /lib/apparmor/rc.apparmor.functions
|
||||
|
||||
# do not load in a container
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
systemd-detect-virt --quiet --container && \
|
||||
! is_container_with_internal_policy; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -d /rofs/etc/apparmor.d ] && exit 0 # do not load if running liveCD
|
||||
|
||||
profile=/etc/apparmor.d/"$1"
|
||||
[ -e "$profile" ] || exit 0 # skip when missing profile
|
||||
|
||||
module=/sys/module/apparmor
|
||||
[ -d $module ] || exit 0 # do not load without AppArmor in kernel
|
||||
|
||||
[ -x /sbin/apparmor_parser ] || exit 0 # do not load without parser
|
||||
|
||||
aafs=/sys/kernel/security/apparmor
|
||||
[ -d $aafs ] || exit 0 # do not load if unmounted
|
||||
[ -w $aafs/.load ] || exit 1 # fail if cannot load profiles
|
||||
|
||||
params=$module/parameters
|
||||
[ -r $params/enabled ] || exit 0 # do not load if missing
|
||||
read -r enabled < $params/enabled || exit 1 # if this fails, something went wrong
|
||||
[ "$enabled" = "Y" ] || exit 0 # do not load if disabled
|
||||
|
||||
/sbin/apparmor_parser -r -W "$profile" || exit 0 # LP: #1058356
|
117
parser/rc.apparmor.debian
Normal file
117
parser/rc.apparmor.debian
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ----------------------------------------------------------------------
|
||||
# rc.apparmor by Steve Beattie
|
||||
#
|
||||
# /etc/init.d/apparmor
|
||||
#
|
||||
# chkconfig: 2345 01 99
|
||||
# description: AppArmor rc file. This rc script inserts the apparmor \
|
||||
# module and runs the parser on the /etc/apparmor.d/ \
|
||||
# directory.
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: apparmor
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Default-Start: 3 4 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: AppArmor initialization
|
||||
# Description: AppArmor rc file. This rc script inserts the apparmor
|
||||
# module and runs the parser on the /etc/apparmor.d/
|
||||
# directory.
|
||||
### END INIT INFO
|
||||
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
||||
|
||||
aa_action() {
|
||||
STRING=$1
|
||||
shift
|
||||
$*
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ] ; then
|
||||
aa_log_success_msg $"$STRING "
|
||||
else
|
||||
aa_log_failure_msg $"$STRING "
|
||||
fi
|
||||
return $rc
|
||||
}
|
||||
|
||||
aa_log_success_msg() {
|
||||
[ -n "$1" ] && echo -n $1
|
||||
echo ": done."
|
||||
}
|
||||
|
||||
aa_log_warning_msg() {
|
||||
[ -n "$1" ] && echo -n $1
|
||||
echo ": Warning."
|
||||
}
|
||||
|
||||
aa_log_failure_msg() {
|
||||
[ -n "$1" ] && echo -n $1
|
||||
echo ": Failed."
|
||||
}
|
||||
|
||||
aa_log_skipped_msg() {
|
||||
[ -n "$1" ] && echo -n $1
|
||||
echo ": Skipped."
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status|kill}"
|
||||
}
|
||||
|
||||
# source apparmor function library
|
||||
if [ -f "${APPARMOR_FUNCTIONS}" ]; then
|
||||
. ${APPARMOR_FUNCTIONS}
|
||||
else
|
||||
aa_log_failure_msg "Unable to find AppArmor initscript functions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test -x ${PARSER} || exit 0 # by debian policy
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
apparmor_start
|
||||
rc=$?
|
||||
;;
|
||||
stop)
|
||||
apparmor_stop
|
||||
rc=$?
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
apparmor_restart
|
||||
rc=$?
|
||||
;;
|
||||
try-restart)
|
||||
apparmor_try_restart
|
||||
rc=$?
|
||||
;;
|
||||
kill)
|
||||
apparmor_kill
|
||||
rc=$?
|
||||
;;
|
||||
status)
|
||||
apparmor_status
|
||||
rc=$?
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $rc
|
@@ -68,7 +68,7 @@ is_apparmor_present() {
|
||||
# something like `systemd-detect-virt --container`.
|
||||
#
|
||||
# The only known container environments capable of supporting internal policy
|
||||
# are LXD and LXC environments, and Windows Subsystem for Linux.
|
||||
# are LXD and LXC environment.
|
||||
#
|
||||
# Returns 0 if the container environment is capable of having its own internal
|
||||
# policy and non-zero otherwise.
|
||||
@@ -90,12 +90,6 @@ is_container_with_internal_policy() {
|
||||
local ns_stacked
|
||||
local ns_name
|
||||
|
||||
# WSL needs to be detected explicitly
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
[ "$(systemd-detect-virt --container)" = "wsl" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! [ -f "$ns_stacked_path" ] || ! [ -f "$ns_name_path" ]; then
|
||||
return 1
|
||||
fi
|
||||
@@ -117,6 +111,37 @@ is_container_with_internal_policy() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# This set of patterns to skip needs to be kept in sync with
|
||||
# AppArmor.pm::isSkippableFile()
|
||||
# returns 0 if profile should NOT be skipped
|
||||
# returns 1 on verbose skip
|
||||
# returns 2 on silent skip
|
||||
skip_profile() {
|
||||
local profile="$1"
|
||||
if [ "${profile%.rpmnew}" != "$profile" ] || \
|
||||
[ "${profile%.rpmsave}" != "$profile" ] || \
|
||||
[ "${profile%.orig}" != "$profile" ] || \
|
||||
[ "${profile%.rej}" != "$profile" ] || \
|
||||
[ "${profile%\~}" != "$profile" ] ; then
|
||||
return 1
|
||||
fi
|
||||
# Silently ignore the dpkg, pacman, and xbps files
|
||||
if [ "${profile%.dpkg-new}" != "$profile" ] || \
|
||||
[ "${profile%.dpkg-old}" != "$profile" ] || \
|
||||
[ "${profile%.dpkg-dist}" != "$profile" ] || \
|
||||
[ "${profile%.dpkg-bak}" != "$profile" ] || \
|
||||
[ "${profile%.dpkg-remove}" != "$profile" ] || \
|
||||
[ "${profile%.pacsave}" != "$profile" ] || \
|
||||
[ "${profile%.pacnew}" != "$profile" ] ; then
|
||||
return 2
|
||||
fi
|
||||
if echo "$profile" | grep -E -q '^.+\.new-[0-9\.]+_[0-9]+$'; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__parse_profiles_dir() {
|
||||
local parser_cmd="$1"
|
||||
local profile_dir="$2"
|
||||
@@ -132,11 +157,41 @@ __parse_profiles_dir() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
if ! "$PARSER" $PARSER_OPTS "$parser_cmd" -- "$profile_dir"; then
|
||||
status=1
|
||||
aa_log_failure_msg "At least one profile failed to load"
|
||||
fi
|
||||
# Note: the parser automatically skips files that match skip_profile()
|
||||
# when we pass it a directory, but not when we pass it an individual
|
||||
# profile. So we need to use skip_profile only in the latter case,
|
||||
# as long as the parser is in sync' with skip_profile().
|
||||
"$PARSER" $PARSER_OPTS "$parser_cmd" -- "$profile_dir" || {
|
||||
# FIXME: once the parser properly handles broken profiles
|
||||
# (LP: #1377338), remove the following code and the
|
||||
# skip_profile() function. For now, if the parser returns
|
||||
# an error, just run it again separately on each profile.
|
||||
for profile in "$profile_dir"/*; do
|
||||
skip_profile "$profile"
|
||||
skip=$?
|
||||
if [ "$skip" -eq 2 ]; then
|
||||
# Ignore skip status == 2 (silent skip)
|
||||
continue
|
||||
elif [ "$skip" -ne 0 ] ; then
|
||||
aa_log_skipped_msg "$profile"
|
||||
logger -t "AppArmor(init)" -p daemon.warn \
|
||||
"Skipping profile $profile"
|
||||
continue
|
||||
fi
|
||||
if [ ! -f "$profile" ] ; then
|
||||
continue
|
||||
fi
|
||||
printf "%s\0" "$profile"
|
||||
done | \
|
||||
# Use xargs to parallelize calls to the parser over all CPUs
|
||||
xargs -n1 -0r -P "$(getconf _NPROCESSORS_ONLN)" \
|
||||
"$PARSER" $PARSER_OPTS "$parser_cmd" --
|
||||
if [ $? -ne 0 ]; then
|
||||
status=1
|
||||
aa_log_failure_msg "At least one profile failed to load"
|
||||
fi
|
||||
}
|
||||
|
||||
return "$status"
|
||||
}
|
||||
|
||||
@@ -160,6 +215,7 @@ parse_profiles() {
|
||||
# run the parser on all of the apparmor profiles
|
||||
if [ ! -f "$PARSER" ]; then
|
||||
aa_log_failure_msg "AppArmor parser not found"
|
||||
aa_log_action_end 1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -171,6 +227,41 @@ parse_profiles() {
|
||||
return "$STATUS"
|
||||
}
|
||||
|
||||
profiles_names_list() {
|
||||
# run the parser on all of the apparmor profiles
|
||||
if [ ! -f "$PARSER" ]; then
|
||||
aa_log_failure_msg "- AppArmor parser not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for profile_dir in $PROFILE_DIRS; do
|
||||
if [ ! -d "$profile_dir" ]; then
|
||||
aa_log_warning_msg "- Profile directory not found: $profile_dir"
|
||||
continue
|
||||
fi
|
||||
|
||||
for profile in "$profile_dir"/*; do
|
||||
if skip_profile "$profile" && [ -f "$profile" ] ; then
|
||||
LIST_ADD=$("$PARSER" -N "$profile" )
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "$LIST_ADD"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
failstop_system() {
|
||||
level=$(runlevel | cut -d" " -f2)
|
||||
if [ "$level" -ne "1" ] ; then
|
||||
aa_log_failure_msg "- could not start AppArmor. Changing to runlevel 1"
|
||||
telinit 1;
|
||||
return 255;
|
||||
fi
|
||||
aa_log_failure_msg "- could not start AppArmor."
|
||||
return 255
|
||||
}
|
||||
|
||||
is_apparmor_loaded() {
|
||||
if ! is_securityfs_mounted ; then
|
||||
mount_securityfs
|
||||
@@ -218,7 +309,7 @@ apparmor_start() {
|
||||
fi
|
||||
|
||||
# if there is anything in the profiles file don't load
|
||||
if ! read -r _ < "$SFS_MOUNTPOINT/profiles"; then
|
||||
if ! read -r line < "$SFS_MOUNTPOINT/profiles"; then
|
||||
parse_profiles load
|
||||
else
|
||||
aa_log_skipped_msg ": already loaded with profiles."
|
||||
@@ -266,7 +357,7 @@ remove_profiles() {
|
||||
}
|
||||
|
||||
apparmor_stop() {
|
||||
aa_log_daemon_msg "Unloading AppArmor profiles"
|
||||
aa_log_daemon_msg "Unloading AppArmor profiles "
|
||||
remove_profiles
|
||||
rc=$?
|
||||
aa_log_end_msg "$rc"
|
||||
|
125
parser/rc.apparmor.redhat
Normal file
125
parser/rc.apparmor.redhat
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ----------------------------------------------------------------------
|
||||
# rc.apparmor by Steve Beattie
|
||||
#
|
||||
# /etc/init.d/apparmor
|
||||
#
|
||||
# chkconfig: 2345 01 99
|
||||
# description: AppArmor rc file. This rc script inserts the apparmor \
|
||||
# module and runs the parser on the /etc/apparmor.d/ \
|
||||
# directory.
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: apparmor
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Default-Start: 3 4 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: AppArmor initialization
|
||||
# Description: AppArmor rc file. This rc script inserts the apparmor
|
||||
# module and runs the parser on the /etc/apparmor.d/
|
||||
# directory.
|
||||
### END INIT INFO
|
||||
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
||||
|
||||
# source function library
|
||||
if [ -f /etc/init.d/functions ]; then
|
||||
. /etc/init.d/functions
|
||||
elif [ -f /etc/rc.d/init.d/functions ]; then
|
||||
. /etc/rc.d/init.d/functions
|
||||
elif [ -f /lib/lsb/init-functions ]; then
|
||||
. /lib/lsb/init-functions
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status|kill}"
|
||||
}
|
||||
|
||||
aa_log_success_msg() {
|
||||
echo -n "$*"
|
||||
success
|
||||
echo
|
||||
}
|
||||
|
||||
aa_log_warning_msg() {
|
||||
echo -n "$*"
|
||||
warning
|
||||
echo
|
||||
}
|
||||
|
||||
aa_log_skipped_msg() {
|
||||
echo -n "$*"
|
||||
warning
|
||||
echo
|
||||
}
|
||||
|
||||
aa_log_failure_msg() {
|
||||
echo -n "$*"
|
||||
failure
|
||||
echo
|
||||
}
|
||||
|
||||
aa_action() {
|
||||
STRING=$1
|
||||
shift
|
||||
action "${STRING} " "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
# source apparmor function library
|
||||
if [ -f "${APPARMOR_FUNCTIONS}" ]; then
|
||||
. ${APPARMOR_FUNCTIONS}
|
||||
else
|
||||
aa_log_failure_msg "Unable to find AppArmor initscript functions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
apparmor_start
|
||||
rc=$?
|
||||
;;
|
||||
stop)
|
||||
apparmor_stop
|
||||
rc=$?
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
apparmor_restart
|
||||
rc=$?
|
||||
;;
|
||||
try-restart)
|
||||
apparmor_try_restart
|
||||
rc=$?
|
||||
;;
|
||||
kill)
|
||||
apparmor_kill
|
||||
rc=$?
|
||||
;;
|
||||
status)
|
||||
apparmor_status
|
||||
rc=$?
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $rc
|
||||
|
@@ -112,7 +112,7 @@ static const char *const sig_names[MAXMAPPED_SIG + 1] = {
|
||||
"lost",
|
||||
"unused",
|
||||
|
||||
"exists", /* always last existence test mapped to MAXMAPPED_SIG */
|
||||
"exists", /* always last existance 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 accesses. The file handle at a
|
||||
identified by a file handle in successive acesses. 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 declarative language, fully described in
|
||||
AppArmor profiles use a simple declaritive 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
|
||||
|
@@ -17,19 +17,19 @@ endif
|
||||
|
||||
all: tests
|
||||
|
||||
.PHONY: tests error_output gen_dbus gen_xtrans parser_sanity caching minimize equality dirtest valgrind
|
||||
tests: error_output caching minimize equality dirtest parser_sanity
|
||||
.PHONY: tests error_output gen_dbus gen_xtrans parser_sanity caching minimize equality valgrind
|
||||
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.py
|
||||
./gen-xtrans.pl
|
||||
|
||||
$(GEN_TRANS_DIRS):
|
||||
mkdir $@
|
||||
|
||||
gen_dbus: $(GEN_TRANS_DIRS)
|
||||
./gen-dbus.py
|
||||
./gen-dbus.pl
|
||||
|
||||
error_output: $(PARSER)
|
||||
LANG=C ./errors.py -p "$(PARSER)" $(PYTEST_ARG)
|
||||
@@ -46,9 +46,6 @@ minimize: $(PARSER)
|
||||
equality: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./equality.sh
|
||||
|
||||
dirtest: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./dirtest.sh
|
||||
|
||||
valgrind: $(PARSER) gen_xtrans gen_dbus
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER) $(PARSER_ARGS)" -v simple_tests
|
||||
|
||||
|
@@ -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 variable. For example, to run the tests on the system parser,
|
||||
the PARSER veriable. 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 should be ignored.
|
||||
thus are expected testsuite failures and hsould be ignored.
|
||||
|
||||
- #=DISABLED -- skips the test, and marks it as a failed TODO task.
|
||||
Useful if the particular testcase causes the parser to infinite
|
||||
|
@@ -73,13 +73,13 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
self.cmd_prefix = [config.parser, '--config-file=./parser.conf', '--base', self.tmp_dir, '--skip-kernel-load']
|
||||
|
||||
if not self.is_apparmorfs_mounted():
|
||||
self.cmd_prefix.extend(('-M', './features_files/features.all'))
|
||||
self.cmd_prefix += ['-M', './features_files/features.all']
|
||||
|
||||
# Otherwise get_cache_dir() will try to create /var/cache/apparmor
|
||||
# and will fail when the test suite is run as non-root.
|
||||
self.cmd_prefix.extend((
|
||||
self.cmd_prefix += [
|
||||
'--cache-loc', os.path.join(self.tmp_dir, 'cache')
|
||||
))
|
||||
]
|
||||
|
||||
# create directory for cached blobs
|
||||
# NOTE: get_cache_dir() requires cmd_prefix to be fully initialized
|
||||
@@ -98,8 +98,7 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
shutil.rmtree(self.tmp_dir)
|
||||
|
||||
def get_cache_dir(self, create=False):
|
||||
cmd = [config.parser, '--print-cache-dir']
|
||||
cmd.extend(self.cmd_prefix)
|
||||
cmd = [config.parser, '--print-cache-dir'] + self.cmd_prefix
|
||||
rc, report = self.run_cmd(cmd)
|
||||
if rc != 0:
|
||||
if "unrecognized option '--print-cache-dir'" not in report:
|
||||
@@ -154,7 +153,7 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
||||
'''test profiles are not cached by default'''
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '-r', self.profile))
|
||||
cmd.extend(['-q', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE), expected=False)
|
||||
|
||||
@@ -162,7 +161,7 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
||||
'''test profiles are not cached with --skip-cache'''
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '--write-cache', '--skip-cache', '-r', self.profile))
|
||||
cmd.extend(['-q', '--write-cache', '--skip-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE), expected=False)
|
||||
|
||||
@@ -170,7 +169,7 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
||||
'''test profiles are cached when requested'''
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE))
|
||||
|
||||
@@ -178,7 +177,7 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
||||
'''test features file is written when caching'''
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE))
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, '.features'))
|
||||
@@ -189,7 +188,7 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
||||
self.require_apparmorfs()
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE))
|
||||
self.assert_path_exists(os.path.join(self.cache_dir, '.features'))
|
||||
@@ -207,7 +206,7 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
|
||||
self.unused_cache_loc = self.cache_dir
|
||||
self.cmd_prefix.extend(('--cache-loc', alt_cache_loc))
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir()
|
||||
|
||||
def tearDown(self):
|
||||
@@ -254,7 +253,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
def _generate_cache_file(self):
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-q', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
self.assert_path_exists(self.cache_file)
|
||||
|
||||
@@ -283,7 +282,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
self._generate_cache_file()
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', self.profile))
|
||||
cmd.extend(['-v', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Cached reload succeeded')
|
||||
|
||||
def test_cache_not_loaded_when_skip_arg(self):
|
||||
@@ -292,7 +291,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
self._generate_cache_file()
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--skip-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--skip-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
def test_cache_not_loaded_when_skip_read_arg(self):
|
||||
@@ -301,7 +300,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
self._generate_cache_file()
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--skip-read-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--skip-read-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
def test_cache_not_loaded_when_features_differ(self):
|
||||
@@ -312,7 +311,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', self.profile))
|
||||
cmd.extend(['-v', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
def test_cache_writing_does_not_overwrite_features_when_features_differ(self):
|
||||
@@ -323,7 +322,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--write-cache', '--skip-bad-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--write-cache', '--skip-bad-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(features_file)
|
||||
# ensure that the features does *not* match the current features set
|
||||
@@ -335,7 +334,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--write-cache', '--skip-bad-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--write-cache', '--skip-bad-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(self.cache_file, expected=False)
|
||||
|
||||
@@ -350,7 +349,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
new_features_file = new_file + '/.features';
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(features_file)
|
||||
self.assert_path_exists(new_features_file)
|
||||
@@ -363,7 +362,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
orig_stat = os.stat(cache_file)
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(cache_file)
|
||||
stat = os.stat(cache_file)
|
||||
@@ -379,7 +378,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
check_file = testlib.write_file(self.cache_dir, 'monkey', 'monkey\n')
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--write-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(check_file, expected=False)
|
||||
|
||||
@@ -417,7 +416,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
orig_stat = os.stat(self.cache_file)
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', self.profile))
|
||||
cmd.extend(['-v', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
stat = os.stat(self.cache_file)
|
||||
@@ -435,7 +434,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
orig_stat = os.stat(self.cache_file)
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', self.profile))
|
||||
cmd.extend(['-v', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
stat = os.stat(self.cache_file)
|
||||
@@ -453,7 +452,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
orig_stat = os.stat(self.cache_file)
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', '-W', self.profile))
|
||||
cmd.extend(['-v', '-r', '-W', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
stat = os.stat(self.cache_file)
|
||||
@@ -470,7 +469,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
orig_stat = os.stat(self.cache_file)
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '-r', '-W', self.profile))
|
||||
cmd.extend(['-v', '-r', '-W', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
|
||||
stat = os.stat(self.cache_file)
|
||||
@@ -490,7 +489,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd[0] = new_parser
|
||||
cmd.extend(('-v', '-r', self.profile))
|
||||
cmd.extend(['-v', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Cached reload succeeded for')
|
||||
|
||||
def _purge_cache_test(self, location):
|
||||
@@ -498,7 +497,7 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
cache_file = testlib.write_file(self.cache_dir, location, 'monkey\n')
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(('-v', '--purge-cache', '-r', self.profile))
|
||||
cmd.extend(['-v', '--purge-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd)
|
||||
# no message is output
|
||||
self.assert_path_exists(cache_file, expected=False)
|
||||
@@ -527,7 +526,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
|
||||
self.orig_cache_dir = self.cache_dir
|
||||
self.cmd_prefix.extend(('--cache-loc', alt_cache_loc))
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir(create=True)
|
||||
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||
|
||||
@@ -541,7 +540,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
|
||||
|
||||
# skip tearDown check to ensure non-alt cache is empty
|
||||
self.check_orig_cache = False
|
||||
filelist = (PROFILE, '.features', 'monkey')
|
||||
filelist = [PROFILE, '.features', 'monkey']
|
||||
|
||||
for f in filelist:
|
||||
testlib.write_file(self.orig_cache_dir, f, 'monkey\n')
|
||||
|
@@ -1,72 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2022
|
||||
# Canonical, Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical Ltd.
|
||||
#
|
||||
|
||||
# simple test to ensure dir is being iterated as expected
|
||||
# yes this needs to be improved and reworked
|
||||
|
||||
|
||||
# passed in by Makefile
|
||||
#APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
|
||||
|
||||
|
||||
do_tst() {
|
||||
local msg="$1"
|
||||
local expected="$2"
|
||||
local rc=0
|
||||
shift 2
|
||||
#global tmpdir
|
||||
|
||||
${APPARMOR_PARSER} "$@" > "$tmpdir/out" 2>/dev/null
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ] && [ "$expected" != "fail" ] ; then
|
||||
echo "failed: expected \"$expected\" but parser returned error"
|
||||
return 1
|
||||
fi
|
||||
if [ $rc -eq 0 ] && [ "$expected" = "fail" ] ; then
|
||||
echo "succeeded unexpectedly: expected \"$expected\" but parser returned success"
|
||||
return 1
|
||||
fi
|
||||
if ! diff -q "$tmpdir/out" dirtest/dirtest.out ; then
|
||||
echo "failed: expected \"$expected\" but output comparison failed"
|
||||
diff -u dirtest/dirtest.out "$tmpdir/out"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
tmpdir=$(mktemp -d "$tmpdir.XXXXXXXX")
|
||||
chmod 755 "$tmpdir"
|
||||
export tmpdir
|
||||
|
||||
rc=0
|
||||
|
||||
# pass - no parser errors and output matches
|
||||
# error - parser error and output matches
|
||||
# fail - comparison out parser output failed
|
||||
do_tst "good dir list" pass -N dirtest/gooddir/ || rc=1
|
||||
do_tst "bad link in dir" fail -N dirtest/badlink/ || rc=1
|
||||
do_tst "bad profile in dir" fail -N dirtest/badprofile/ || rc=1
|
||||
|
||||
rm -rf "$tmpdir"
|
||||
|
||||
if [ $rc -eq 0 ] ; then
|
||||
echo "PASS"
|
||||
fi
|
||||
|
||||
exit $rc
|
@@ -1 +0,0 @@
|
||||
foo
|
@@ -1 +0,0 @@
|
||||
../goodtarget
|
@@ -1,2 +0,0 @@
|
||||
profile a_profile {
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
profile b_profile {
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
profile bad_profile {
|
||||
file
|
||||
}
|
@@ -1 +0,0 @@
|
||||
../goodtarget
|
@@ -1,2 +0,0 @@
|
||||
profile a_profile {
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
profile b_profile {
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
good_target
|
||||
a_profile
|
||||
b_profile
|
@@ -1 +0,0 @@
|
||||
../goodtarget
|
@@ -1,2 +0,0 @@
|
||||
profile a_profile {
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
profile b_profile {
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
profile good_target {
|
||||
}
|
@@ -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 multiple permissions
|
||||
# because policy write permission "w" actually expands to mutiple 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
|
||||
|
@@ -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='', is_error=True):
|
||||
def _run_test(self, profile, message=None, is_error=True):
|
||||
cmd = self.cmd_prefix + [profile]
|
||||
|
||||
(rc, out, outerr) = self._run_cmd(cmd, stdout=subprocess.DEVNULL)
|
||||
@@ -36,14 +36,8 @@ class AAErrorTests(testlib.AATestTemplate):
|
||||
else:
|
||||
self.assertEqual(rc, 0, 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)
|
||||
if message:
|
||||
self.assertIn(message, outerr, report)
|
||||
|
||||
def test_okay(self):
|
||||
self._run_test('errors/okay.sd', is_error=False)
|
||||
@@ -51,40 +45,40 @@ 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'\n",
|
||||
"AppArmor parser error for errors/single.sd in profile errors/single.sd at line 3: Could not open 'failure'",
|
||||
)
|
||||
|
||||
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'\n",
|
||||
"AppArmor parser error for errors/double.sd in profile errors/includes/busted at line 66: Could not open 'does-not-exist'",
|
||||
)
|
||||
|
||||
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\n",
|
||||
"AppArmor parser error for errors/modefail.sd in profile errors/modefail.sd at line 6: syntax error, unexpected TOK_ID, expecting TOK_MODE",
|
||||
)
|
||||
|
||||
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'\n",
|
||||
"AppArmor parser error for errors/multi_include.sd in profile errors/multi_include.sd at line 12: Could not open 'failure'",
|
||||
)
|
||||
|
||||
def test_deprecation1(self):
|
||||
self.cmd_prefix.append('--warn=deprecated')
|
||||
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\n",
|
||||
"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",
|
||||
is_error=False
|
||||
)
|
||||
|
||||
def test_deprecation2(self):
|
||||
self.cmd_prefix.append('--warn=deprecated')
|
||||
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\n",
|
||||
"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",
|
||||
is_error=False
|
||||
)
|
||||
|
||||
|
167
parser/tst/gen-dbus.pl
Executable file
167
parser/tst/gen-dbus.pl
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Copyright (c) 2013
|
||||
# Canonical, Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical Ltd.
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
|
||||
my $count=0;
|
||||
|
||||
my $prefix="simple_tests/generated_dbus";
|
||||
|
||||
my @quantifier = ("", "deny", "audit");
|
||||
my @session = ("", "bus=session", "bus=system", "bus=accessibility");
|
||||
my @path = ("", "path=/foo/bar", "path=\"/foo/bar\"");
|
||||
my @interface = ("", "interface=com.baz", "interface=\"com.baz\"");
|
||||
my @member = ("", "member=bar", "member=\"bar\"");
|
||||
|
||||
my @name = ("", "name=com.foo", "name=\"com.foo\"");
|
||||
my @peer = map { "peer=($_)" } (@name, "label=/usr/bin/app",
|
||||
"label=\"/usr/bin/app\"",
|
||||
"name=com.foo label=/usr/bin/app",
|
||||
"name=\"com.foo\" label=\"/usr/bin/app\"");
|
||||
|
||||
# @msg_perms are the permissions that are related to sending and receiving
|
||||
# messages. @svc_perms are the permissions related to services.
|
||||
my @base_msg_perms = ("r", "w", "rw", "read", "receive", "write", "send");
|
||||
my @msg_perms = ("", @base_msg_perms, (map { "($_)" } @base_msg_perms),
|
||||
"(write, read)", "(send receive)", "(send read)",
|
||||
"(receive write)");
|
||||
|
||||
gen_files("message-rules", "PASS", \@quantifier, \@msg_perms, \@session,
|
||||
[""], \@path, \@interface, \@member, \@peer);
|
||||
gen_files("service-rules", "PASS", \@quantifier, ["bind"], \@session,
|
||||
\@name, [""], [""], [""], [""]);
|
||||
gen_files("eavesdrop-rules", "PASS", \@quantifier, ["eavesdrop"], \@session,
|
||||
[""], [""], [""], [""], [""]);
|
||||
gen_file("sloppy-formatting", "PASS", "", "(send , receive )", "bus=session",
|
||||
"", "path =\"/foo/bar\"", "interface = com.foo", " member=bar",
|
||||
"peer =( label= /usr/bin/app name =\"com.foo\")");
|
||||
gen_file("sloppy-formatting", "PASS", "", "bind", "bus =session",
|
||||
"name= com.foo", "", "", "", "");
|
||||
gen_file("sloppy-formatting", "PASS", "", "eavesdrop", "bus = system",
|
||||
"", "", "", "", "");
|
||||
|
||||
# Don't use the first element, which is empty, from each array since all empty
|
||||
# conditionals would PASS but we want all FAILs
|
||||
shift @msg_perms;
|
||||
shift @name;
|
||||
shift @path;
|
||||
shift @interface;
|
||||
shift @member;
|
||||
shift @peer;
|
||||
gen_files("message-incompat", "FAIL", \@quantifier, \@msg_perms, \@session,
|
||||
\@name, [""], [""], [""], [""]);
|
||||
gen_files("service-incompat", "FAIL", \@quantifier, ["bind"], \@session,
|
||||
\@name, \@path, [""], [""], [""]);
|
||||
gen_files("service-incompat", "FAIL", \@quantifier, ["bind"], \@session,
|
||||
\@name, [""], \@interface, [""], [""]);
|
||||
gen_files("service-incompat", "FAIL", \@quantifier, ["bind"], \@session,
|
||||
\@name, [""], [""], \@member, [""]);
|
||||
gen_files("service-incompat", "FAIL", \@quantifier, ["bind"], \@session,
|
||||
\@name, [""], [""], [""], \@peer);
|
||||
gen_files("eavesdrop-incompat", "FAIL", \@quantifier, ["eavesdrop"], \@session,
|
||||
\@name, \@path, \@interface, \@member, \@peer);
|
||||
|
||||
gen_files("pairing-unsupported", "FAIL", \@quantifier, ["send", "bind"],
|
||||
\@session, ["name=sn", "label=sl"], [""], [""], [""],
|
||||
["peer=(name=pn)", "peer=(label=pl)"]);
|
||||
|
||||
# missing bus= prefix
|
||||
gen_file("bad-formatting", "FAIL", "", "send", "session", "", "", "", "", "");
|
||||
# incorrectly formatted permissions
|
||||
gen_files("bad-perms", "FAIL", [""], ["send receive", "(send", "send)"],
|
||||
["bus=session"], [""], [""], [""], [""], [""]);
|
||||
# invalid permissions
|
||||
gen_files("bad-perms", "FAIL", [""],
|
||||
["a", "x", "Ux", "ix", "m", "k", "l", "(a)", "(x)"], [""], [""],
|
||||
[""], [""], [""], [""]);
|
||||
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "bus=1 bus=2");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "name=1 name=2");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "path=1 path=2");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "interface=1 interface=2");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "member=1 member=2");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "peer=(name=1) peer=(name=2)");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "peer=(label=1) peer=(label=2)");
|
||||
gen_file("duplicated-conditionals", "FAIL", "", "peer=(name=1) peer=(label=2)");
|
||||
|
||||
print "Generated $count dbus tests\n";
|
||||
|
||||
sub print_rule($$$$$$$$$) {
|
||||
my ($file, $quantifier, $perms, $session, $name, $path, $interface, $member, $peer) = @_;
|
||||
|
||||
print $file " ";
|
||||
print $file " ${quantifier}" if ${quantifier};
|
||||
print $file " dbus";
|
||||
print $file " ${perms}" if ${perms};
|
||||
print $file " ${session}" if ${session};
|
||||
print $file " ${name}" if ${name};
|
||||
print $file " ${path}" if ${path};
|
||||
print $file " ${interface}" if ${interface};
|
||||
print $file " ${member}" if ${member};
|
||||
print $file " ${peer}" if ${peer};
|
||||
print $file ",\n";
|
||||
}
|
||||
|
||||
sub gen_file($$$$$$$$$$) {
|
||||
my ($test, $xres, $quantifier, $perms, $session, $name, $path, $interface, $member, $peer) = @_;
|
||||
|
||||
my $file;
|
||||
unless (open $file, ">${prefix}/$test-$count.sd") {
|
||||
print("couldn't open $test\n");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print $file "#\n";
|
||||
print $file "#=DESCRIPTION ${test}\n";
|
||||
print $file "#=EXRESULT ${xres}\n";
|
||||
print $file "#\n";
|
||||
print $file "/usr/bin/foo {\n";
|
||||
print_rule($file, $quantifier, $perms, $session, $name, $path, $interface,
|
||||
$member, $peer);
|
||||
print $file "}\n";
|
||||
close($file);
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
sub gen_files($$$$$$$$$$) {
|
||||
my ($test, $xres, $quantifiers, $perms, $sessions, $names, $paths, $interfaces, $members, $peers) = @_;
|
||||
|
||||
foreach my $quantifier (@{$quantifiers}) {
|
||||
foreach my $perm (@{$perms}) {
|
||||
foreach my $session (@{$sessions}) {
|
||||
foreach my $name (@{$names}) {
|
||||
foreach my $path (@{$paths}) {
|
||||
foreach my $interface (@{$interfaces}) {
|
||||
foreach my $member (@{$members}) {
|
||||
foreach my $peer (@{$peers}) {
|
||||
gen_file($test, $xres, $quantifier, $perm, $session, $name,
|
||||
$path, $interface, $member, $peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,157 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2013 Canonical, Ltd. (All rights reserved)
|
||||
# Copyright (c) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical Ltd.
|
||||
#
|
||||
|
||||
from testlib import write_file
|
||||
|
||||
def get_rule (quantifier, perms, session, name, path, interface, member, peer):
|
||||
|
||||
result = ' '
|
||||
|
||||
for part in (quantifier, 'dbus', perms, session, name, path, interface, member, peer):
|
||||
if part:
|
||||
result += ' %s' % part
|
||||
|
||||
result += ',\n'
|
||||
|
||||
return result
|
||||
|
||||
def gen_file(test, xres, quantifier, perms, session, name, path, interface, member, peer):
|
||||
global count
|
||||
|
||||
content = ''
|
||||
content += '#\n'
|
||||
content += '#=DESCRIPTION %s\n' % test
|
||||
content += '#=EXRESULT %s\n' % xres
|
||||
content += '#\n'
|
||||
content += '/usr/bin/foo {\n'
|
||||
content += get_rule(quantifier, perms, session, name, path, interface, member, peer)
|
||||
content += '}\n'
|
||||
|
||||
write_file('simple_tests/generated_dbus', '%s-%s.sd' % (test, count), content)
|
||||
|
||||
count += 1
|
||||
|
||||
def gen_files (test, xres, quantifiers, perms, sessions, names, paths, interfaces, members, peers):
|
||||
for quantifier in quantifiers:
|
||||
for perm in perms:
|
||||
for session in sessions:
|
||||
for name in names:
|
||||
for path in paths:
|
||||
for interface in interfaces:
|
||||
for member in members:
|
||||
for peer in peers:
|
||||
gen_file(test, xres, quantifier, perm, session, name, path, interface, member, peer)
|
||||
|
||||
count=0
|
||||
|
||||
quantifier = ('', 'deny', 'audit')
|
||||
session = ('', 'bus=session', 'bus=system', 'bus=accessibility')
|
||||
path = ['', 'path=/foo/bar', 'path="/foo/bar"']
|
||||
interface = ['', 'interface=com.baz', 'interface="com.baz"']
|
||||
member = ['', 'member=bar', 'member="bar"']
|
||||
|
||||
name = ['', 'name=com.foo', 'name="com.foo"']
|
||||
peer = [
|
||||
'peer=()',
|
||||
'peer=(name=com.foo)',
|
||||
'peer=(name="com.foo")',
|
||||
'peer=(label=/usr/bin/app)',
|
||||
'peer=(label="/usr/bin/app")',
|
||||
'peer=(name=com.foo label=/usr/bin/app)',
|
||||
'peer=(name="com.foo" label="/usr/bin/app")',
|
||||
]
|
||||
|
||||
# msg_perms are the permissions that are related to sending and receiving
|
||||
# messages.
|
||||
msg_perms = [
|
||||
'',
|
||||
'r',
|
||||
'w',
|
||||
'rw',
|
||||
'read',
|
||||
'receive',
|
||||
'write',
|
||||
'send',
|
||||
'(r)',
|
||||
'(w)',
|
||||
'(rw)',
|
||||
'(read)',
|
||||
'(receive)',
|
||||
'(write)',
|
||||
'(send)',
|
||||
'(write, read)',
|
||||
'(send receive)',
|
||||
'(send read)',
|
||||
'(receive write)',
|
||||
]
|
||||
|
||||
empty_tup = ('',)
|
||||
|
||||
gen_files('message-rules', 'PASS', quantifier, msg_perms, session,
|
||||
empty_tup, path, interface, member, peer)
|
||||
gen_files('service-rules', 'PASS', quantifier, ['bind'], session,
|
||||
name, empty_tup, empty_tup, empty_tup, empty_tup)
|
||||
gen_files('eavesdrop-rules', 'PASS', quantifier, ['eavesdrop'], session,
|
||||
empty_tup, empty_tup, empty_tup, empty_tup, empty_tup)
|
||||
gen_file('sloppy-formatting', 'PASS', '', '(send , receive )', 'bus=session',
|
||||
'', 'path ="/foo/bar"', 'interface = com.foo', ' member=bar',
|
||||
'peer =( label= /usr/bin/app name ="com.foo")')
|
||||
gen_file('sloppy-formatting', 'PASS', '', 'bind', 'bus =session',
|
||||
'name= com.foo', '', '', '', '')
|
||||
gen_file('sloppy-formatting', 'PASS', '', 'eavesdrop', 'bus = system',
|
||||
'', '', '', '', '')
|
||||
|
||||
# Don't use the empty element from each array since all empty conditionals would PASS but we want all FAILs
|
||||
msg_perms.remove('')
|
||||
name.remove('')
|
||||
path.remove('')
|
||||
interface.remove('')
|
||||
member.remove('')
|
||||
peer.remove('peer=()')
|
||||
|
||||
gen_files('message-incompat', 'FAIL', quantifier, msg_perms, session, name, empty_tup, empty_tup, empty_tup, empty_tup)
|
||||
gen_files('service-incompat', 'FAIL', quantifier, ('bind',), session, name, path, empty_tup, empty_tup, empty_tup)
|
||||
gen_files('service-incompat', 'FAIL', quantifier, ('bind',), session, name, empty_tup, interface, empty_tup, empty_tup)
|
||||
gen_files('service-incompat', 'FAIL', quantifier, ('bind',), session, name, empty_tup, empty_tup, member, empty_tup)
|
||||
gen_files('service-incompat', 'FAIL', quantifier, ('bind',), session, name, empty_tup, empty_tup, empty_tup, peer)
|
||||
gen_files('eavesdrop-incompat', 'FAIL', quantifier, ('eavesdrop',), session, name, path, interface, member, peer)
|
||||
|
||||
gen_files('pairing-unsupported', 'FAIL', quantifier, ('send', 'bind'),
|
||||
session, ('name=sn', 'label=sl'), empty_tup, empty_tup, empty_tup,
|
||||
('peer=(name=pn)', 'peer=(label=pl)'))
|
||||
|
||||
# missing bus= prefix
|
||||
gen_file('bad-formatting', 'FAIL', '', 'send', 'session', '', '', '', '', '')
|
||||
# incorrectly formatted permissions
|
||||
gen_files('bad-perms', 'FAIL', empty_tup, ('send receive', '(send', 'send)'),
|
||||
('bus=session',), empty_tup, empty_tup, empty_tup, empty_tup, empty_tup)
|
||||
# invalid permissions
|
||||
gen_files('bad-perms', 'FAIL', empty_tup,
|
||||
('a', 'x', 'Ux', 'ix', 'm', 'k', 'l', '(a)', '(x)'), empty_tup, empty_tup,
|
||||
empty_tup, empty_tup, empty_tup, empty_tup)
|
||||
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'bus=1 bus=2', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'name=1 name=2', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'path=1 path=2', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'interface=1 interface=2', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'member=1 member=2', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(name=1) peer=(name=2)', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(label=1) peer=(label=2)', '', '', '', '', '', '')
|
||||
gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(name=1) peer=(label=2)', '', '', '', '', '', '')
|
||||
|
||||
print('Generated %s dbus tests' % count)
|
235
parser/tst/gen-xtrans.pl
Executable file
235
parser/tst/gen-xtrans.pl
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,219 +0,0 @@
|
||||
#!/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 test leading permissions or using unsafe keywords
|
||||
# It is assumed that there are extra tests to verify 1 to 1 correspondance
|
||||
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 counterpart,
|
||||
# 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 information
|
||||
# the accept state infomation
|
||||
# {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 dot
|
||||
# strip of the test stuff around the parser command and use the 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
|
||||
# eliminates the states with 'w' and 'a' because the quiet information is
|
||||
# elimnates 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 eliminates the states with 'w' and 'a' because
|
||||
# parameter this elimnates 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 overridden during dfa creation.
|
||||
# 3rd is a generic permission that should be overriden 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 artificial trap state
|
||||
# notice that the deny info is being carried, by an artifical trap state
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/fe17f85/0/0)
|
||||
|
||||
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi "
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi ",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi ""
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi "",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi <
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi <,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi <>
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - empty/cut-off rule
|
||||
#=EXRESULT FAIL
|
||||
|
||||
abi <>,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION validate some uses of capabilities.
|
||||
#=DESCRIPTION validate some uses of capabilties.
|
||||
#=EXRESULT FAIL
|
||||
# vim:syntax=subdomain
|
||||
# Last Modified: Sun Apr 17 19:44:44 2005
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#=DESCRIPTION conditional else in invalid locations
|
||||
#=DESCRIPTION conditional else in invlaid locations
|
||||
#=EXRESULT FAIL
|
||||
|
||||
$BAR = false
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#
|
||||
#=DESCRIPTION netdomain tcp connect w/multiple from statements
|
||||
#=DESCRIPTION netdomain tcp connect w/multiple from statments
|
||||
#=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 with named profile, duplicate mode bits
|
||||
#=DESCRIPTION Basic namespace test wit 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 size rlimit test
|
||||
#=DESCRIPTION simple max virtual memory szie rlimit test
|
||||
#=EXRESULT PASS
|
||||
|
||||
profile rlimit {
|
||||
|
@@ -86,7 +86,7 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
|
||||
(rc, out, outerr) = self._run_cmd(command, input, stderr, stdout, stdin, timeout)
|
||||
report = out + outerr
|
||||
|
||||
return rc, report
|
||||
return [rc, report]
|
||||
|
||||
def _run_cmd(self, command, input=None, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stdin=None, timeout=120):
|
||||
@@ -96,7 +96,7 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
|
||||
sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr,
|
||||
close_fds=True, preexec_fn=subprocess_setup, universal_newlines=True)
|
||||
except OSError as e:
|
||||
return 127, str(e), ''
|
||||
return [127, str(e)]
|
||||
|
||||
timeout_communicate = TimeoutFunction(sp.communicate, timeout)
|
||||
out, outerr = (None, None)
|
||||
@@ -115,7 +115,7 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
|
||||
if outerr is None:
|
||||
outerr = ''
|
||||
|
||||
return rc, out, outerr
|
||||
return (rc, out, outerr)
|
||||
|
||||
|
||||
# Timeout handler using alarm() from John P. Speno's Pythonic Avocado
|
||||
|
@@ -42,8 +42,8 @@ class AAParserValgrindTests(testlib.AATestTemplate):
|
||||
self.maxDiff = None
|
||||
|
||||
def _runtest(self, testname, config):
|
||||
parser_args = ('-Q', '-I', config.testdir, '-M', './features_files/features.all')
|
||||
failure_rc = (VALGRIND_ERROR_CODE, testlib.TIMEOUT_ERROR_CODE)
|
||||
parser_args = ['-Q', '-I', config.testdir, '-M', './features_files/features.all']
|
||||
failure_rc = [VALGRIND_ERROR_CODE, testlib.TIMEOUT_ERROR_CODE]
|
||||
command = [config.valgrind]
|
||||
command.extend(VALGRIND_ARGS)
|
||||
command.append(config.parser)
|
||||
@@ -68,11 +68,11 @@ def create_suppressions():
|
||||
|
||||
handle, name = tempfile.mkstemp(suffix='.suppressions', prefix='aa-parser-valgrind')
|
||||
os.close(handle)
|
||||
with open(name, "w+") as handle:
|
||||
handle.write(VALGRIND_SUPPRESSIONS)
|
||||
handle = open(name,"w+")
|
||||
handle.write(VALGRIND_SUPPRESSIONS)
|
||||
handle.close()
|
||||
return name
|
||||
|
||||
|
||||
def main():
|
||||
rc = 0
|
||||
p = ArgumentParser()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user