mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 14:55:10 +00:00
Compare commits
95 Commits
apparmor-3
...
v3.0.3
Author | SHA1 | Date | |
---|---|---|---|
|
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 |
39
.gitignore
vendored
39
.gitignore
vendored
@@ -10,22 +10,10 @@ binutils/aa-status
|
||||
binutils/aa-status.8
|
||||
binutils/cJSON.o
|
||||
binutils/po/*.mo
|
||||
changehat/mod_apparmor/.libs
|
||||
changehat/mod_apparmor/mod_apparmor.8
|
||||
changehat/mod_apparmor/mod_apparmor.8.html
|
||||
changehat/mod_apparmor/mod_apparmor.la
|
||||
changehat/mod_apparmor/mod_apparmor.lo
|
||||
changehat/mod_apparmor/mod_apparmor.slo
|
||||
changehat/mod_apparmor/mod_apparmor.so
|
||||
changehat/mod_apparmor/pod2htmd.tmp
|
||||
changehat/pam_apparmor/get_options.o
|
||||
changehat/pam_apparmor/pam_apparmor.o
|
||||
changehat/pam_apparmor/pam_apparmor.so
|
||||
parser/po/*.mo
|
||||
parser/af_names.h
|
||||
parser/cap_names.h
|
||||
parser/generated_cap_names.h
|
||||
parser/generated_af_names.h
|
||||
parser/tst_lib
|
||||
parser/tst_misc
|
||||
parser/tst_regex
|
||||
@@ -171,7 +159,6 @@ libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/perl/libapparmor_wrap.o
|
||||
libraries/libapparmor/swig/perl/pm_to_blib
|
||||
libraries/libapparmor/swig/python/LibAppArmor.py
|
||||
libraries/libapparmor/swig/python/LibAppArmor.egg-info/
|
||||
libraries/libapparmor/swig/python/build/
|
||||
libraries/libapparmor/swig/python/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/python/Makefile
|
||||
@@ -188,7 +175,7 @@ libraries/libapparmor/swig/ruby/LibAppArmor_wrap.c
|
||||
libraries/libapparmor/swig/ruby/LibAppArmor_wrap.o
|
||||
libraries/libapparmor/swig/ruby/Makefile
|
||||
libraries/libapparmor/swig/ruby/Makefile.in
|
||||
libraries/libapparmor/swig/ruby/Makefile.bak
|
||||
libraries/libapparmor/swig/ruby/Makefile.new
|
||||
libraries/libapparmor/swig/ruby/Makefile.ruby
|
||||
libraries/libapparmor/swig/ruby/mkmf.log
|
||||
libraries/libapparmor/testsuite/.deps
|
||||
@@ -207,6 +194,7 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||
libraries/libapparmor/testsuite/test_multi/out
|
||||
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
||||
changehat/mod_apparmor/.libs
|
||||
utils/*.8
|
||||
utils/*.8.html
|
||||
utils/*.5
|
||||
@@ -215,8 +203,6 @@ utils/*.tmp
|
||||
utils/po/*.mo
|
||||
utils/apparmor/*.pyc
|
||||
utils/apparmor/rule/*.pyc
|
||||
utils/apparmor.egg-info/
|
||||
utils/build/
|
||||
utils/htmlcov/
|
||||
utils/test/common_test.pyc
|
||||
utils/test/.coverage
|
||||
@@ -226,11 +212,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
|
||||
@@ -245,10 +227,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
|
||||
@@ -259,10 +237,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
|
||||
@@ -273,20 +248,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
|
||||
@@ -298,15 +268,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
|
||||
|
138
.gitlab-ci.yml
138
.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 zlib1g-dev
|
||||
- lsb_release -a
|
||||
- uname -a
|
||||
|
||||
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
||||
# reports
|
||||
@@ -8,132 +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 autoconf-archive 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 python3-setuptools
|
||||
# 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
|
||||
- make -C profiles check-extras
|
||||
|
||||
shellcheck:
|
||||
stage: test
|
||||
needs: []
|
||||
extends:
|
||||
- .ubuntu-before_script
|
||||
script:
|
||||
- apt-get install --no-install-recommends -y python3-minimal 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
|
@@ -124,7 +124,7 @@ static char **parse_args(int argc, char **argv)
|
||||
{"stdout", no_argument, 0, ARG_STDOUT},
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "+dvhxf:l:w:", long_opts, NULL)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "+dvhxl:w:", long_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
opt_debug = true;
|
||||
@@ -181,7 +181,7 @@ int main(int argc, char **argv)
|
||||
error("failed to extract features abi from the kernel");
|
||||
}
|
||||
if (opt_file) {
|
||||
in = open(opt_file, O_RDONLY);
|
||||
int in = open(opt_file, O_RDONLY);
|
||||
if (in == -1)
|
||||
error("failed to open file '%s'", opt_file);
|
||||
rc = aa_features_new_from_file(&features, in);
|
||||
|
@@ -135,16 +135,7 @@ static int get_profiles(struct profile **profiles, size_t *n) {
|
||||
while (getline(&line, &len, fp) != -1) {
|
||||
struct profile *_profiles;
|
||||
autofree char *status = NULL;
|
||||
autofree char *name = NULL;
|
||||
char *tmpname = aa_splitcon(line, &status);
|
||||
|
||||
if (!tmpname) {
|
||||
dfprintf(stderr, "Error: failed profile name split of '%s'.\n", line);
|
||||
ret = AA_EXIT_INTERNAL_ERROR;
|
||||
// skip this entry and keep processing
|
||||
continue;
|
||||
}
|
||||
name = strdup(tmpname);
|
||||
autofree char *name = strdup(aa_splitcon(line, &status));
|
||||
|
||||
if (status)
|
||||
status = strdup(status);
|
||||
@@ -454,7 +445,6 @@ static int detailed_output(FILE *json) {
|
||||
const char *process_statuses[] = {"enforce", "complain", "unconfined", "mixed", "kill"};
|
||||
int ret;
|
||||
size_t i;
|
||||
int need_finish = 0;
|
||||
|
||||
ret = get_profiles(&profiles, &nprofiles);
|
||||
if (ret != 0) {
|
||||
@@ -535,20 +525,16 @@ static int detailed_output(FILE *json) {
|
||||
} else {
|
||||
fprintf(json, "%s\"%s\": [{\"profile\": \"%s\", \"pid\": \"%s\", \"status\": \"%s\"}",
|
||||
// first element will be a unique executable
|
||||
j == 0 && !need_finish ? "" : "], ",
|
||||
i == 0 && j == 0 ? "" : "], ",
|
||||
filtered[j].exe, filtered[j].profile, filtered[j].pid, filtered[j].mode);
|
||||
}
|
||||
|
||||
need_finish = 1;
|
||||
}
|
||||
}
|
||||
free_processes(filtered, nfiltered);
|
||||
}
|
||||
if (json) {
|
||||
if (need_finish > 0) {
|
||||
fprintf(json, "]");
|
||||
}
|
||||
fprintf(json, "}}\n");
|
||||
fprintf(json, "%s}}\n", nprocesses > 0 ? "]" : "");
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@@ -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.1.7
|
||||
3.0.3
|
||||
|
@@ -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_".
|
||||
|
||||
|
@@ -92,13 +92,6 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
|
||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||
fi
|
||||
|
||||
EXTRA_CFLAGS="-Wall $(EXTRA_WARNINGS) -fPIC"
|
||||
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
||||
AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
||||
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
||||
,)
|
||||
AC_SUBST([AM_CFLAGS], ["$EXTRA_CFLAGS"])
|
||||
|
||||
AC_OUTPUT(
|
||||
Makefile
|
||||
doc/Makefile
|
||||
|
@@ -116,14 +116,6 @@ The specified I<file/task> does not exist or is not visible.
|
||||
|
||||
The confinement data is too large to fit in the supplied buffer.
|
||||
|
||||
=item B<ENOPROTOOPT>
|
||||
|
||||
The kernel doesn't support the SO_PEERLABEL option in sockets. This happens
|
||||
mainly when the kernel lacks 'fine grained unix mediation' support. It also
|
||||
can happen on LSM stacking kernels where another LSM has claimed this
|
||||
interface and decides to return this error, although this is really a
|
||||
corner case.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
@@ -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
|
||||
|
@@ -109,12 +109,12 @@ To immediately stack a profile named "profile_a", as performed with
|
||||
aa_stack_profile("profile_a"), the equivalent of this shell command can be
|
||||
used:
|
||||
|
||||
$ echo -n "stack profile_a" > /proc/self/attr/current
|
||||
$ echo -n "stackprofile profile_a" > /proc/self/attr/current
|
||||
|
||||
To stack a profile named "profile_a" at the next exec, as performed with
|
||||
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
|
||||
|
||||
$ echo -n "stack profile_a" > /proc/self/attr/exec
|
||||
$ echo -n "stackexec profile_a" > /proc/self/attr/exec
|
||||
|
||||
These raw AppArmor filesystem operations must only be used when using
|
||||
libapparmor is not a viable option.
|
||||
@@ -184,7 +184,6 @@ with apparmor_parser(8):
|
||||
/etc/passwd r,
|
||||
|
||||
# Needed for aa_stack_profile()
|
||||
change-profile -> &i_cant_be_trusted_anymore,
|
||||
/usr/lib/libapparmor*.so* mr,
|
||||
/proc/[0-9]*/attr/current w,
|
||||
}
|
||||
|
@@ -159,8 +159,6 @@ typedef struct
|
||||
char *fs_type;
|
||||
char *flags;
|
||||
char *src_name;
|
||||
|
||||
char *class;
|
||||
} aa_log_record;
|
||||
|
||||
/**
|
||||
|
@@ -66,17 +66,17 @@ variable to configure. See ``configure --help'' for reference.
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have setuptools, else fail
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the setuptools Python package])
|
||||
ac_setuptools_result=`$PYTHON -c "import setuptools" 2>&1`
|
||||
if test -z "$ac_setuptools_result"; then
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test -z "$ac_distutils_result"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "setuptools".
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_setuptools_result])
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
@@ -88,8 +88,8 @@ $ac_setuptools_result])
|
||||
PYTHON_CPPFLAGS=`$PYTHON_CONFIG --includes`
|
||||
fi
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import sys; import sysconfig;\
|
||||
sys.stdout.write('%s\n' % sysconfig.get_path('include'));"`
|
||||
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
|
||||
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
@@ -108,8 +108,8 @@ sys.stdout.write('%s\n' % sysconfig.get_path('include'));"`
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
# (makes two attempts to ensure we've got a version number
|
||||
# from the interpreter)
|
||||
py_version=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('%s\n' % ''.join(sysconfig.get_config_vars('VERSION')))"`
|
||||
py_version=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
|
||||
sys.stdout.write('%s\n' % ''.join(get_config_vars('VERSION')))"`
|
||||
if test "$py_version" == "[None]"; then
|
||||
if test -n "$PYTHON_VERSION"; then
|
||||
py_version=$PYTHON_VERSION
|
||||
@@ -119,8 +119,8 @@ sys.stdout.write("%s\n" % sys.version[[:3]])"`
|
||||
fi
|
||||
fi
|
||||
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('-L' + sysconfig.get_path('stdlib') + ' -lpython\n')"`$py_version`$PYTHON -c \
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
|
||||
sys.stdout.write('-L' + get_python_lib(0,1) + ' -lpython\n')"`$py_version`$PYTHON -c \
|
||||
"import sys; sys.stdout.write('%s' % getattr(sys,'abiflags',''))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LDFLAGS])
|
||||
@@ -131,8 +131,8 @@ sys.stdout.write('-L' + sysconfig.get_path('stdlib') + ' -lpython\n')"`$py_versi
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('%s\n' % sysconfig.get_path('purelib'));"`
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_lib(0,0));"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
@@ -146,8 +146,8 @@ sys.stdout.write('%s\n' % sysconfig.get_path('purelib'));"`
|
||||
PYTHON_EXTRA_LIBS=''
|
||||
fi
|
||||
if test -z "$PYTHON_EXTRA_LIBS"; then
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
conf = sysconfig.get_config_var; \
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
sys.stdout.write('%s %s %s\n' % (conf('BLDLIBRARY'), conf('LOCALMODLIBS'), conf('LIBS')))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
|
||||
@@ -162,8 +162,8 @@ sys.stdout.write('%s %s %s\n' % (conf('BLDLIBRARY'), conf('LOCALMODLIBS'), conf(
|
||||
PYTHON_EXTRA_LDFLAGS=''
|
||||
fi
|
||||
if test -z "$PYTHON_EXTRA_LDFLAGS"; then
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
conf = sysconfig.get_config_var; \
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
sys.stdout.write('%s\n' % conf('LINKFORSHARED'))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
|
||||
|
@@ -11,13 +11,9 @@ INCLUDES = $(all_includes)
|
||||
# 3. If any interfaces have been added, removed, or changed since the last
|
||||
# update,
|
||||
# - increment AA_LIB_CURRENT
|
||||
# - by 1 if bugfix release
|
||||
# - by 5 on larger releases. This gives room to fix library interface
|
||||
# problems in the unlikely event where an interface has to break.
|
||||
# - set AA_LIB_REVISION to 0.
|
||||
# 4. If any interfaces have been added since the last public release, then
|
||||
# - increment AA_LIB_AGE by the same amount that AA_LIB_CURRENT was
|
||||
# incremented.
|
||||
# - increment AA_LIB_AGE.
|
||||
# 5. If any interfaces have been removed or changed since the last public
|
||||
# release, then
|
||||
# - set AA_LIB_AGE to 0.
|
||||
@@ -30,12 +26,9 @@ INCLUDES = $(all_includes)
|
||||
# For more information, see:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
#
|
||||
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
||||
|
||||
AA_LIB_CURRENT = 13
|
||||
AA_LIB_REVISION = 3
|
||||
AA_LIB_AGE = 12
|
||||
EXPECTED_SO_NAME = libapparmor.so.1.12.3
|
||||
AA_LIB_CURRENT = 9
|
||||
AA_LIB_REVISION = 1
|
||||
AA_LIB_AGE = 8
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
|
||||
@@ -45,6 +38,7 @@ include $(COMMONDIR)/Make.rules
|
||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||
AM_LFLAGS = -v
|
||||
AM_YFLAGS = -d -p aalogparse_
|
||||
AM_CFLAGS = -Wall $(EXTRA_WARNINGS) -fPIC
|
||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||
scanner.h: scanner.l
|
||||
$(LEX) -v $<
|
||||
@@ -52,7 +46,7 @@ scanner.h: scanner.l
|
||||
scanner.c: scanner.l
|
||||
|
||||
af_protos.h:
|
||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dD - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dM - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||
|
||||
lib_LTLIBRARIES = libapparmor.la
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||
@@ -83,8 +77,4 @@ tst_kernel_LDFLAGS = -pthread
|
||||
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
.PHONY: check-local
|
||||
check-local:
|
||||
test -f ./.libs/$(EXPECTED_SO_NAME) || { echo '*** unexpected .so name/number for libapparmor (expected $(EXPECTED_SO_NAME), the actual filename is shown below) ***' ; ls -l ./.libs/libapparmor.so.*.* ; exit 1; }
|
||||
|
||||
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc
|
||||
|
@@ -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;
|
||||
@@ -398,10 +396,6 @@ static bool walk_one(const char **str, const struct component *component,
|
||||
i = 0;
|
||||
|
||||
cur++;
|
||||
|
||||
/* Partial match, continue to search */
|
||||
if (i == component->len && !isbrace_space_or_nul(*cur))
|
||||
i = 0;
|
||||
}
|
||||
|
||||
/* Return false if a full match was not found */
|
||||
@@ -670,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,
|
||||
@@ -683,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++) {
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#if (YYDEBUG != 0)
|
||||
#define debug_unused_ /* nothing */
|
||||
#else
|
||||
#define debug_unused_ unused_
|
||||
#define no_debug_unused_ unused_
|
||||
#endif
|
||||
|
||||
aa_log_record *ret_record;
|
||||
@@ -46,7 +46,7 @@ aa_log_record *ret_record;
|
||||
/* Since we're a library, on any errors we don't want to print out any
|
||||
* error messages. We should probably add a debug interface that does
|
||||
* emit messages when asked for. */
|
||||
void aalogparse_error(unused_ void *scanner, debug_unused_ char const *s)
|
||||
void aalogparse_error(unused_ void *scanner, no_debug_unused_ char const *s)
|
||||
{
|
||||
#if (YYDEBUG != 0)
|
||||
printf("ERROR: %s\n", s);
|
||||
@@ -159,9 +159,7 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
||||
%token TOK_KEY_NAMESPACE
|
||||
%token TOK_KEY_ERROR
|
||||
%token TOK_KEY_FSUID
|
||||
%token TOK_KEY_FSUID_UPPER
|
||||
%token TOK_KEY_OUID
|
||||
%token TOK_KEY_OUID_UPPER
|
||||
%token TOK_KEY_UID
|
||||
%token TOK_KEY_AUID
|
||||
%token TOK_KEY_SAUID
|
||||
@@ -187,9 +185,7 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
||||
%token TOK_KEY_FSTYPE
|
||||
%token TOK_KEY_FLAGS
|
||||
%token TOK_KEY_SRCNAME
|
||||
%token TOK_KEY_CLASS
|
||||
|
||||
%token TOK_SOCKLOGD_KERNEL
|
||||
%token TOK_SYSLOG_KERNEL
|
||||
%token TOK_SYSLOG_USER
|
||||
|
||||
@@ -236,28 +232,24 @@ dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
|
||||
;
|
||||
|
||||
syslog_id: TOK_ID TOK_SYSLOG_KERNEL { free($1); }
|
||||
| TOK_SOCKLOGD_KERNEL { }
|
||||
;
|
||||
|
||||
syslog_type:
|
||||
syslog_date syslog_id audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date syslog_id key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
/* needs update: hard newline in handling mutiline log messages */
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_USER key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
;
|
||||
@@ -354,10 +346,6 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->fsuid = $3;}
|
||||
| TOK_KEY_OUID TOK_EQUALS TOK_DIGITS
|
||||
{ ret_record->ouid = $3;}
|
||||
| TOK_KEY_FSUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ free($3);} /* Ignore - fsuid username */
|
||||
| TOK_KEY_OUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ free($3);} /* Ignore - ouid username */
|
||||
| TOK_KEY_SAUID TOK_EQUALS TOK_DIGITS
|
||||
{ /* Ignore - Source audit ID from user AVC messages */ }
|
||||
| TOK_KEY_HOSTNAME TOK_EQUALS safe_string
|
||||
@@ -385,7 +373,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
| TOK_KEY_CAPABILITY TOK_EQUALS TOK_DIGITS
|
||||
{ /* need to reverse map number to string, need to figure out
|
||||
* how to get auto generation of reverse mapping table into
|
||||
* autotools Makefile. For now just drop 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
|
||||
@@ -393,7 +381,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
ret_record->name = $3;
|
||||
}
|
||||
| TOK_KEY_OFFSET TOK_EQUALS TOK_DIGITS
|
||||
{ /* offset is used for reporting where an error occurred unpacking
|
||||
{ /* offset is used for reporting where an error occured unpacking
|
||||
* loaded policy. We can just drop this currently
|
||||
*/
|
||||
}
|
||||
@@ -432,8 +420,6 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
ret_record->event = AA_RECORD_INVALID;
|
||||
ret_record->info = $1;
|
||||
}
|
||||
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->class = $3; }
|
||||
;
|
||||
|
||||
apparmor_event:
|
||||
|
@@ -43,7 +43,6 @@
|
||||
__asm__ (".symver " #real "," #name "@" #version)
|
||||
#define default_symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version)
|
||||
#define DLLEXPORT __attribute__((visibility("default"),externally_visible))
|
||||
|
||||
#define UNCONFINED "unconfined"
|
||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||
@@ -825,7 +824,7 @@ int aa_change_onexec(const char *profile)
|
||||
}
|
||||
|
||||
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
|
||||
DLLEXPORT extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
|
||||
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
||||
|
||||
@@ -1223,7 +1222,7 @@ int query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
||||
|
||||
/* export multiple aa_query_label symbols to compensate for downstream
|
||||
* releases with differing symbol versions. */
|
||||
DLLEXPORT extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
|
||||
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
||||
|
||||
@@ -1319,9 +1318,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,
|
||||
|
@@ -103,8 +103,6 @@ void free_record(aa_log_record *record)
|
||||
free(record->flags);
|
||||
if (record->src_name != NULL)
|
||||
free(record->src_name);
|
||||
if (record->class != NULL)
|
||||
free(record->class);
|
||||
|
||||
free(record);
|
||||
}
|
||||
|
@@ -6,14 +6,14 @@
|
||||
|
||||
IMMUNIX_1.0 {
|
||||
global:
|
||||
change_hat; __old_change_hat;
|
||||
change_hat;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
APPARMOR_1.0 {
|
||||
global:
|
||||
change_hat; __change_hat;
|
||||
change_hat;
|
||||
parse_record;
|
||||
free_record;
|
||||
local:
|
||||
@@ -24,7 +24,7 @@ APPARMOR_1.1 {
|
||||
global:
|
||||
aa_is_enabled;
|
||||
aa_find_mountpoint;
|
||||
aa_change_hat; __old_change_hat;
|
||||
aa_change_hat;
|
||||
aa_change_hatv;
|
||||
aa_change_hat_vargs;
|
||||
aa_change_profile;
|
||||
@@ -37,7 +37,7 @@ APPARMOR_1.1 {
|
||||
free_record;
|
||||
aa_getprocattr_raw;
|
||||
aa_getprocattr;
|
||||
aa_query_label; __aa_query_label;
|
||||
aa_query_label;
|
||||
|
||||
# no more symbols here, please
|
||||
|
||||
@@ -47,7 +47,7 @@ APPARMOR_1.1 {
|
||||
|
||||
APPARMOR_2.9 {
|
||||
global:
|
||||
aa_query_label; query_label;
|
||||
aa_query_label;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_1.1;
|
||||
|
@@ -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",
|
||||
|
@@ -72,7 +72,7 @@ void string_buf_append(unsigned int length, char *text)
|
||||
|
||||
%}
|
||||
|
||||
ws [ \t\r\n\x1d]
|
||||
ws [ \t\r\n]
|
||||
|
||||
equals "="
|
||||
digit [[:digit:]]
|
||||
@@ -121,8 +121,6 @@ key_namespace "namespace"
|
||||
key_mask "mask"
|
||||
key_denied_mask "denied_mask"
|
||||
key_requested_mask "requested_mask"
|
||||
key_denied "denied"
|
||||
key_requested "requested"
|
||||
key_attribute "attribute"
|
||||
key_task "task"
|
||||
key_parent "parent"
|
||||
@@ -140,9 +138,7 @@ key_sock_type "sock_type"
|
||||
key_protocol "protocol"
|
||||
key_error "error"
|
||||
key_fsuid "fsuid"
|
||||
key_fsuid_upper "FSUID"
|
||||
key_ouid "ouid"
|
||||
key_ouid_upper "OUID"
|
||||
key_uid "uid"
|
||||
key_auid "auid"
|
||||
key_sauid "sauid"
|
||||
@@ -165,20 +161,17 @@ key_dest "dest"
|
||||
key_path "path"
|
||||
key_interface "interface"
|
||||
key_member "member"
|
||||
key_method "method"
|
||||
key_signal "signal"
|
||||
key_peer "peer"
|
||||
key_fstype "fstype"
|
||||
key_flags "flags"
|
||||
key_srcname "srcname"
|
||||
key_class "class"
|
||||
audit "audit"
|
||||
|
||||
/* network addrs */
|
||||
ip_addr [a-f[:digit:].:]{3,}
|
||||
|
||||
/* syslog tokens */
|
||||
socklogd_kernel kern.notice{colon}
|
||||
syslog_kernel kernel{colon}
|
||||
syslog_user [[:alnum:]_-]+\[[[:digit:]]+\]{colon}
|
||||
syslog_yyyymmdd {digit}{4}{minus}{digit}{2}{minus}{digit}{2}
|
||||
@@ -313,8 +306,6 @@ yy_flex_debug = 0;
|
||||
{key_mask} { return(TOK_KEY_MASK); }
|
||||
{key_denied_mask} { return(TOK_KEY_DENIED_MASK); }
|
||||
{key_requested_mask} { return(TOK_KEY_REQUESTED_MASK); }
|
||||
{key_denied} { return(TOK_KEY_DENIED_MASK); }
|
||||
{key_requested} { return(TOK_KEY_REQUESTED_MASK); }
|
||||
{key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
|
||||
{key_task} { return(TOK_KEY_TASK); }
|
||||
{key_parent} { return(TOK_KEY_PARENT); }
|
||||
@@ -332,9 +323,7 @@ yy_flex_debug = 0;
|
||||
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
||||
{key_error} { return(TOK_KEY_ERROR); }
|
||||
{key_fsuid} { return(TOK_KEY_FSUID); }
|
||||
{key_fsuid_upper} { return(TOK_KEY_FSUID_UPPER); }
|
||||
{key_ouid} { return(TOK_KEY_OUID); }
|
||||
{key_ouid_upper} { return(TOK_KEY_OUID_UPPER); }
|
||||
{key_uid} { return(TOK_KEY_UID); }
|
||||
{key_auid} { return(TOK_KEY_AUID); }
|
||||
{key_sauid} { return(TOK_KEY_SAUID); }
|
||||
@@ -356,15 +345,12 @@ yy_flex_debug = 0;
|
||||
{key_path} { return(TOK_KEY_PATH); }
|
||||
{key_interface} { return(TOK_KEY_INTERFACE); }
|
||||
{key_member} { return(TOK_KEY_MEMBER); }
|
||||
{key_method} { return(TOK_KEY_MEMBER); }
|
||||
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
|
||||
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
|
||||
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
||||
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
||||
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
||||
{key_class} { BEGIN(safe_string); return(TOK_KEY_CLASS); }
|
||||
|
||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
|
||||
{syslog_user} { return(TOK_SYSLOG_USER); }
|
||||
{syslog_month} { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
|
||||
@@ -379,7 +365,6 @@ yy_flex_debug = 0;
|
||||
|
||||
<hostname>{
|
||||
{ws}+ { /* eat whitespace */ }
|
||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||
{syslog_hostname} { yylval->t_str = strdup(yytext); BEGIN(INITIAL); return(TOK_ID); }
|
||||
}
|
||||
|
||||
|
@@ -135,7 +135,7 @@ static int do_test_walk_one(const char **str, const struct component *component,
|
||||
|
||||
static int test_walk_one(void)
|
||||
{
|
||||
struct component c = (struct component) { NULL, 0 };
|
||||
struct component c;
|
||||
const char *str;
|
||||
int rc = 0;
|
||||
|
||||
|
@@ -55,7 +55,7 @@ extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||
extern int aa_getcon(char **label, char **mode);
|
||||
extern int aa_getpeercon_raw(int fd, char *buf, socklen_t *len, char **mode);
|
||||
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||
int *audit);
|
||||
|
@@ -21,7 +21,7 @@ install-exec-local:
|
||||
|
||||
clean-local:
|
||||
if test -x "$(PYTHON)"; then $(PYTHON) setup.py clean; fi
|
||||
rm -rf build LibAppArmor.egg-info
|
||||
rm -rf build
|
||||
if test $(top_srcdir) != $(top_builddir) ; then rm -f libapparmor_wrap.c ; fi
|
||||
|
||||
endif
|
||||
|
@@ -1 +1,6 @@
|
||||
from LibAppArmor.LibAppArmor import *
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
from LibAppArmor.LibAppArmor import *
|
||||
else:
|
||||
from .LibAppArmor import *
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from setuptools import setup, Extension
|
||||
from distutils.core import setup, Extension
|
||||
import string
|
||||
|
||||
setup(name = 'LibAppArmor',
|
||||
|
@@ -10,7 +10,8 @@ test_python.py: test_python.py.in $(top_builddir)/config.status
|
||||
|
||||
CLEANFILES = test_python.py
|
||||
|
||||
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
|
||||
# bah, how brittle is this?
|
||||
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")'
|
||||
|
||||
TESTS = test_python.py
|
||||
TESTS_ENVIRONMENT = \
|
||||
|
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# the build path has changed in setuptools 62.1:
|
||||
# https://github.com/pypa/setuptools/commit/1c23f5e1e4b18b50081cbabb2dea22bf345f5894
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
import setuptools
|
||||
|
||||
|
||||
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
||||
identifier = sys.implementation.cache_tag
|
||||
else:
|
||||
identifier = "%d.%d" % sys.version_info[:2]
|
||||
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))
|
@@ -13,7 +13,6 @@
|
||||
import ctypes
|
||||
import os
|
||||
import unittest
|
||||
|
||||
import LibAppArmor as libapparmor
|
||||
|
||||
TESTDIR = "../../../testsuite/test_multi"
|
||||
@@ -35,7 +34,6 @@ OUTPUT_MAP = {
|
||||
'Local port': 'net_local_port',
|
||||
'Foreign port': 'net_foreign_port',
|
||||
'Audit subid': 'audit_sub_id',
|
||||
'Class': '_class',
|
||||
}
|
||||
|
||||
# FIXME: pull this automatically out of LibAppArmor, but swig
|
||||
@@ -77,11 +75,11 @@ class AAPythonBindingsTests(unittest.TestCase):
|
||||
|
||||
expected = self.parse_output_file(outfile)
|
||||
self.assertEqual(expected, record,
|
||||
"expected records did not match\n"
|
||||
"expected = %s\nactual = %s" % (expected, record))
|
||||
"expected records did not match\n" +
|
||||
"expected = %s\nactual = %s" % (expected, record))
|
||||
|
||||
def parse_output_file(self, outfile):
|
||||
"""parse testcase .out file and return dict"""
|
||||
'''parse testcase .out file and return dict'''
|
||||
|
||||
output = dict()
|
||||
with open(os.path.join(TESTDIR, outfile), 'r') as f:
|
||||
@@ -107,10 +105,10 @@ class AAPythonBindingsTests(unittest.TestCase):
|
||||
return output
|
||||
|
||||
def create_record_dict(self, record):
|
||||
"""parse the swig created record and construct a dict from it"""
|
||||
'''parse the swig created record and construct a dict from it'''
|
||||
|
||||
new_record = dict()
|
||||
for key in [x for x in dir(record) if not (x.startswith('__') or x == 'this')]:
|
||||
for key in [x for x in dir(record) if not (x.startswith('_') or x == 'this')]:
|
||||
value = getattr(record, key)
|
||||
if key == "event" and value in EVENT_MAP:
|
||||
new_record[key] = EVENT_MAP[value]
|
||||
@@ -130,7 +128,7 @@ class AAPythonBindingsTests(unittest.TestCase):
|
||||
|
||||
|
||||
def find_testcases(testdir):
|
||||
"""dig testcases out of passed directory"""
|
||||
'''dig testcases out of passed directory'''
|
||||
|
||||
for f in os.listdir(testdir):
|
||||
if f.endswith(".in"):
|
||||
@@ -145,6 +143,5 @@ def main():
|
||||
setattr(AAPythonBindingsTests, 'test_%s' % (f), stub_test)
|
||||
return unittest.main(verbosity=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -9,9 +9,7 @@ LibAppArmor_wrap.c : $(srcdir)/../SWIG/libapparmor.i
|
||||
MOSTLYCLEANFILES=LibAppArmor_wrap.c
|
||||
|
||||
Makefile.ruby: extconf.rb
|
||||
mv Makefile Makefile.bak
|
||||
PREFIX=$(prefix) $(RUBY) $< --with-LibAppArmor-include=$(top_srcdir)/include
|
||||
mv Makefile.bak Makefile
|
||||
|
||||
LibAppArmor.so: LibAppArmor_wrap.c Makefile.ruby
|
||||
$(MAKE) -fMakefile.ruby
|
||||
@@ -24,7 +22,7 @@ install-exec-local: Makefile.ruby
|
||||
|
||||
clean-local:
|
||||
if test -f Makefile.ruby; then $(MAKE) -fMakefile.ruby clean; fi
|
||||
rm -f Makefile.ruby Makefile.bak
|
||||
rm -f Makefile.ruby Makefile.new
|
||||
rm -f *.o *.so *.log
|
||||
|
||||
endif
|
||||
|
@@ -2,8 +2,16 @@
|
||||
|
||||
require 'mkmf'
|
||||
|
||||
# hack 1: Before extconf.rb gets called, Makefile gets backed up, and
|
||||
# restored afterwards (see Makefile.am)
|
||||
# hack 1: ruby black magic to write a Makefile.new instead of a Makefile
|
||||
alias open_orig open
|
||||
def open(path, mode=nil, perm=nil)
|
||||
path = 'Makefile.new' if path == 'Makefile'
|
||||
if block_given?
|
||||
open_orig(path, mode, perm) { |io| yield(io) }
|
||||
else
|
||||
open_orig(path, mode, perm)
|
||||
end
|
||||
end
|
||||
|
||||
if ENV['PREFIX']
|
||||
prefix = CONFIG['prefix']
|
||||
@@ -19,7 +27,7 @@ if find_library('apparmor', 'parse_record', '../../src/.libs') and
|
||||
|
||||
# hack 2: strip all rpath references
|
||||
open('Makefile.ruby', 'w') do |out|
|
||||
IO.foreach('Makefile') do |line|
|
||||
IO.foreach('Makefile.new') do |line|
|
||||
out.puts line.gsub(/-Wl,-R'[^']*'/, '')
|
||||
end
|
||||
end
|
||||
|
@@ -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:
|
||||
#
|
||||
|
@@ -134,8 +134,6 @@ int print_results(aa_log_record *record)
|
||||
print_string("Flags", record->flags);
|
||||
print_string("Src name", record->src_name);
|
||||
|
||||
print_string("Class", record->class);
|
||||
|
||||
print_long("Epoch", record->epoch, 0);
|
||||
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
||||
return(0);
|
||||
|
@@ -1 +0,0 @@
|
||||
type=AVC msg=audit(1661734785.992:270): apparmor="ALLOWED" operation="open" profile="/usr/bin/dolphin" name="/home/otis/.config/kdedefaults/kdeglobals" pid=3483 comm="dolphin" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="otis" OUID="root"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: 0x1d-uppercase-FSUID-OUID.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1661734785.992:270
|
||||
Operation: open
|
||||
Mask: r
|
||||
Denied Mask: r
|
||||
fsuid: 1000
|
||||
ouid: 0
|
||||
Profile: /usr/bin/dolphin
|
||||
Name: /home/otis/.config/kdedefaults/kdeglobals
|
||||
Command: dolphin
|
||||
PID: 3483
|
||||
Epoch: 1661734785
|
||||
Audit subid: 270
|
@@ -1,4 +0,0 @@
|
||||
/usr/bin/dolphin {
|
||||
/home/otis/.config/kdedefaults/kdeglobals r,
|
||||
|
||||
}
|
@@ -1 +0,0 @@
|
||||
type=AVC msg=audit(1676978994.840:1493): apparmor="DENIED" operation="link" profile="cargo" name="/var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib" pid=12412 comm="cargo" requested_mask="xm" denied_mask="xm" fsuid=250 ouid=250 target="/var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/deps/libbootstrap-4542dd99e796257e.rlib"FSUID="portage" OUID="portage"
|
@@ -1,16 +0,0 @@
|
||||
START
|
||||
File: file_xm.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1676978994.840:1493
|
||||
Operation: link
|
||||
Mask: xm
|
||||
Denied Mask: xm
|
||||
fsuid: 250
|
||||
ouid: 250
|
||||
Profile: cargo
|
||||
Name: /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib
|
||||
Command: cargo
|
||||
Name2: /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/deps/libbootstrap-4542dd99e796257e.rlib
|
||||
PID: 12412
|
||||
Epoch: 1676978994
|
||||
Audit subid: 1493
|
@@ -1,4 +0,0 @@
|
||||
profile cargo {
|
||||
owner /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib m,
|
||||
|
||||
}
|
@@ -1 +0,0 @@
|
||||
audit.log:type=AVC msg=audit(1630913351.586:4): apparmor="STATUS" info="AppArmor Filesystem Enabled" pid=1 comm="swapper/0"
|
@@ -1,3 +0,0 @@
|
||||
START
|
||||
File: status-filesystem-enabled.in
|
||||
Event type: AA_RECORD_INVALID
|
@@ -1 +0,0 @@
|
||||
Dec 15 17:32:17 kinetic kernel: [4835959.046111] audit: type=1107 audit(1671125537.724:209): pid=7308 uid=0 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call" bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" method="Hello" mask="send" label="/tmp/apparmor/tests/regression/apparmor/dbus_message" peer_label="unconfined" exe="/usr/local/bin/dbus-broker" sauid=0 hostname=? addr=? terminal=?'
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_dbus_11.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1671125537.724:209
|
||||
Operation: dbus_method_call
|
||||
Denied Mask: send
|
||||
Profile: /tmp/apparmor/tests/regression/apparmor/dbus_message
|
||||
Peer profile: unconfined
|
||||
Command: /usr/local/bin/dbus-broker
|
||||
DBus bus: session
|
||||
DBus path: /org/freedesktop/DBus
|
||||
DBus interface: org.freedesktop.DBus
|
||||
DBus member: Hello
|
||||
Epoch: 1671125537
|
||||
Audit subid: 209
|
@@ -1,4 +0,0 @@
|
||||
/tmp/apparmor/tests/regression/apparmor/dbus_message {
|
||||
dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello peer=(label=unconfined),
|
||||
|
||||
}
|
@@ -1 +0,0 @@
|
||||
2021-09-11T20:57:41.91645 kern.notice: [ 469.180605] audit: type=1400 audit(1631392703.952:3): apparmor="ALLOWED" operation="mkdir" profile="/usr/sbin/sshd" name="/run/user/1000/kakoune/" pid=2545 comm="sshd" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_socklogd_mkdir.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1631392703.952:3
|
||||
Operation: mkdir
|
||||
Mask: c
|
||||
Denied Mask: c
|
||||
fsuid: 1000
|
||||
ouid: 1000
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /run/user/1000/kakoune/
|
||||
Command: sshd
|
||||
PID: 2545
|
||||
Epoch: 1631392703
|
||||
Audit subid: 3
|
@@ -1,4 +0,0 @@
|
||||
/usr/sbin/sshd {
|
||||
owner /run/user/1000/kakoune/ w,
|
||||
|
||||
}
|
@@ -70,11 +70,6 @@ CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
|
||||
endif
|
||||
endif #CFLAGS
|
||||
|
||||
HAVE_FLTO_PARTITION_NONE:=$(shell ${CC} -E -flto-partition=none /dev/null 1>/dev/null 2>&1 && echo true)
|
||||
ifeq ($(HAVE_FLTO_PARTITION_NONE),true)
|
||||
CFLAGS += -flto-partition=none
|
||||
endif
|
||||
|
||||
EXTRA_CXXFLAGS = ${CFLAGS} ${CPPFLAGS} ${CXX_WARNINGS} -std=gnu++0x
|
||||
EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
|
||||
|
||||
@@ -312,18 +307,10 @@ parser_version.h: Makefile
|
||||
# as well as the filtering that occurs for network protocols that
|
||||
# apparmor should not mediate.
|
||||
|
||||
generated_af_names.h: ../common/list_af_names.sh
|
||||
../common/list_af_names.sh > $@
|
||||
|
||||
af_names.h: generated_af_names.h base_af_names.h
|
||||
cat base_af_names.h | diff -u - generated_af_names.h | grep -v '^.AF_MAX' | grep '^\+[^+]' ; \
|
||||
if [ $$? -eq 1 ] ; then \
|
||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@ ; \
|
||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@ ; \
|
||||
else \
|
||||
echo "Error: new AF names detected; please update base_af_names.h with values from generated_af_names.h" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
af_names.h: ../common/list_af_names.sh
|
||||
../common/list_af_names.sh | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@
|
||||
../common/list_af_names.sh | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@
|
||||
# cat $@
|
||||
|
||||
generated_cap_names.h: /usr/include/linux/capability.h
|
||||
../common/list_capabilities.sh | LC_ALL=C sed -n -e "s/[ \\t]\\?CAP_\\([A-Z0-9_]\\+\\)/\{\"\\L\\1\", \\UCAP_\\1, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE\},\\n/pg" > $@
|
||||
@@ -355,8 +342,13 @@ tests: apparmor_parser ${TESTS}
|
||||
$(AAREOBJECT): FORCE
|
||||
$(MAKE) -C $(AAREDIR) CFLAGS="$(EXTRA_CXXFLAGS)"
|
||||
|
||||
.PHONY: install-rhel4
|
||||
install-rhel4: install-redhat
|
||||
|
||||
.PHONY: install-redhat
|
||||
install-redhat: install-systemd
|
||||
install-redhat:
|
||||
install -m 755 -d $(DESTDIR)/etc/init.d
|
||||
install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
|
||||
|
||||
.PHONY: install-suse
|
||||
install-suse: install-systemd
|
||||
@@ -384,12 +376,12 @@ DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
|
||||
elif [ -f /etc/debian_version ] ; then \
|
||||
echo debian ;\
|
||||
elif which rpm > /dev/null ; then \
|
||||
if [ "$$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
||||
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
||||
echo suse ;\
|
||||
elif [ "$$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
||||
echo redhat ;\
|
||||
elif [ "$$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
||||
echo redhat ;\
|
||||
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
||||
echo rhel4 ;\
|
||||
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
||||
echo rhel4 ;\
|
||||
else \
|
||||
echo unknown ;\
|
||||
fi ;\
|
||||
@@ -419,7 +411,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}
|
||||
|
||||
@@ -443,7 +434,7 @@ clean: pod_clean
|
||||
rm -f $(YACC_C_FILES)
|
||||
rm -f parser_version.h
|
||||
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
||||
rm -f af_names.h generated_af_names.h
|
||||
rm -f af_names.h
|
||||
rm -f cap_names.h generated_cap_names.h
|
||||
rm -rf techdoc.aux techdoc.out techdoc.log techdoc.pdf techdoc.toc techdoc.txt techdoc/
|
||||
$(MAKE) -s -C $(AAREDIR) clean
|
||||
|
@@ -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)
|
||||
@@ -111,7 +111,8 @@ unix_rule::unix_rule(unsigned int type_p, bool audit_p, bool denied):
|
||||
|
||||
unix_rule::unix_rule(int mode_p, struct cond_entry *conds,
|
||||
struct cond_entry *peer_conds):
|
||||
af_rule("unix"), addr(NULL), peer_addr(NULL)
|
||||
af_rule("unix"), addr(NULL), peer_addr(NULL),
|
||||
audit(0), deny(0)
|
||||
{
|
||||
move_conditionals(conds);
|
||||
move_peer_conditionals(peer_conds);
|
||||
@@ -135,7 +136,7 @@ ostream &unix_rule::dump_local(ostream &os)
|
||||
{
|
||||
af_rule::dump_local(os);
|
||||
if (addr)
|
||||
os << " addr='" << addr << "'";
|
||||
os << "addr='" << addr << "'";
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ ostream &unix_rule::dump_peer(ostream &os)
|
||||
{
|
||||
af_rule::dump_peer(os);
|
||||
if (peer_addr)
|
||||
os << " addr='" << peer_addr << "'";
|
||||
os << "addr='" << peer_addr << "'";
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -325,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;
|
||||
}
|
||||
|
||||
@@ -355,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();
|
||||
@@ -376,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 */
|
||||
|
@@ -36,6 +36,9 @@ class unix_rule: public af_rule {
|
||||
public:
|
||||
char *addr;
|
||||
char *peer_addr;
|
||||
int mode;
|
||||
int audit;
|
||||
bool deny;
|
||||
|
||||
unix_rule(unsigned int type_p, bool audit_p, bool denied);
|
||||
unix_rule(int mode, struct cond_entry *conds,
|
||||
|
@@ -148,7 +148,7 @@ capabilities(7))
|
||||
|
||||
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
||||
|
||||
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
|
||||
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' ) ','
|
||||
|
||||
B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
||||
|
||||
@@ -172,7 +172,7 @@ B<MOUNT FLAGS EXPRESSION> = ( I<MOUNT FLAGS LIST> | I<MOUNT EXPRESSION> )
|
||||
|
||||
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
|
||||
|
||||
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nostrictatime' | 'lazytime' | 'nolazytime' | 'nouser' | 'user' | 'symfollow' | 'nosymfollow' )
|
||||
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nouser' | 'user' )
|
||||
|
||||
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
||||
|
||||
@@ -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' )
|
||||
@@ -842,7 +842,7 @@ and other operations that are typically reserved for the root user.
|
||||
|
||||
AppArmor supports simple coarse grained network mediation. The network
|
||||
rule restrict all socket(2) based operations. The mediation done is
|
||||
a coarse-grained check on whether a socket of a given type and family
|
||||
a course grained check on whether a socket of a given type and family
|
||||
can be created, read, or written. There is no mediation based of port
|
||||
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
|
||||
only specify type 'dgram' and 'raw'.
|
||||
@@ -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
|
||||
@@ -1793,7 +1786,7 @@ An example AppArmor profile:
|
||||
/usr/lib/** r,
|
||||
/tmp/foo.pid wr,
|
||||
/tmp/foo.* lrw,
|
||||
@{HOME}/.foo_file rw,
|
||||
/@{HOME}/.foo_file rw,
|
||||
/usr/bin/baz Cx -> baz,
|
||||
|
||||
# a comment about foo's hat (subprofile), bar.
|
||||
|
@@ -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 exercised 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 parameter.
|
||||
|
||||
B<Warning> Setting complain mode globally 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 parameter.
|
||||
|
||||
=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 parameter.
|
||||
|
||||
=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 parameter.
|
||||
|
||||
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:
|
||||
|
||||
|
@@ -17,8 +17,6 @@
|
||||
|
||||
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_action()
|
||||
{
|
||||
echo "$1"
|
||||
@@ -27,50 +25,36 @@ aa_action()
|
||||
return $?
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_warning_msg()
|
||||
{
|
||||
echo "Warning: $*"
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_failure_msg()
|
||||
{
|
||||
echo "Error: $*"
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_action_start()
|
||||
{
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_action_end()
|
||||
{
|
||||
printf ""
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_daemon_msg()
|
||||
{
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_skipped_msg()
|
||||
{
|
||||
echo "Skipped: $*"
|
||||
}
|
||||
|
||||
# This function is used in rc.apparmor.functions
|
||||
# shellcheck disable=SC2317
|
||||
aa_log_end_msg()
|
||||
{
|
||||
printf ""
|
||||
@@ -87,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=$?
|
||||
;;
|
||||
@@ -102,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=$?
|
||||
;;
|
||||
|
@@ -299,11 +299,11 @@ Enable various warnings during policy compilation. A single warn flag
|
||||
can be specified per --warn option, but the --warn flag can be passed
|
||||
multiple times.
|
||||
|
||||
apparmor_parser --warn=rule-not-enforced ...
|
||||
apparmor_parser --warn=rules-not-enforced ...
|
||||
|
||||
A specific warning can be disabled by prepending I<no>- to the flag
|
||||
|
||||
apparmor_parser --warn=no-rule-not-enforced ...
|
||||
apparmor_parser --warn=no-rules-not-enforced ...
|
||||
|
||||
Use --help=warn to see a full list of which warn flags are supported.
|
||||
|
||||
@@ -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 aggressive 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
|
||||
@@ -451,7 +434,7 @@ Eg.
|
||||
|
||||
would result in Optimize=minimize being set.
|
||||
|
||||
The Include, Dump, and Optimize options accumulate except for the inversion
|
||||
The Include, Dump, and Optimize options accululate except for the inversion
|
||||
option (no-X vs. X), and a couple options that work by setting/clearing
|
||||
multiple options (compress-small). In that case the option will override
|
||||
the flags it sets but will may accumulate with others.
|
||||
|
@@ -1,46 +0,0 @@
|
||||
AF_UNSPEC 0,
|
||||
AF_UNIX 1,
|
||||
AF_INET 2,
|
||||
AF_AX25 3,
|
||||
AF_IPX 4,
|
||||
AF_APPLETALK 5,
|
||||
AF_NETROM 6,
|
||||
AF_BRIDGE 7,
|
||||
AF_ATMPVC 8,
|
||||
AF_X25 9,
|
||||
AF_INET6 10,
|
||||
AF_ROSE 11,
|
||||
AF_NETBEUI 13,
|
||||
AF_SECURITY 14,
|
||||
AF_KEY 15,
|
||||
AF_NETLINK 16,
|
||||
AF_PACKET 17,
|
||||
AF_ASH 18,
|
||||
AF_ECONET 19,
|
||||
AF_ATMSVC 20,
|
||||
AF_RDS 21,
|
||||
AF_SNA 22,
|
||||
AF_IRDA 23,
|
||||
AF_PPPOX 24,
|
||||
AF_WANPIPE 25,
|
||||
AF_LLC 26,
|
||||
AF_IB 27,
|
||||
AF_MPLS 28,
|
||||
AF_CAN 29,
|
||||
AF_TIPC 30,
|
||||
AF_BLUETOOTH 31,
|
||||
AF_IUCV 32,
|
||||
AF_RXRPC 33,
|
||||
AF_ISDN 34,
|
||||
AF_PHONET 35,
|
||||
AF_IEEE802154 36,
|
||||
AF_CAIF 37,
|
||||
AF_ALG 38,
|
||||
AF_NFC 39,
|
||||
AF_VSOCK 40,
|
||||
AF_KCM 41,
|
||||
AF_QIPCRTR 42,
|
||||
AF_SMC 43,
|
||||
AF_XDP 44,
|
||||
AF_MCTP 45,
|
||||
AF_MAX 46,
|
@@ -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 << " -> ";
|
||||
|
@@ -193,8 +193,9 @@ void CHFA::insert_state(vector<pair<size_t, size_t> > &free_list,
|
||||
State *default_state = dfa.nonmatching;
|
||||
ssize_t base = 0;
|
||||
int resize;
|
||||
|
||||
StateTrans &trans = from->trans;
|
||||
ssize_t c;
|
||||
ssize_t c = trans.begin()->first.c;
|
||||
ssize_t prev = 0;
|
||||
ssize_t x = first_free;
|
||||
|
||||
@@ -203,7 +204,6 @@ void CHFA::insert_state(vector<pair<size_t, size_t> > &free_list,
|
||||
if (trans.empty())
|
||||
goto do_insert;
|
||||
|
||||
c = trans.begin()->first.c;
|
||||
repeat:
|
||||
resize = 0;
|
||||
/* get the first free entry that won't underflow */
|
||||
@@ -251,18 +251,10 @@ repeat:
|
||||
first_free = next;
|
||||
}
|
||||
|
||||
/* these flags will only be set on states that have transitions */
|
||||
do_insert:
|
||||
if (c < 0) {
|
||||
base |= MATCH_FLAG_OOB_TRANSITION;
|
||||
}
|
||||
do_insert:
|
||||
/* While a state without transitions could have the diff encode
|
||||
* flag set, it would be pointless resulting in just an extra
|
||||
* state transition in the encoding chain, and so it should be
|
||||
* considered an error
|
||||
* TODO: add check that state without transitions isn't being
|
||||
* given a diffencode flag
|
||||
*/
|
||||
if (from->flags & DiffEncodeFlag)
|
||||
base |= DiffEncodeBit32;
|
||||
default_base.push_back(make_pair(default_state, base));
|
||||
|
@@ -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
|
||||
@@ -189,19 +189,6 @@ void Node::dump_syntax_tree(ostream &os)
|
||||
* a b c T
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static Node *simplify_eps_pair(Node *t)
|
||||
{
|
||||
if (t->is_type(NODE_TYPE_TWOCHILD) &&
|
||||
t->child[0] == &epsnode &&
|
||||
t->child[1] == &epsnode) {
|
||||
t->release();
|
||||
return &epsnode;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static void rotate_node(Node *t, int dir)
|
||||
{
|
||||
// (a | b) | c -> a | (b | c)
|
||||
@@ -210,9 +197,7 @@ static void rotate_node(Node *t, int dir)
|
||||
t->child[dir] = left->child[dir];
|
||||
left->child[dir] = left->child[!dir];
|
||||
left->child[!dir] = t->child[!dir];
|
||||
|
||||
// check that rotation didn't create (E | E)
|
||||
t->child[!dir] = simplify_eps_pair(left);
|
||||
t->child[!dir] = left;
|
||||
}
|
||||
|
||||
/* return False if no work done */
|
||||
@@ -224,7 +209,13 @@ int TwoChildNode::normalize_eps(int dir)
|
||||
// Ea -> aE
|
||||
// Test for E | (E | E) and E . (E . E) which will
|
||||
// result in an infinite loop
|
||||
Node *c = simplify_eps_pair(child[!dir]);
|
||||
Node *c = child[!dir];
|
||||
if (dynamic_cast<TwoChildNode *>(c) &&
|
||||
&epsnode == c->child[dir] &&
|
||||
&epsnode == c->child[!dir]) {
|
||||
c->release();
|
||||
c = &epsnode;
|
||||
}
|
||||
child[!dir] = child[dir];
|
||||
child[dir] = c;
|
||||
return 1;
|
||||
@@ -238,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 {
|
||||
@@ -257,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];
|
||||
@@ -353,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])) {
|
||||
@@ -364,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];
|
||||
@@ -378,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();
|
||||
@@ -388,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();
|
||||
@@ -403,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;
|
||||
@@ -428,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++) {
|
||||
@@ -451,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;
|
||||
@@ -484,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;
|
||||
@@ -511,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) {
|
||||
@@ -537,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])
|
||||
@@ -548,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++;
|
||||
}
|
||||
}
|
||||
@@ -644,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; }
|
||||
|
737
parser/mount.cc
737
parser/mount.cc
@@ -98,9 +98,6 @@
|
||||
* nomand
|
||||
* #define MS_DIRSYNC 128 Directory modifications are synchronous
|
||||
* dirsync
|
||||
* #define MS_NOSYMFOLLOW 256 Do not follow symlinks
|
||||
* symfollow
|
||||
* nosymfollow
|
||||
* #define MS_NOATIME 1024 Do not update access times
|
||||
* noatime
|
||||
* atime
|
||||
@@ -142,9 +139,6 @@
|
||||
* #define MS_STRICTATIME (1<<24) Always perform atime updates
|
||||
* strictatime
|
||||
* nostrictatime
|
||||
* #define MS_LAZYTIME (1<<25) Update the on-disk [acm]times lazily
|
||||
* lazytime
|
||||
* nolazytime
|
||||
* #define MS_NOSEC (1<<28)
|
||||
* #define MS_BORN (1<<29)
|
||||
* #define MS_ACTIVE (1<<30)
|
||||
@@ -212,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.
|
||||
*
|
||||
*
|
||||
@@ -252,8 +246,6 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
||||
{"mand", MS_MAND, 0},
|
||||
{"nomand", 0, MS_MAND},
|
||||
{"dirsync", MS_DIRSYNC, 0},
|
||||
{"symfollow", 0, MS_NOSYMFOLLOW},
|
||||
{"nosymfollow", MS_NOSYMFOLLOW, 0},
|
||||
{"atime", 0, MS_NOATIME},
|
||||
{"noatime", MS_NOATIME, 0},
|
||||
{"diratime", 0, MS_NODIRATIME},
|
||||
@@ -291,9 +283,6 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
||||
{"iversion", MS_IVERSION, 0},
|
||||
{"noiversion", 0, MS_IVERSION},
|
||||
{"strictatime", MS_STRICTATIME, 0},
|
||||
{"nostrictatime", 0, MS_STRICTATIME},
|
||||
{"lazytime", MS_LAZYTIME, 0},
|
||||
{"nolazytime", 0, MS_LAZYTIME},
|
||||
{"user", 0, (unsigned int) MS_NOUSER},
|
||||
{"nouser", (unsigned int) MS_NOUSER, 0},
|
||||
|
||||
@@ -309,22 +298,6 @@ static struct mnt_keyword_table mnt_conds_table[] = {
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
static ostream &dump_flags(ostream &os,
|
||||
pair <unsigned int, unsigned int> flags)
|
||||
{
|
||||
for (int i = 0; mnt_opts_table[i].keyword; i++) {
|
||||
if ((flags.first & mnt_opts_table[i].set) ||
|
||||
(flags.second & mnt_opts_table[i].clear))
|
||||
os << mnt_opts_table[i].keyword;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream &os, pair<unsigned int, unsigned int> flags)
|
||||
{
|
||||
return dump_flags(os, flags);
|
||||
}
|
||||
|
||||
static int find_mnt_keyword(struct mnt_keyword_table *table, const char *name)
|
||||
{
|
||||
int i;
|
||||
@@ -347,7 +320,7 @@ int is_valid_mnt_cond(const char *name, int src)
|
||||
|
||||
static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
||||
{
|
||||
unsigned int flags = 0, invflags = 0;
|
||||
unsigned int flags = 0;
|
||||
*inv = 0;
|
||||
|
||||
struct value_list *entry, *tmp, *prev = NULL;
|
||||
@@ -356,11 +329,11 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
||||
i = find_mnt_keyword(mnt_opts_table, entry->value);
|
||||
if (i != -1) {
|
||||
flags |= mnt_opts_table[i].set;
|
||||
invflags |= mnt_opts_table[i].clear;
|
||||
*inv |= mnt_opts_table[i].clear;
|
||||
PDEBUG(" extracting mount flag %s req: 0x%x inv: 0x%x"
|
||||
" => req: 0x%x inv: 0x%x\n",
|
||||
entry->value, mnt_opts_table[i].set,
|
||||
mnt_opts_table[i].clear, flags, invflags);
|
||||
mnt_opts_table[i].clear, flags, *inv);
|
||||
if (prev)
|
||||
prev->next = tmp;
|
||||
if (entry == *list)
|
||||
@@ -371,27 +344,9 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
||||
prev = entry;
|
||||
}
|
||||
|
||||
if (inv)
|
||||
*inv = invflags;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static bool conflicting_flags(unsigned int flags, unsigned int inv)
|
||||
{
|
||||
if (flags & inv) {
|
||||
for (int i = 0; i < 31; i++) {
|
||||
unsigned int mask = 1 << i;
|
||||
if ((flags & inv) & mask) {
|
||||
cerr << "conflicting flag values = "
|
||||
<< flags << ", " << inv << "\n";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct value_list *extract_fstype(struct cond_entry **conds)
|
||||
{
|
||||
struct value_list *list = NULL;
|
||||
@@ -414,19 +369,22 @@ static struct value_list *extract_fstype(struct cond_entry **conds)
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct cond_entry *extract_options(struct cond_entry **conds, int eq)
|
||||
static struct value_list *extract_options(struct cond_entry **conds, int eq)
|
||||
{
|
||||
struct cond_entry *list = NULL, *entry, *tmp, *prev = NULL;
|
||||
struct value_list *list = NULL;
|
||||
|
||||
struct cond_entry *entry, *tmp, *prev = NULL;
|
||||
|
||||
list_for_each_safe(*conds, entry, tmp) {
|
||||
if ((strcmp(entry->name, "options") == 0 ||
|
||||
strcmp(entry->name, "option") == 0) &&
|
||||
entry->eq == eq) {
|
||||
list_remove_at(*conds, prev, entry);
|
||||
PDEBUG(" extracting %s %s\n", entry->name, entry->eq ?
|
||||
"=" : "in");
|
||||
list_append(entry, list);
|
||||
list = entry;
|
||||
PDEBUG(" extracting option %s\n", entry->name);
|
||||
list_append(entry->vals, list);
|
||||
list = entry->vals;
|
||||
entry->vals = NULL;
|
||||
free_cond_entry(entry);
|
||||
} else
|
||||
prev = entry;
|
||||
}
|
||||
@@ -434,129 +392,60 @@ static struct cond_entry *extract_options(struct cond_entry **conds, int eq)
|
||||
return list;
|
||||
}
|
||||
|
||||
static void perror_conds(const char *rule, struct cond_entry *conds)
|
||||
{
|
||||
struct cond_entry *entry;
|
||||
|
||||
list_for_each(conds, entry) {
|
||||
PERROR( "unsupported %s condition '%s%s(...)'\n", rule, entry->name, entry->eq ? "=" : " in ");
|
||||
}
|
||||
}
|
||||
|
||||
static void perror_vals(const char *rule, struct value_list *vals)
|
||||
{
|
||||
struct value_list *entry;
|
||||
|
||||
list_for_each(vals, entry) {
|
||||
PERROR( "unsupported %s value '%s'\n", rule, entry->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_one_option(struct cond_entry *&opts, unsigned int &flags,
|
||||
unsigned int &inv_flags)
|
||||
{
|
||||
struct cond_entry *entry;
|
||||
struct value_list *vals;
|
||||
|
||||
entry = list_pop(opts);
|
||||
vals = entry->vals;
|
||||
entry->vals = NULL;
|
||||
/* fail if there are any unknown optional flags */
|
||||
if (opts) {
|
||||
PERROR(" unsupported multiple 'mount options %s(...)'\n", entry->eq ? "=" : " in ");
|
||||
exit(1);
|
||||
}
|
||||
free_cond_entry(entry);
|
||||
|
||||
flags = extract_flags(&vals, &inv_flags);
|
||||
if (vals) {
|
||||
perror_vals("mount option", vals);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
|
||||
struct cond_entry *dst_conds unused, char *mnt_point_p,
|
||||
int allow_p):
|
||||
mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
|
||||
flagsv(0), opt_flagsv(0), audit(0), deny(0)
|
||||
flags(0), inv_flags(0), audit(0), deny(0)
|
||||
{
|
||||
/* FIXME: dst_conds are ignored atm */
|
||||
dev_type = extract_fstype(&src_conds);
|
||||
|
||||
if (src_conds) {
|
||||
/* move options in () to local list */
|
||||
struct cond_entry *opts_in = extract_options(&src_conds, 0);
|
||||
struct value_list *list = extract_options(&src_conds, 0);
|
||||
|
||||
if (opts_in) {
|
||||
unsigned int tmpflags = 0, tmpinv_flags = 0;
|
||||
struct cond_entry *entry;
|
||||
opts = extract_options(&src_conds, 1);
|
||||
if (opts)
|
||||
flags = extract_flags(&opts, &inv_flags);
|
||||
|
||||
while ((entry = list_pop(opts_in))) {
|
||||
process_one_option(entry, tmpflags,
|
||||
tmpinv_flags);
|
||||
/* optional flags if set/clear mean the same
|
||||
* thing and can be represented by a single
|
||||
* bitset, also there is no need to check for
|
||||
* conflicting flags when they are optional
|
||||
*/
|
||||
opt_flagsv.push_back(tmpflags | tmpinv_flags);
|
||||
}
|
||||
if (list) {
|
||||
unsigned int tmpflags, tmpinv_flags = 0;
|
||||
|
||||
tmpflags = extract_flags(&list, &tmpinv_flags);
|
||||
/* these flags are optional so set both */
|
||||
tmpflags |= tmpinv_flags;
|
||||
tmpinv_flags |= tmpflags;
|
||||
|
||||
flags |= tmpflags;
|
||||
inv_flags |= tmpinv_flags;
|
||||
|
||||
if (opts)
|
||||
list_append(opts, list);
|
||||
else if (list)
|
||||
opts = list;
|
||||
}
|
||||
|
||||
/* move options=() to opts list */
|
||||
struct cond_entry *opts_eq = extract_options(&src_conds, 1);
|
||||
if (opts_eq) {
|
||||
unsigned int tmpflags = 0, tmpinv_flags = 0;
|
||||
struct cond_entry *entry;
|
||||
|
||||
while ((entry = list_pop(opts_eq))) {
|
||||
process_one_option(entry, tmpflags,
|
||||
tmpinv_flags);
|
||||
/* throw away tmpinv_flags, only needed in
|
||||
* consistancy check
|
||||
*/
|
||||
if (allow_p & AA_DUMMY_REMOUNT)
|
||||
tmpflags |= MS_REMOUNT;
|
||||
|
||||
if (conflicting_flags(tmpflags, tmpinv_flags)) {
|
||||
PERROR("conflicting flags in the rule\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
flagsv.push_back(tmpflags);
|
||||
}
|
||||
}
|
||||
|
||||
if (src_conds) {
|
||||
perror_conds("mount", src_conds);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flagsv.size() + opt_flagsv.size())) {
|
||||
/* no flag options, and not remount, allow everything */
|
||||
if (allow_p & AA_DUMMY_REMOUNT) {
|
||||
flagsv.push_back(MS_REMOUNT);
|
||||
opt_flagsv.push_back(MS_REMOUNT_FLAGS & ~MS_REMOUNT);
|
||||
} else {
|
||||
flagsv.push_back(MS_ALL_FLAGS);
|
||||
opt_flagsv.push_back(MS_ALL_FLAGS);
|
||||
}
|
||||
} else if (!(flagsv.size())) {
|
||||
/* no flags but opts set */
|
||||
if (allow_p & AA_DUMMY_REMOUNT)
|
||||
flagsv.push_back(MS_REMOUNT);
|
||||
else
|
||||
flagsv.push_back(0);
|
||||
} else if (!(opt_flagsv.size())) {
|
||||
opt_flagsv.push_back(0);
|
||||
}
|
||||
|
||||
if (allow_p & AA_DUMMY_REMOUNT) {
|
||||
allow_p = AA_MAY_MOUNT;
|
||||
flags |= MS_REMOUNT;
|
||||
inv_flags = 0;
|
||||
} else if (!(flags | inv_flags)) {
|
||||
/* no flag options, and not remount, allow everything */
|
||||
flags = MS_ALL_FLAGS;
|
||||
inv_flags = MS_ALL_FLAGS;
|
||||
}
|
||||
|
||||
allow = allow_p;
|
||||
|
||||
if (src_conds) {
|
||||
PERROR(" unsupported mount conditions\n");
|
||||
exit(1);
|
||||
}
|
||||
if (opts) {
|
||||
PERROR(" unsupported mount options\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ostream &mnt_rule::dump(ostream &os)
|
||||
@@ -568,13 +457,9 @@ ostream &mnt_rule::dump(ostream &os)
|
||||
else if (allow & AA_MAY_PIVOTROOT)
|
||||
os << "pivotroot";
|
||||
else
|
||||
os << "error: unknown mount perm";
|
||||
|
||||
for (unsigned int i = 0; i < flagsv.size(); i++)
|
||||
os << " flags=(0x" << hex << flagsv[i] << ")";
|
||||
for (unsigned int i = 0; i < opt_flagsv.size(); i++)
|
||||
os << " flags in (0x" << hex << opt_flagsv[i] << ")";
|
||||
os << "error: unknonwn mount perm";
|
||||
|
||||
os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
|
||||
if (dev_type) {
|
||||
os << " type=";
|
||||
print_value_list(dev_type);
|
||||
@@ -630,7 +515,7 @@ int mnt_rule::expand_variables(void)
|
||||
}
|
||||
|
||||
static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
unsigned int opt_flags)
|
||||
unsigned int inv_flags)
|
||||
{
|
||||
char *p = buffer;
|
||||
int i, len = 0;
|
||||
@@ -643,7 +528,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
return TRUE;
|
||||
}
|
||||
for (i = 0; i <= 31; ++i) {
|
||||
if ((opt_flags) & (1 << i))
|
||||
if ((flags & inv_flags) & (1 << i))
|
||||
len = snprintf(p, size, "(\\x%02x|)", i + 1);
|
||||
else if (flags & (1 << i))
|
||||
len = snprintf(p, size, "\\x%02x", i + 1);
|
||||
@@ -698,331 +583,17 @@ void mnt_rule::warn_once(const char *name)
|
||||
rule_t::warn_once(name, "mount rules not enforce");
|
||||
}
|
||||
|
||||
|
||||
int mnt_rule::gen_policy_remount(Profile &prof, int &count,
|
||||
unsigned int flags, unsigned int opt_flags)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
int tmpallow;
|
||||
|
||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||
|
||||
/* remount can't be conditional on device and type */
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (mnt_point) {
|
||||
/* both device && mnt_point or just mnt_point */
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
} else {
|
||||
if (!convert_entry(mntbuf, device))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
}
|
||||
/* skip device */
|
||||
vec[1] = default_match_pattern;
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_REMOUNT_FLAGS,
|
||||
opt_flags & MS_REMOUNT_FLAGS))
|
||||
goto fail;
|
||||
|
||||
vec[3] = flagsbuf;
|
||||
|
||||
if (opts)
|
||||
tmpallow = AA_MATCH_CONT;
|
||||
else
|
||||
tmpallow = allow;
|
||||
|
||||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
if (opts) {
|
||||
/* rule with data match required */
|
||||
optsbuf.clear();
|
||||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
||||
return RULE_OK;
|
||||
|
||||
fail:
|
||||
return RULE_ERROR;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
|
||||
unsigned int flags, unsigned int opt_flags)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
|
||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||
|
||||
/* bind mount rules can't be conditional on dev_type or data */
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_BIND_FLAGS,
|
||||
opt_flags & MS_BIND_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
return RULE_OK;
|
||||
|
||||
fail:
|
||||
return RULE_ERROR;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
|
||||
unsigned int flags,
|
||||
unsigned int opt_flags)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
char *mountpoint = mnt_point;
|
||||
|
||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||
|
||||
/* change type base rules can specify the mount point by using
|
||||
* the parser token position reserved to device. that's why if
|
||||
* the mount point is not specified, we use device in its
|
||||
* place. this is a deprecated behavior.
|
||||
*
|
||||
* change type base rules can not be conditional on device
|
||||
* (source), device type or data
|
||||
*/
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (flags && flags != MS_ALL_FLAGS && device && mnt_point) {
|
||||
PERROR("source and mount point cannot be used at the "
|
||||
"same time for propagation type flags");
|
||||
goto fail;
|
||||
} else if (device && !mnt_point) {
|
||||
mountpoint = device;
|
||||
}
|
||||
if (!convert_entry(mntbuf, mountpoint))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
/* skip device and type */
|
||||
vec[1] = default_match_pattern;
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MAKE_FLAGS,
|
||||
opt_flags & MS_MAKE_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
return RULE_OK;
|
||||
|
||||
fail:
|
||||
return RULE_ERROR;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
|
||||
unsigned int flags, unsigned int opt_flags)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
|
||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||
|
||||
/* mount move rules can not be conditional on dev_type,
|
||||
* or data
|
||||
*/
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MOVE_FLAGS,
|
||||
opt_flags & MS_MOVE_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
return RULE_OK;
|
||||
|
||||
fail:
|
||||
return RULE_ERROR;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
||||
unsigned int flags, unsigned int opt_flags)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
int tmpallow;
|
||||
|
||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
typebuf.clear();
|
||||
if (!build_list_val_expr(typebuf, dev_type))
|
||||
goto fail;
|
||||
vec[2] = typebuf.c_str();
|
||||
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_NEW_FLAGS,
|
||||
opt_flags & MS_NEW_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
|
||||
if (opts)
|
||||
tmpallow = AA_MATCH_CONT;
|
||||
else
|
||||
tmpallow = allow;
|
||||
|
||||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
if (opts) {
|
||||
/* rule with data match required */
|
||||
optsbuf.clear();
|
||||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
||||
return RULE_OK;
|
||||
|
||||
fail:
|
||||
return RULE_ERROR;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_flag_rules(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags)
|
||||
{
|
||||
/*
|
||||
* XXX: added !flags to cover cases like:
|
||||
* mount options in (bind) /d -> /4,
|
||||
*/
|
||||
if ((allow & AA_MAY_MOUNT) && (!flags || flags == MS_ALL_FLAGS)) {
|
||||
/* no mount flags specified, generate multiple rules */
|
||||
if (!device && !dev_type &&
|
||||
gen_policy_remount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||
return RULE_ERROR;
|
||||
if (!dev_type && !opts &&
|
||||
gen_policy_bind_mount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||
return RULE_ERROR;
|
||||
if ((!device || !mnt_point) && !dev_type && !opts &&
|
||||
gen_policy_change_mount_type(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||
return RULE_ERROR;
|
||||
if (!dev_type && !opts &&
|
||||
gen_policy_move_mount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||
return RULE_ERROR;
|
||||
|
||||
return gen_policy_new_mount(prof, count, flags, opt_flags);
|
||||
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
|
||||
&& !device && !dev_type) {
|
||||
return gen_policy_remount(prof, count, flags, opt_flags);
|
||||
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
|
||||
&& !dev_type && !opts) {
|
||||
return gen_policy_bind_mount(prof, count, flags, opt_flags);
|
||||
} else if ((allow & AA_MAY_MOUNT) &&
|
||||
(flags & (MS_MAKE_CMDS))
|
||||
&& (!device || !mnt_point) && !dev_type && !opts) {
|
||||
return gen_policy_change_mount_type(prof, count, flags, opt_flags);
|
||||
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
|
||||
&& !dev_type && !opts) {
|
||||
return gen_policy_move_mount(prof, count, flags, opt_flags);
|
||||
} else if ((allow & AA_MAY_MOUNT) &&
|
||||
((flags | opt_flags) & ~MS_CMDS)) {
|
||||
/* generic mount if flags are set that are not covered by
|
||||
* above commands
|
||||
*/
|
||||
return gen_policy_new_mount(prof, count, flags, opt_flags);
|
||||
} /* else must be RULE_OK for some rules */
|
||||
|
||||
return RULE_OK;
|
||||
}
|
||||
|
||||
int mnt_rule::gen_policy_re(Profile &prof)
|
||||
{
|
||||
std::string mntbuf;
|
||||
std::string devbuf;
|
||||
std::string typebuf;
|
||||
char flagsbuf[PATH_MAX + 3];
|
||||
std::string optsbuf;
|
||||
char class_mount_hdr[64];
|
||||
const char *vec[5];
|
||||
int count = 0;
|
||||
unsigned int tmpflags, tmpinv_flags;
|
||||
|
||||
if (!features_supports_mount) {
|
||||
warn_once(prof.name);
|
||||
@@ -1034,10 +605,202 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
||||
/* a single mount rule may result in multiple matching rules being
|
||||
* created in the backend to cover all the possible choices
|
||||
*/
|
||||
for (size_t i = 0; i < flagsv.size(); i++) {
|
||||
for (size_t j = 0; j < opt_flagsv.size(); j++) {
|
||||
if (gen_flag_rules(prof, count, flagsv[i], opt_flagsv[j]) == RULE_ERROR)
|
||||
|
||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
|
||||
&& !device && !dev_type) {
|
||||
int tmpallow;
|
||||
/* remount can't be conditional on device and type */
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (mnt_point) {
|
||||
/* both device && mnt_point or just mnt_point */
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
} else {
|
||||
if (!convert_entry(mntbuf, device))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
}
|
||||
/* skip device */
|
||||
vec[1] = default_match_pattern;
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
tmpflags = flags;
|
||||
tmpinv_flags = inv_flags;
|
||||
if (tmpflags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_REMOUNT_FLAGS;
|
||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_REMOUNT_FLAGS;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
|
||||
if (opts)
|
||||
tmpallow = AA_MATCH_CONT;
|
||||
else
|
||||
tmpallow = allow;
|
||||
|
||||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
if (opts) {
|
||||
/* rule with data match required */
|
||||
optsbuf.clear();
|
||||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
|
||||
&& !dev_type && !opts) {
|
||||
/* bind mount rules can't be conditional on dev_type or data */
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
tmpflags = flags;
|
||||
tmpinv_flags = inv_flags;
|
||||
if (tmpflags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_BIND_FLAGS;
|
||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_BIND_FLAGS;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
if ((allow & AA_MAY_MOUNT) &&
|
||||
(flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
|
||||
&& !device && !dev_type && !opts) {
|
||||
/* change type base rules can not be conditional on device,
|
||||
* device type or data
|
||||
*/
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
/* skip device and type */
|
||||
vec[1] = default_match_pattern;
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
tmpflags = flags;
|
||||
tmpinv_flags = inv_flags;
|
||||
if (tmpflags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_MAKE_FLAGS;
|
||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_MAKE_FLAGS;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
|
||||
&& !dev_type && !opts) {
|
||||
/* mount move rules can not be conditional on dev_type,
|
||||
* or data
|
||||
*/
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
/* skip type */
|
||||
vec[2] = default_match_pattern;
|
||||
|
||||
tmpflags = flags;
|
||||
tmpinv_flags = inv_flags;
|
||||
if (tmpflags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_MOVE_FLAGS;
|
||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
||||
tmpflags &= MS_MOVE_FLAGS;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
if ((allow & AA_MAY_MOUNT) &&
|
||||
(flags | inv_flags) & ~MS_CMDS) {
|
||||
int tmpallow;
|
||||
/* generic mount if flags are set that are not covered by
|
||||
* above commands
|
||||
*/
|
||||
/* rule class single byte header */
|
||||
mntbuf.assign(class_mount_hdr);
|
||||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
typebuf.clear();
|
||||
if (!build_list_val_expr(typebuf, dev_type))
|
||||
goto fail;
|
||||
vec[2] = typebuf.c_str();
|
||||
|
||||
tmpflags = flags;
|
||||
tmpinv_flags = inv_flags;
|
||||
if (tmpflags != MS_ALL_FLAGS)
|
||||
tmpflags &= ~MS_CMDS;
|
||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
||||
tmpinv_flags &= ~MS_CMDS;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
|
||||
if (opts)
|
||||
tmpallow = AA_MATCH_CONT;
|
||||
else
|
||||
tmpallow = allow;
|
||||
|
||||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
if (opts) {
|
||||
/* rule with data match required */
|
||||
optsbuf.clear();
|
||||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (allow & AA_MAY_UMOUNT) {
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#define __AA_MOUNT_H
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "parser.h"
|
||||
#include "rule.h"
|
||||
@@ -40,8 +39,6 @@
|
||||
#define MS_MAND (1 << 6)
|
||||
#define MS_NOMAND 0
|
||||
#define MS_DIRSYNC (1 << 7)
|
||||
#define MS_SYMFOLLOW 0
|
||||
#define MS_NOSYMFOLLOW (1 << 8)
|
||||
#define MS_NODIRSYNC 0
|
||||
#define MS_NOATIME (1 << 10)
|
||||
#define MS_ATIME 0
|
||||
@@ -64,7 +61,6 @@
|
||||
#define MS_IVERSION (1 << 23)
|
||||
#define MS_NOIVERSION 0
|
||||
#define MS_STRICTATIME (1 << 24)
|
||||
#define MS_LAZYTIME (1 << 25)
|
||||
#define MS_NOUSER (1 << 31)
|
||||
#define MS_USER 0
|
||||
|
||||
@@ -78,14 +74,12 @@
|
||||
|
||||
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
|
||||
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
|
||||
MS_NOSYMFOLLOW | \
|
||||
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
|
||||
MS_MOVE | MS_VERBOSE | MS_ACL | \
|
||||
MS_UNBINDABLE | MS_RUNBINDABLE | \
|
||||
MS_PRIVATE | MS_RPRIVATE | \
|
||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED | \
|
||||
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | \
|
||||
MS_LAZYTIME | MS_USER)
|
||||
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | MS_USER)
|
||||
|
||||
/* set of flags we don't use but define (but not with the kernel values)
|
||||
* for MNT_FLAGS
|
||||
@@ -100,15 +94,16 @@
|
||||
MS_KERNMOUNT | MS_STRICTATIME)
|
||||
|
||||
#define MS_BIND_FLAGS (MS_BIND | MS_RBIND)
|
||||
#define MS_MAKE_CMDS (MS_UNBINDABLE | MS_RUNBINDABLE | \
|
||||
#define MS_MAKE_FLAGS ((MS_UNBINDABLE | MS_RUNBINDABLE | \
|
||||
MS_PRIVATE | MS_RPRIVATE | \
|
||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
||||
#define MS_MAKE_FLAGS (MS_ALL_FLAGS & ~(MNT_FLAGS))
|
||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED) | \
|
||||
(MS_ALL_FLAGS & ~(MNT_FLAGS)))
|
||||
#define MS_MOVE_FLAGS (MS_MOVE)
|
||||
|
||||
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | MS_MAKE_CMDS)
|
||||
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | \
|
||||
MS_UNBINDABLE | MS_RUNBINDABLE | MS_PRIVATE | MS_RPRIVATE | \
|
||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
||||
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
|
||||
#define MS_NEW_FLAGS (MS_ALL_FLAGS & ~MS_CMDS)
|
||||
|
||||
#define MNT_SRC_OPT 1
|
||||
#define MNT_DST_OPT 2
|
||||
@@ -126,19 +121,6 @@
|
||||
|
||||
|
||||
class mnt_rule: public rule_t {
|
||||
int gen_policy_remount(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
int gen_policy_bind_mount(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
int gen_policy_change_mount_type(Profile &prof, int &count,
|
||||
unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
int gen_policy_move_mount(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
int gen_policy_new_mount(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
int gen_flag_rules(Profile &prof, int &count, unsigned int flags,
|
||||
unsigned int opt_flags);
|
||||
public:
|
||||
char *mnt_point;
|
||||
char *device;
|
||||
@@ -146,7 +128,7 @@ public:
|
||||
struct value_list *dev_type;
|
||||
struct value_list *opts;
|
||||
|
||||
std::vector<unsigned int> flagsv, opt_flagsv;
|
||||
unsigned int flags, inv_flags;
|
||||
|
||||
int allow, audit;
|
||||
int deny;
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -66,12 +66,10 @@ extern int parser_token;
|
||||
#define WARN_FORMAT 0x400
|
||||
#define WARN_MISSING 0x800
|
||||
#define WARN_OVERRIDE 0x1000
|
||||
#define WARN_INCLUDE 0x2000
|
||||
|
||||
#define WARN_DEV (WARN_RULE_NOT_ENFORCED | WARN_RULE_DOWNGRADED | WARN_ABI | \
|
||||
WARN_DEPRECATED | WARN_DANGEROUS | WARN_UNEXPECTED | \
|
||||
WARN_FORMAT | WARN_MISSING | WARN_OVERRIDE | \
|
||||
WARN_DEBUG_CACHE | WARN_INCLUDE)
|
||||
WARN_FORMAT | WARN_MISSING | WARN_OVERRIDE | WARN_DEBUG_CACHE)
|
||||
|
||||
#define DEFAULT_WARNINGS (WARN_CONFIG | WARN_CACHE | WARN_JOBS | \
|
||||
WARN_UNEXPECTED | WARN_OVERRIDE)
|
||||
@@ -79,8 +77,7 @@ extern int parser_token;
|
||||
#define WARN_ALL (WARN_RULE_NOT_ENFORCED | WARN_RULE_DOWNGRADED | WARN_ABI | \
|
||||
WARN_DEPRECATED | WARN_CONFIG | WARN_CACHE | \
|
||||
WARN_DEBUG_CACHE | WARN_JOBS | WARN_DANGEROUS | \
|
||||
WARN_UNEXPECTED | WARN_FORMAT | WARN_MISSING | \
|
||||
WARN_OVERRIDE | WARN_INCLUDE)
|
||||
WARN_UNEXPECTED | WARN_FORMAT | WARN_MISSING | WARN_OVERRIDE)
|
||||
|
||||
extern dfaflags_t warnflags;
|
||||
extern dfaflags_t werrflags;
|
||||
@@ -232,7 +229,6 @@ do { \
|
||||
#endif
|
||||
|
||||
|
||||
#define list_first(LIST) (LIST)
|
||||
#define list_for_each(LIST, ENTRY) \
|
||||
for ((ENTRY) = (LIST); (ENTRY); (ENTRY) = (ENTRY)->next)
|
||||
#define list_for_each_safe(LIST, ENTRY, TMP) \
|
||||
@@ -266,16 +262,6 @@ do { \
|
||||
prev; \
|
||||
})
|
||||
|
||||
#define list_pop(LIST) \
|
||||
({ \
|
||||
typeof(LIST) _entry = (LIST); \
|
||||
if (LIST) { \
|
||||
(LIST) = (LIST)->next; \
|
||||
_entry->next = NULL; \
|
||||
} \
|
||||
_entry; \
|
||||
})
|
||||
|
||||
#define list_remove_at(LIST, PREV, ENTRY) \
|
||||
if (PREV) \
|
||||
(PREV)->next = (ENTRY)->next; \
|
||||
@@ -390,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;
|
||||
@@ -165,7 +165,6 @@ FILE *search_path(char *filename, char **fullpath, bool *skip)
|
||||
if (g_includecache->find(buf)) {
|
||||
/* hit do not want to re-include */
|
||||
*skip = true;
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -274,7 +274,7 @@ static inline void sd_write_aligned_blob(std::ostringstream &buf, void *b, int b
|
||||
buf.write((const char *) b, b_size);
|
||||
}
|
||||
|
||||
static void sd_write_strn(std::ostringstream &buf, const char *b, int size, const char *name)
|
||||
static void sd_write_strn(std::ostringstream &buf, char *b, int size, const char *name)
|
||||
{
|
||||
sd_write_name(buf, name);
|
||||
sd_write8(buf, SD_STRING);
|
||||
@@ -282,7 +282,7 @@ static void sd_write_strn(std::ostringstream &buf, const char *b, int size, cons
|
||||
buf.write(b, size);
|
||||
}
|
||||
|
||||
static inline void sd_write_string(std::ostringstream &buf, const char *b, const char *name)
|
||||
static inline void sd_write_string(std::ostringstream &buf, char *b, const char *name)
|
||||
{
|
||||
sd_write_strn(buf, b, strlen(b) + 1, name);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -401,7 +401,11 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
|
||||
sd_write_struct(buf, "profile");
|
||||
if (flattened) {
|
||||
assert(profile->parent);
|
||||
sd_write_string(buf, profile->get_name(false).c_str(), NULL);
|
||||
autofree char *name = (char *) malloc(3 + strlen(profile->name) + strlen(profile->parent->name));
|
||||
if (!name)
|
||||
return;
|
||||
sprintf(name, "%s//%s", profile->parent->name, profile->name);
|
||||
sd_write_string(buf, name, NULL);
|
||||
} else {
|
||||
sd_write_string(buf, profile->name, NULL);
|
||||
}
|
||||
|
@@ -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);
|
||||
@@ -167,10 +165,10 @@ void include_filename(char *filename, int search, bool if_exists)
|
||||
include_file = search_path(filename, &fullpath, &cached);
|
||||
if (!include_file && cached) {
|
||||
goto skip;
|
||||
} else if (!include_file && preprocess_only) {
|
||||
fprintf(yyout, "\n\n##failed include <%s>\n", filename);
|
||||
} else if (preprocess_only) {
|
||||
fprintf(yyout, "\n\n##included <%s>\n", filename);
|
||||
} else if (!include_file && preprocess_only) {
|
||||
fprintf(yyout, "\n\n##failed include <%s>\n", filename);
|
||||
}
|
||||
|
||||
} else if (g_includecache->find(filename)) {
|
||||
@@ -613,7 +611,6 @@ GT >
|
||||
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||
* It needs to be handled specially
|
||||
*/
|
||||
pwarn(WARN_INCLUDE, _("deprecated use of '#include'\n"));
|
||||
yy_push_state(INCLUDE_EXISTS);
|
||||
}
|
||||
|
||||
@@ -628,7 +625,6 @@ include{WS}+if{WS}+exists/{WS} {
|
||||
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||
* It needs to be handled specially
|
||||
*/
|
||||
pwarn(WARN_INCLUDE, _("deprecated use of '#include'\n"));
|
||||
yy_push_state(INCLUDE);
|
||||
}
|
||||
|
||||
@@ -745,7 +741,7 @@ include/{WS} {
|
||||
}
|
||||
}
|
||||
|
||||
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODE,INCLUDE,INCLUDE_EXISTS,ABI_MODE>{
|
||||
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODEINCLUDE,INCLUDE_EXISTS,ABI_MODE>{
|
||||
(.|\n) {
|
||||
DUMP_PREPROCESS;
|
||||
/* Something we didn't expect */
|
||||
|
@@ -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},
|
||||
};
|
||||
@@ -269,7 +264,6 @@ optflag_table_t warnflag_table[] = {
|
||||
{ 1, "missing", "warn when missing qualifier and a default is used", WARN_MISSING },
|
||||
{ 1, "override", "warn when overriding", WARN_OVERRIDE },
|
||||
{ 1, "dev", "turn on warnings that are useful for profile development", WARN_DEV },
|
||||
{ 1, "pound-include", "warn when #include is used", WARN_INCLUDE },
|
||||
{ 1, "all", "turn on all warnings", WARN_ALL},
|
||||
{ 0, NULL, NULL, 0 },
|
||||
};
|
||||
@@ -420,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)
|
||||
@@ -453,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" \
|
||||
@@ -770,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);
|
||||
@@ -1146,7 +1112,7 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
retval = process_binary(option, kernel_interface,
|
||||
cachename);
|
||||
if (!retval || skip_bad_cache_rebuild)
|
||||
goto out;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,8 +1175,7 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
}
|
||||
}
|
||||
out:
|
||||
/* cleanup */
|
||||
reset_parser(profilename);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1298,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)
|
||||
@@ -1326,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 */
|
||||
@@ -1452,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;
|
||||
@@ -1476,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;
|
||||
@@ -1547,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);
|
||||
@@ -1670,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;
|
||||
@@ -1697,7 +1573,6 @@ int main(int argc, char *argv[])
|
||||
if (ofile)
|
||||
fclose(ofile);
|
||||
aa_policy_cache_unref(policy_cache);
|
||||
aa_kernel_interface_unref(kernel_interface);
|
||||
|
||||
return last_error;
|
||||
}
|
||||
|
@@ -486,18 +486,13 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||
&prof->xmatch_len);
|
||||
if (ptype == ePatternBasic)
|
||||
prof->xmatch_len = strlen(name);
|
||||
|
||||
if (ptype == ePatternInvalid) {
|
||||
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
|
||||
if (!prof->attachment)
|
||||
free(name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!prof->attachment)
|
||||
free(name);
|
||||
|
||||
if (ptype == ePatternBasic && !(prof->altnames || prof->attachment || prof->xattrs.list)) {
|
||||
if (ptype == ePatternInvalid) {
|
||||
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
|
||||
return FALSE;
|
||||
} else if (ptype == ePatternBasic && !(prof->altnames || prof->attachment || prof->xattrs.list)) {
|
||||
/* no regex so do not set xmatch */
|
||||
prof->xmatch = NULL;
|
||||
prof->xmatch_len = 0;
|
||||
@@ -546,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)
|
||||
@@ -1773,7 +1787,7 @@ static int abi_features_base(struct aa_features **features, char *filename, bool
|
||||
{
|
||||
autofclose FILE *f = NULL;
|
||||
struct stat my_stat;
|
||||
autofree char *fullpath = NULL;
|
||||
char *fullpath = NULL;
|
||||
bool cached;
|
||||
|
||||
if (search) {
|
||||
|
@@ -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
|
||||
@@ -105,12 +99,11 @@ is_container_with_internal_policy() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# LXD, Incus and LXC set up AppArmor namespaces starting with "lxd-",
|
||||
# "incus-" and "lxc-", respectively. Return non-zero for all other
|
||||
# namespace identifiers.
|
||||
# LXD and LXC set up AppArmor namespaces starting with "lxd-" and
|
||||
# "lxc-", respectively. Return non-zero for all other namespace
|
||||
# identifiers.
|
||||
read -r ns_name < "$ns_name_path"
|
||||
if [ "${ns_name#lxd-*}" = "$ns_name" ] && \
|
||||
[ "${ns_name#incus-*}" = "$ns_name" ] && \
|
||||
[ "${ns_name#lxc-*}" = "$ns_name" ]; then
|
||||
return 1
|
||||
fi
|
||||
@@ -118,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"
|
||||
@@ -133,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
|
||||
echo "$profile"
|
||||
done | \
|
||||
# Use xargs to parallelize calls to the parser over all CPUs
|
||||
xargs -n1 -d"\n" --max-procs="$(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"
|
||||
}
|
||||
|
||||
@@ -161,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
|
||||
|
||||
@@ -172,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
|
||||
@@ -219,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."
|
||||
@@ -267,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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user