mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 15:25:27 +00:00
Compare commits
244 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2e922a9a9b | ||
|
6937123153 | ||
|
5df25d9077 | ||
|
095c9013a5 | ||
|
99f19fdc0f | ||
|
c1dc77347c | ||
|
514cabda19 | ||
|
9987a7ec9c | ||
|
149800201c | ||
|
ddfb5722c0 | ||
|
7b03af8210 | ||
|
f37e9b4e7f | ||
|
f64e0e79f8 | ||
|
bed6986bef | ||
|
a70c80a80f | ||
|
17d3831d2d | ||
|
6ab732ed38 | ||
|
ab91f7bfa3 | ||
|
420aea6262 | ||
|
b672900629 | ||
|
77ebda113e | ||
|
f18c39514c | ||
|
67c1eaff9d | ||
|
ca23b1af45 | ||
|
1742647862 | ||
|
b50888a6de | ||
|
f2a40bb530 | ||
|
803fef6cd9 | ||
|
732ed66f0a | ||
|
f6ee78d5b2 | ||
|
082274c10f | ||
|
734130abad | ||
|
b78e8edee0 | ||
|
fbb8486fe6 | ||
|
25aad109e1 | ||
|
859a16310b | ||
|
052820e648 | ||
|
5e4c68712f | ||
|
ddee796d70 | ||
|
9d841a2291 | ||
|
9cb010f746 | ||
|
645545048c | ||
|
540aa94418 | ||
|
affc7a9fb4 | ||
|
6f5c61e6af | ||
|
b86f313281 | ||
|
4167497738 | ||
|
5cc04694bf | ||
|
b54929b0e0 | ||
|
e0f7594c73 | ||
|
a17775b821 | ||
|
e97b1e732a | ||
|
bc133dd9b5 | ||
|
2f658e2422 | ||
|
730b346fde | ||
|
51a7041f85 | ||
|
d55b94642c | ||
|
8b79ce540c | ||
|
866aaa1687 | ||
|
08412a8a39 | ||
|
1f99202c26 | ||
|
14744e83a6 | ||
|
69800c435a | ||
|
50ae9a1884 | ||
|
e27df656f0 | ||
|
2bef2e23d1 | ||
|
ed1fd20aa9 | ||
|
ffb051db51 | ||
|
e45a46d47d | ||
|
f651633281 | ||
|
02ab39208b | ||
|
fac81098fa | ||
|
2fbb1ed2df | ||
|
65c1a6cae2 | ||
|
529985973d | ||
|
7349a9cb03 | ||
|
fb7a5983bc | ||
|
f4c722c739 | ||
|
267c18e725 | ||
|
41eae89869 | ||
|
e13569fecb | ||
|
1c570118ed | ||
|
ec0c5d470a | ||
|
925cf94cdc | ||
|
090e9986f1 | ||
|
2eb9ab0913 | ||
|
7f0aed7fb8 | ||
|
3abf501527 | ||
|
a5eeed7c63 | ||
|
5070ba61e1 | ||
|
82bd9a390d | ||
|
acb40969b5 | ||
|
7473044d41 | ||
|
56b8e16698 | ||
|
b3dfe3366a | ||
|
249b68c92e | ||
|
749d94297f | ||
|
8a8349d14d | ||
|
7cc2c0dfad | ||
|
bb0a9c76e3 | ||
|
b86917dc95 | ||
|
9d8b6f4dbd | ||
|
40ba8bf047 | ||
|
e24484c42e | ||
|
d9d3cae2aa | ||
|
35522677d3 | ||
|
90c0d2b3c3 | ||
|
0361997506 | ||
|
14f622bc2b | ||
|
a0b77b804b | ||
|
26a3351552 | ||
|
28586f7309 | ||
|
71d089b4fa | ||
|
9179b5cf17 | ||
|
21ffea57f6 | ||
|
313e0b4266 | ||
|
f2914da00a | ||
|
6801c0d0d0 | ||
|
2becda217b | ||
|
8e63137612 | ||
|
f97782b100 | ||
|
aa7dc70de3 | ||
|
3f1ed05da6 | ||
|
971908b730 | ||
|
481f59a39b | ||
|
9e48a5da5e | ||
|
4814763c97 | ||
|
1328a42d5a | ||
|
be94d7b27f | ||
|
2ad924f2b1 | ||
|
bf662b5594 | ||
|
110b96bd3d | ||
|
10a4b3b9fb | ||
|
419d82c13b | ||
|
26b6dc1306 | ||
|
63b7cb0660 | ||
|
30e0eacebc | ||
|
1f36505f3e | ||
|
8d9c904174 | ||
|
4c7924ec31 | ||
|
b4a5f44473 | ||
|
e9d9395f91 | ||
|
b950c76d66 | ||
|
95912e41bf | ||
|
64c196a487 | ||
|
df0a2335f2 | ||
|
f472b6bb34 | ||
|
059adcdf76 | ||
|
a7ffae4396 | ||
|
5d973c2657 | ||
|
c4e607199c | ||
|
e28d0a922a | ||
|
b74f224106 | ||
|
0b18e57cc5 | ||
|
b714cf1b0d | ||
|
b7732a2a30 | ||
|
6b78daf25b | ||
|
26a8b72225 | ||
|
36bdd6ea70 | ||
|
0d0a196077 | ||
|
5e187daa0b | ||
|
776975dc38 | ||
|
f3c39034ae | ||
|
45922c6d21 | ||
|
80d900d18c | ||
|
812d53b546 | ||
|
4ffcb2a8a9 | ||
|
96b339f870 | ||
|
b4fa0cf9f6 | ||
|
f0876ea92a | ||
|
06069cc47a | ||
|
0c2690d819 | ||
|
47da50b7e6 | ||
|
50ee50f931 | ||
|
566f656101 | ||
|
11ae3f6ecd | ||
|
671ddccf19 | ||
|
4395d6dea8 | ||
|
86ec3dd658 | ||
|
14096cb3a7 | ||
|
208933829f | ||
|
cea8e7cfa0 | ||
|
c9bf36dd2e | ||
|
e6ef536957 | ||
|
dc7c702188 | ||
|
3b5683be29 | ||
|
f9eb3fea0f | ||
|
130958a4a4 | ||
|
2bc64070c9 | ||
|
1f9085e5e7 | ||
|
46f88f5f0d | ||
|
f8c535801e | ||
|
8b3997aa0e | ||
|
7f643fbc31 | ||
|
275c7c0d50 | ||
|
d66720ef07 | ||
|
22e94633c3 | ||
|
ccef9161a8 | ||
|
b21b28f486 | ||
|
735afbc947 | ||
|
1c3839c39a | ||
|
86db2263b8 | ||
|
41b6182019 | ||
|
8ef7b59454 | ||
|
0eefeeb0e7 | ||
|
21b0d14ea4 | ||
|
11e7dab95e | ||
|
e88af93322 | ||
|
ad5e988efb | ||
|
b0456adbd8 | ||
|
8dd517f6dd | ||
|
547708bc99 | ||
|
8f6d94bf44 | ||
|
0b93a7f991 | ||
|
e2c1b21dec | ||
|
cb4f553d60 | ||
|
967d394ef4 | ||
|
705ce5ca3e | ||
|
6d22c871bf | ||
|
a3db7f8acb | ||
|
7f1007d13e | ||
|
f8a174c08b | ||
|
cab3210bd0 | ||
|
85f8cace12 | ||
|
26af640fda | ||
|
1bac9d2d79 | ||
|
e1929298ac | ||
|
8fc3dcb312 | ||
|
6f1d054468 | ||
|
ef718df685 | ||
|
2ea3309942 | ||
|
8d142809f5 | ||
|
efd8eedd52 | ||
|
62dbd29656 | ||
|
1b51dac4c9 | ||
|
1361116542 | ||
|
8b17fd1fa6 | ||
|
6ab19ea82f | ||
|
1541175c36 | ||
|
cb5cdf2656 | ||
|
1b58f226ce | ||
|
d71e46baaa | ||
|
924983e702 | ||
|
6344b8ecc3 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -63,7 +63,8 @@ parser/techdoc.aux
|
||||
parser/techdoc.log
|
||||
parser/techdoc.pdf
|
||||
parser/techdoc.toc
|
||||
profiles/apparmor.d/local/*.*
|
||||
profiles/apparmor.d/local/*
|
||||
!profiles/apparmor.d/local/README
|
||||
libraries/libapparmor/Makefile
|
||||
libraries/libapparmor/Makefile.in
|
||||
libraries/libapparmor/aclocal.m4
|
||||
|
8
Makefile
8
Makefile
@@ -19,7 +19,7 @@ DIRS=libraries/libapparmor \
|
||||
|
||||
# with conversion to git, we don't export from the remote
|
||||
REPO_URL?=git@gitlab.com:apparmor/apparmor.git
|
||||
REPO_BRANCH?=master
|
||||
REPO_BRANCH?=apparmor-2.13
|
||||
|
||||
COVERITY_DIR=cov-int
|
||||
RELEASE_DIR=apparmor-${VERSION}
|
||||
@@ -55,7 +55,11 @@ snapshot: clean
|
||||
coverity: snapshot
|
||||
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
|
||||
$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
||||
cov-build --dir $(COVERITY_DIR) -- $(MAKE) -C $(SNAPSHOT_NAME)/$(dir);)
|
||||
cov-build --dir $(COVERITY_DIR) -- $(MAKE) -C $(SNAPSHOT_NAME)/$(dir); \
|
||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-$(subst /,.,$(dir)).txt ;)
|
||||
$(foreach dir, libraries/libapparmor utils, \
|
||||
cov-build --dir $(COVERITY_DIR) --no-command --fs-capture-search $(SNAPSHOT_NAME)/$(dir); \
|
||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
|
||||
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
||||
|
||||
.PHONY: export_dir
|
||||
|
@@ -1,3 +1,9 @@
|
||||
# AppArmor
|
||||
|
||||
[](https://gitlab.com/apparmor/apparmor/commits/master)
|
||||
[](https://gitlab.com/apparmor/apparmor/pipelines)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/1699)
|
||||
|
||||
------------
|
||||
Introduction
|
||||
------------
|
||||
@@ -17,9 +23,27 @@ library, available under the LGPL license, which allows change_hat(2)
|
||||
and change_profile(2) to be used by non-GPL binaries).
|
||||
|
||||
For more information, you can read the techdoc.pdf (available after
|
||||
building the parser) and by visiting the http://apparmor.net/ web
|
||||
building the parser) and by visiting the https://apparmor.net/ web
|
||||
site.
|
||||
|
||||
----------------
|
||||
Getting in Touch
|
||||
----------------
|
||||
|
||||
Please send all complaints, feature requests, rants about the software,
|
||||
and questions to the
|
||||
[AppArmor mailing list](https://lists.ubuntu.com/mailman/listinfo/apparmor).
|
||||
|
||||
Bug reports can be filed against the AppArmor project on
|
||||
[launchpad](https://bugs.launchpad.net/apparmor) or reported to the mailing
|
||||
list directly for those who wish not to register for an account on
|
||||
launchpad. See the
|
||||
[wiki page](https://gitlab.com/apparmor/apparmor/wikis/home#reporting-bugs)
|
||||
for more information.
|
||||
|
||||
Security issues can be filed as security bugs on launchpad
|
||||
or directed to `security@apparmor.net`. Additional details can be found
|
||||
in the [wiki](https://gitlab.com/apparmor/apparmor/wikis/home#reporting-security-vulnerabilities).
|
||||
|
||||
-------------
|
||||
Source Layout
|
||||
@@ -27,6 +51,7 @@ Source Layout
|
||||
|
||||
AppArmor consists of several different parts:
|
||||
|
||||
```
|
||||
binutils/ source for basic utilities written in compiled languages
|
||||
changehat/ source for using changehat with Apache, PAM and Tomcat
|
||||
common/ common makefile rules
|
||||
@@ -37,6 +62,7 @@ parser/ source for parser/loader and corresponding documentation
|
||||
profiles/ configuration files, reference profiles and abstractions
|
||||
tests/ regression and stress testsuites
|
||||
utils/ high-level utilities for working with AppArmor
|
||||
```
|
||||
|
||||
--------------------------------------
|
||||
Important note on AppArmor kernel code
|
||||
@@ -61,63 +87,82 @@ the following order. Some systems may need to export various python-related
|
||||
environment variables to complete the build. For example, before building
|
||||
anything on these systems, use something along the lines of:
|
||||
|
||||
```
|
||||
$ export PYTHONPATH=$(realpath libraries/libapparmor/swig/python)
|
||||
$ export PYTHON=/usr/bin/python3
|
||||
$ export PYTHON_VERSION=3
|
||||
$ export PYTHON_VERSIONS=python3
|
||||
|
||||
```
|
||||
|
||||
libapparmor:
|
||||
|
||||
```
|
||||
$ cd ./libraries/libapparmor
|
||||
$ sh ./autogen.sh
|
||||
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
```
|
||||
|
||||
[an additional optional argument to libapparmor's configure is --with-ruby, to
|
||||
generate Ruby bindings to libapparmor.]
|
||||
|
||||
|
||||
Binary Utilities:
|
||||
|
||||
```
|
||||
$ cd binutils
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
```
|
||||
|
||||
parser:
|
||||
|
||||
```
|
||||
$ cd parser
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make check
|
||||
$ make install
|
||||
```
|
||||
|
||||
|
||||
Utilities:
|
||||
|
||||
```
|
||||
$ cd utils
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
```
|
||||
|
||||
Apache mod_apparmor:
|
||||
|
||||
```
|
||||
$ cd changehat/mod_apparmor
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make install
|
||||
```
|
||||
|
||||
|
||||
PAM AppArmor:
|
||||
|
||||
```
|
||||
$ cd changehat/pam_apparmor
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make install
|
||||
```
|
||||
|
||||
|
||||
Profiles:
|
||||
|
||||
```
|
||||
$ cd profiles
|
||||
$ make
|
||||
$ make check # depends on the parser having been built first
|
||||
$ make install
|
||||
|
||||
```
|
||||
|
||||
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
||||
some of the locale languages, you can override the default by passing
|
||||
@@ -138,38 +183,50 @@ For details on structure and adding tests, see
|
||||
tests/regression/apparmor/README.
|
||||
|
||||
To run:
|
||||
|
||||
```
|
||||
$ cd tests/regression/apparmor (requires root)
|
||||
$ make
|
||||
$ sudo make tests
|
||||
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
||||
|
||||
```
|
||||
|
||||
Parser tests
|
||||
------------
|
||||
For details on structure and adding tests, see parser/tst/README.
|
||||
|
||||
To run:
|
||||
|
||||
```
|
||||
$ cd parser/tst
|
||||
$ make
|
||||
$ make tests
|
||||
|
||||
```
|
||||
|
||||
Libapparmor
|
||||
-----------
|
||||
For details on structure and adding tests, see libraries/libapparmor/README.
|
||||
|
||||
```
|
||||
$ cd libraries/libapparmor
|
||||
$ make check
|
||||
```
|
||||
|
||||
Utils
|
||||
-----
|
||||
Tests for the Python utilities exist in the test/ subdirectory.
|
||||
|
||||
```
|
||||
$ cd utils
|
||||
$ make check
|
||||
```
|
||||
|
||||
The aa-decode utility to be tested can be overridden by
|
||||
setting up environment variable APPARMOR_DECODE; e.g.:
|
||||
|
||||
```
|
||||
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
|
||||
```
|
||||
|
||||
Profile checks
|
||||
--------------
|
||||
@@ -177,29 +234,44 @@ A basic consistency check to ensure that the parser and aa-logprof parse
|
||||
successfully the current set of shipped profiles. The system or other
|
||||
parser and logprof can be passed in by overriding the PARSER and LOGPROF
|
||||
variables.
|
||||
|
||||
```
|
||||
$ cd profiles
|
||||
$ make && make check
|
||||
```
|
||||
|
||||
Stress Tests
|
||||
------------
|
||||
To run AppArmor stress tests:
|
||||
|
||||
```
|
||||
$ make all
|
||||
```
|
||||
|
||||
Use these:
|
||||
|
||||
```
|
||||
$ ./change_hat
|
||||
$ ./child
|
||||
$ ./kill.sh
|
||||
$ ./open
|
||||
$ ./s.sh
|
||||
```
|
||||
|
||||
Or run all at once:
|
||||
|
||||
```
|
||||
$ ./stress.sh
|
||||
```
|
||||
|
||||
Please note that the above will stress the system so much it may end up
|
||||
invoking the OOM killer.
|
||||
|
||||
To run parser stress tests (requires /usr/bin/ruby):
|
||||
|
||||
```
|
||||
$ ./stress.sh
|
||||
```
|
||||
|
||||
(see stress.sh -h for options)
|
||||
|
||||
@@ -214,7 +286,10 @@ https://scan.coverity.com/download?tab=cxx to obtain a pre-built copy of
|
||||
cov-build.
|
||||
|
||||
To generate a compressed tarball of an intermediate Coverity directory:
|
||||
|
||||
```
|
||||
$ make coverity
|
||||
```
|
||||
|
||||
The compressed tarball is written to
|
||||
apparmor-<SNAPSHOT_VERSION>-cov-int.tar.gz, where <SNAPSHOT_VERSION>
|
@@ -89,6 +89,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), aa_is_enabled(2), and L<http://wiki.apparmor.net>.
|
||||
apparmor(7), apparmor.d(5), aa_is_enabled(2), and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -88,6 +88,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa-stack(8), aa-namespace(8), apparmor(7), apparmor.d(5), aa_change_profile(3),
|
||||
aa_change_onexec(3) and L<http://wiki.apparmor.net>.
|
||||
aa_change_onexec(3) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -8,14 +8,14 @@ msgstr ""
|
||||
"Project-Id-Version: apparmor\n"
|
||||
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
|
||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||
"PO-Revision-Date: 2017-12-21 12:20+0000\n"
|
||||
"Last-Translator: Christian Boltz <Unknown>\n"
|
||||
"PO-Revision-Date: 2018-02-09 23:55+0000\n"
|
||||
"Last-Translator: Tobias Bannert <tobannert@gmail.com>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-12-22 05:12+0000\n"
|
||||
"X-Generator: Launchpad (build 18521)\n"
|
||||
"X-Launchpad-Export-Date: 2018-02-11 05:14+0000\n"
|
||||
"X-Generator: Launchpad (build 18544)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#: ../aa_enabled.c:26
|
||||
@@ -59,15 +59,15 @@ msgstr "Nein – beim Start deaktiviert.\n"
|
||||
#: ../aa_enabled.c:77
|
||||
#, c-format
|
||||
msgid "Maybe - policy interface not available.\n"
|
||||
msgstr ""
|
||||
msgstr "Vielleicht – Richtlinienschnittstelle nicht verfügbar.\n"
|
||||
|
||||
#: ../aa_enabled.c:81
|
||||
#, c-format
|
||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||
msgstr ""
|
||||
"Vielleicht - ungenügende Berechtigungen, um die Verfügbarkeit zu prüfen\n"
|
||||
"Vielleicht – ungenügende Berechtigungen, um die Verfügbarkeit zu prüfen\n"
|
||||
|
||||
#: ../aa_enabled.c:84
|
||||
#, c-format
|
||||
msgid "Error - '%s'\n"
|
||||
msgstr "Fehler - »%s«\n"
|
||||
msgstr "Fehler – »%s«\n"
|
||||
|
@@ -140,6 +140,6 @@ them at L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -82,7 +82,7 @@ SECDIR ?= ${DESTDIR}/lib/security
|
||||
.PHONY: install
|
||||
install: $(NAME).so
|
||||
install -m 755 -d $(SECDIR)
|
||||
install -m 555 $(NAME).so $(SECDIR)/
|
||||
install -m 755 $(NAME).so $(SECDIR)/
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
@@ -1 +1 @@
|
||||
2.12
|
||||
2.13.1
|
||||
|
@@ -138,7 +138,7 @@ my $ratelimit_saved = sysctl_read($ratelimit_sysctl);
|
||||
END { sysctl_write($ratelimit_sysctl, $ratelimit_saved); }
|
||||
sysctl_write($ratelimit_sysctl, 0);
|
||||
|
||||
UI_Info(gettext("\nBefore you begin, you may wish to check if a\nprofile already exists for the application you\nwish to confine. See the following wiki page for\nmore information:\nhttp://wiki.apparmor.net/index.php/Profiles"));
|
||||
UI_Info(gettext("\nBefore you begin, you may wish to check if a\nprofile already exists for the application you\nwish to confine. See the following wiki page for\nmore information:\nhttps://gitlab.com/apparmor/apparmor/wikis/Profiles"));
|
||||
|
||||
UI_Important(gettext("Please start the application to be profiled in \nanother window and exercise its functionality now.\n\nOnce completed, select the \"Scan\" button below in \norder to scan the system logs for AppArmor events. \n\nFor each AppArmor event, you will be given the \nopportunity to choose whether the access should be \nallowed or denied."));
|
||||
|
||||
@@ -195,7 +195,7 @@ for my $p (sort keys %helpers) {
|
||||
}
|
||||
|
||||
UI_Info(gettext("Reloaded AppArmor profiles in enforce mode."));
|
||||
UI_Info(gettext("\nPlease consider contributing your new profile! See\nthe following wiki page for more information:\nhttp://wiki.apparmor.net/index.php/Profiles\n"));
|
||||
UI_Info(gettext("\nPlease consider contributing your new profile! See\nthe following wiki page for more information:\nhttps://gitlab.com/apparmor/apparmor/wikis/Profiles\n"));
|
||||
UI_Info(sprintf(gettext('Finished generating profile for %s.'), $fqdbin));
|
||||
exit 0;
|
||||
|
||||
|
BIN
documentation/toxie.png
Normal file
BIN
documentation/toxie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,13 @@
|
||||
From a3b0cb6676a04cdad5cc357bc422d0398083b435 Mon Sep 17 00:00:00 2001
|
||||
From 2e7f6d0dc0f1d3642950f529b451af73fa1baf9c Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Tue, 18 Jul 2017 23:27:23 -0700
|
||||
Subject: [PATCH 17/17] UBUNTU: SAUCE: apparmor: af_unix mediation
|
||||
Subject: [PATCH 2/2] apparmor: af_unix mediation
|
||||
|
||||
af_socket mediation did not make it into 4.14 so add remaining out
|
||||
of tree patch
|
||||
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
---
|
||||
security/apparmor/Makefile | 3 +-
|
||||
security/apparmor/af_unix.c | 651 ++++++++++++++++++++++++++++++++++++
|
||||
@@ -23,10 +24,10 @@ Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
create mode 100644 security/apparmor/include/af_unix.h
|
||||
|
||||
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
|
||||
index dafdd387d42b..ef39226ff4aa 100644
|
||||
index e7ff2183532a..90c118f39e13 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -4,7 +4,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
|
||||
@@ -5,7 +5,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
|
||||
|
||||
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
|
||||
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
|
||||
@@ -694,7 +695,7 @@ index 000000000000..c6876db2dbde
|
||||
+ return error;
|
||||
+}
|
||||
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
|
||||
index 125dad5c3fde..20cdb1c4b266 100644
|
||||
index 518d5928661b..63a8a462fc96 100644
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -2187,6 +2187,11 @@ static struct aa_sfs_entry aa_sfs_entry_ns[] = {
|
||||
@@ -920,7 +921,7 @@ index 4364088a0b9e..26660a1a50b0 100644
|
||||
if (!state)
|
||||
return 0;
|
||||
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
|
||||
index cc5ab23a2d84..0ede66d80a53 100644
|
||||
index 72b915dfcaf7..5533d2f1d9de 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -26,6 +26,7 @@
|
||||
@@ -1390,5 +1391,5 @@ index 33d54435f8d6..dd1953b08e58 100644
|
||||
+ aa_label_sk_perm(label, op, request, sock->sk));
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
2.14.1
|
||||
|
@@ -1,4 +1,4 @@
|
||||
This series is based on what is currently in linux-next scheduled for
|
||||
inclusion in 4.14
|
||||
This is based on v4.14 final
|
||||
|
||||
af_unix-mediation is the last remaining patch that is out of tree
|
||||
base socket mediation and af_unix-mediation are the last two remaining
|
||||
patches that are out of tree
|
||||
|
File diff suppressed because it is too large
Load Diff
1395
kernel-patches/v4.15/0002-apparmor-af_unix-mediation.patch
Normal file
1395
kernel-patches/v4.15/0002-apparmor-af_unix-mediation.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -81,7 +81,7 @@ AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(unistd.h stdint.h syslog.h)
|
||||
|
||||
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
|
||||
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv reallocarray])
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_C_CONST
|
||||
|
@@ -257,6 +257,6 @@ should be used.
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
|
||||
aa_getcon(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -204,6 +204,6 @@ separate processes should be used.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -40,6 +40,8 @@ aa_features_is_equal - equality test for two aa_features objects
|
||||
|
||||
aa_features_supports - provides aa_features object support status
|
||||
|
||||
aa_features_id - provides unique identifier for an aa_features object
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
@@ -62,6 +64,8 @@ B<bool aa_features_is_equal(aa_features *features1, aa_features *features2);>
|
||||
|
||||
B<bool aa_features_supports(aa_features *features, const char *str);>
|
||||
|
||||
B<char *aa_features_id(aa_features *features);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -108,6 +112,12 @@ the path, relative to the "apparmor/features/" directory of securityfs, of the
|
||||
feature to query. For example, to test if policy version 6 is supported, I<str>
|
||||
would be "policy/versions/v6".
|
||||
|
||||
The aa_features_id() function returns a string representation of an
|
||||
identifier that can be used to uniquely identify an I<aa_features> object.
|
||||
The mechanism for generating the string representation is internal to
|
||||
libapparmor and subject to change but an example implementation is
|
||||
applying a hash function to the features string.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_features_new() family of functions return 0 on success and I<*features>
|
||||
@@ -126,15 +136,20 @@ and false if they are not equal.
|
||||
aa_features_supports() returns true if the feature represented by I<str> is
|
||||
supported and false if it is not supported.
|
||||
|
||||
aa_features_id() returns a string identifying I<features> which must be
|
||||
freed by the caller. NULL is returned on error, with errno set
|
||||
appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_features> family of functions that return -1 on error.
|
||||
I<aa_features> family of functions that return -1 or NULL on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_features functions described above are present in libapparmor version
|
||||
2.10 and newer.
|
||||
The aa_features_id() function can be found in libapparmor version
|
||||
2.13. All the other aa_feature functions described above are present
|
||||
in libapparmor version 2.10.
|
||||
|
||||
aa_features_unref() saves the value of errno when called and restores errno
|
||||
before exiting in libapparmor version 2.12 and newer.
|
||||
@@ -146,6 +161,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
openat(2) and L<http://wiki.apparmor.net>.
|
||||
openat(2) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -115,6 +115,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -132,6 +132,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
|
||||
aa_splitcon(3) and L<http://wiki.apparmor.net>.
|
||||
aa_splitcon(3) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -160,6 +160,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), openat(2) and L<http://wiki.apparmor.net>.
|
||||
aa_features(3), openat(2) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -34,6 +34,10 @@ aa_policy_cache_remove - removes all policy cache files under a path
|
||||
|
||||
aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
|
||||
|
||||
aa_policy_cache_dir_path - returns the path to the aa_policy_cache directory
|
||||
|
||||
aa_policy_cache_dir_path_preview - returns a preview of the path to the aa_policy_cache directory without an existing aa_policy_cache object
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
@@ -42,6 +46,8 @@ B<typedef struct aa_policy_cache aa_policy_cache;>
|
||||
|
||||
B<int aa_policy_cache_new(aa_policy_cache **policy_cache, aa_features *kernel_features, int dirfd, const char *path, uint16_t max_caches);>
|
||||
|
||||
B<int aa_policy_cache_add_ro_dir(aa_policy_cache *policy_cache, int dirfd, const char *path);>
|
||||
|
||||
B<aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);>
|
||||
|
||||
B<void aa_policy_cache_unref(aa_policy_cache *policy_cache);>
|
||||
@@ -50,6 +56,10 @@ B<int aa_policy_cache_remove(int dirfd, const char *path);>
|
||||
|
||||
B<int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface);>
|
||||
|
||||
B<char *aa_policy_cache_dir_path(aa_policy_cache *policy_cache, int level);>
|
||||
|
||||
B<char *aa_policy_cache_dir_path_preview(aa_features *kernel_features, int dirfd, const char *path);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -59,19 +69,35 @@ policy cache files. The policy cache files are the binary representation of a
|
||||
human-readable AppArmor profile. The binary representation is the form that is
|
||||
loaded into the kernel.
|
||||
|
||||
The aa_policy_cache_new() function creates an I<aa_policy_cache> object based
|
||||
upon a directory file descriptor and path. The I<path> must point to a
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. If
|
||||
I<kernel_features> is NULL, then the features of the current kernel are used.
|
||||
When specifying a valid I<kernel_features> object, it must be the compatible
|
||||
with the features of the kernel of interest. The value of I<max_caches> should
|
||||
be equal to the number of caches that should be allowed before old caches are
|
||||
automatically reaped. The definition of what is considered to be an old cache
|
||||
is private to libapparmor. Specifying 0 means that no new caches should be
|
||||
created and only existing, valid caches may be used. Specifying UINT16_MAX
|
||||
means that a new cache may be created and that the reaping of old caches is
|
||||
disabled. The allocated I<aa_policy_cache> object must be freed using
|
||||
aa_policy_cache_unref().
|
||||
The aa_policy_cache_new() function creates an I<aa_policy_cache>
|
||||
object based upon a directory file descriptor and path. See the
|
||||
openat(2) man page for examples of I<dirfd> and I<path>. The I<path>
|
||||
must point to a directory and it will be used as the basis for the
|
||||
location of policy cache files. See I<aa_policy_cache_dir_path> to
|
||||
find out which directory will be used to store the binary policy cache
|
||||
files. If additional overlay cache directories are used (see
|
||||
I<aa_policy_cache_add_ro_dir>) the directory specified in
|
||||
I<aa_policy_cache_new> is the first directory searched and is the
|
||||
writable overlay. If I<kernel_features> is NULL, then the features of
|
||||
the current kernel are used. When specifying a valid
|
||||
I<kernel_features> object, it must be compatible with the features
|
||||
of the kernel of interest. The value of I<max_caches> should be equal
|
||||
to the number of caches that should be allowed before old caches are
|
||||
automatically reaped. The definition of what is considered to be an
|
||||
old cache is private to libapparmor. Specifying 0 means that no new
|
||||
caches should be created and only existing, valid caches may be used.
|
||||
Specifying UINT16_MAX means that a new cache may be created and that
|
||||
the reaping of old caches is disabled. The allocated
|
||||
I<aa_policy_cache> object must be freed using aa_policy_cache_unref().
|
||||
|
||||
The aa_policy_cache_add_ro_dir() function adds an existing cache directory
|
||||
to the policy cache, as a readonly layer under the primary directory
|
||||
the cache was created with. When the cache is searched for an existing
|
||||
cache file the primary directory will be searched and then the readonly
|
||||
directories in the order that they were added to the policy cache.
|
||||
This allows the policy cache to be seeded with precompiled policy
|
||||
that can be updated by overlaying the read only cache file with one
|
||||
written to the primary cache dir.
|
||||
|
||||
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
|
||||
object.
|
||||
@@ -90,6 +116,18 @@ the I<policy_cache> object. If I<kernel_interface> is NULL, then the current
|
||||
kernel interface is used. When specifying a valid I<kernel_interface> object,
|
||||
it must be the interface of the currently running kernel.
|
||||
|
||||
The aa_policy_cache_dir_path() function provides the path to the cache
|
||||
directory for a I<policy_cache> object at I<level> in the policy cache
|
||||
overlay of cache directories. A I<level> of 0 will always be present
|
||||
and is the first directory to search in an overlay of cache
|
||||
directories, and will also be the writable cache directory
|
||||
layer. Binary policy cache files will be located in the directory
|
||||
returned by this function.
|
||||
|
||||
The aa_policy_cache_dir_levels() function provides access to the number
|
||||
of directories that are being overlayed to create the policy cache.
|
||||
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_policy_cache_new() function returns 0 on success and I<*policy_cache>
|
||||
@@ -102,15 +140,29 @@ aa_policy_cache_ref() returns the value of I<policy_cache>.
|
||||
aa_policy_cache_remove() and aa_policy_cache_replace_all() return 0 on success.
|
||||
-1 is returned on error, with errno set appropriately.
|
||||
|
||||
aa_policy_cache_dir_path() returns a path string which must be freed by the
|
||||
caller. NULL is returned on error, with errno set appropriately.
|
||||
|
||||
aa_policy_cache_dir_levels() returns a number indicating the number of
|
||||
directory levels there are associated with the I<policy_cache>.
|
||||
|
||||
aa_policy_cache_dir_path_preview() is the same as
|
||||
aa_policy_cache_dir_path() except that it doesn't require an existing
|
||||
I<aa_policy_cache> object. This is useful if the calling program cannot
|
||||
create an I<aa_policy_cache> object due to lack of privileges needed to
|
||||
create the cache directory.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_policy_cache> family of functions that return -1 on error.
|
||||
I<aa_policy_cache> family of functions that return -1 or NULL on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_policy_cache functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
All aa_policy_cache functions described above, except for the
|
||||
aa_policy_cache_dir_path() function was added in libapparmor version
|
||||
2.13. All the other aa_policy_cache functions described above are
|
||||
present in libapparmor version 2.10.
|
||||
|
||||
aa_policy_cache_unref() saves the value of errno when called and restores errno
|
||||
before exiting in libapparmor version 2.12 and newer.
|
||||
@@ -123,6 +175,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), aa_kernel_interface(3), openat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -128,6 +128,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_getcon(2), aa_splitcon(3)
|
||||
and L<http://wiki.apparmor.net>.
|
||||
and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -67,6 +67,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_getcon(2) and L<http://wiki.apparmor.net>.
|
||||
aa_getcon(2) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -216,6 +216,6 @@ separate processes should be used.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
|
||||
aa_getcon(2) and L<http://wiki.apparmor.net>.
|
||||
aa_getcon(2) and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -68,7 +68,7 @@ extern int aa_is_enabled(void);
|
||||
extern int aa_find_mountpoint(char **mnt);
|
||||
|
||||
/* Prototypes for self directed domain transitions
|
||||
* see <http://apparmor.net>
|
||||
* see <https://apparmor.net>
|
||||
* Please see the change_hat(2) manpage for information.
|
||||
*/
|
||||
|
||||
@@ -154,6 +154,7 @@ extern int aa_features_write_to_file(aa_features *features,
|
||||
extern bool aa_features_is_equal(aa_features *features1,
|
||||
aa_features *features2);
|
||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
||||
extern char *aa_features_id(aa_features *features);
|
||||
|
||||
typedef struct aa_kernel_interface aa_kernel_interface;
|
||||
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
@@ -186,12 +187,22 @@ extern int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path,
|
||||
uint16_t max_caches);
|
||||
extern int aa_policy_cache_add_ro_dir(aa_policy_cache *policy_cache, int dirfd,
|
||||
const char *path);
|
||||
extern aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
|
||||
extern void aa_policy_cache_unref(aa_policy_cache *policy_cache);
|
||||
|
||||
extern int aa_policy_cache_remove(int dirfd, const char *path);
|
||||
extern int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
aa_kernel_interface *kernel_interface);
|
||||
extern int aa_policy_cache_no_dirs(aa_policy_cache *policy_cache);
|
||||
extern char *aa_policy_cache_dir_path(aa_policy_cache *policy_cache, int n);
|
||||
extern int aa_policy_cache_dirfd(aa_policy_cache *policy_cache, int dir);
|
||||
extern int aa_policy_cache_open(aa_policy_cache *policy_cache, const char *name,
|
||||
int flags);
|
||||
extern char *aa_policy_cache_filename(aa_policy_cache *policy_cache, const char *name);
|
||||
extern char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
||||
int dirfd, const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ int _aa_asprintf(char **strp, const char *fmt, ...);
|
||||
|
||||
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *));
|
||||
int _aa_overlaydirat_for_each(int dirfd[], int n, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
|
||||
# For more information, see:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
#
|
||||
AA_LIB_CURRENT = 5
|
||||
AA_LIB_REVISION = 2
|
||||
AA_LIB_AGE = 4
|
||||
AA_LIB_CURRENT = 7
|
||||
AA_LIB_REVISION = 0
|
||||
AA_LIB_AGE = 6
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
|
||||
@@ -46,9 +46,9 @@ af_protos.h: /usr/include/netinet/in.h
|
||||
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
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||
|
||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c
|
||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
|
||||
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
|
||||
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
|
||||
|
||||
|
317
libraries/libapparmor/src/PMurHash.c
Normal file
317
libraries/libapparmor/src/PMurHash.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
* MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
* domain.
|
||||
*
|
||||
* This implementation was written by Shane Day, and is also public domain.
|
||||
*
|
||||
* This is a portable ANSI C implementation of MurmurHash3_x86_32 (Murmur3A)
|
||||
* with support for progressive processing.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
If you want to understand the MurmurHash algorithm you would be much better
|
||||
off reading the original source. Just point your browser at:
|
||||
http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
|
||||
|
||||
|
||||
What this version provides?
|
||||
|
||||
1. Progressive data feeding. Useful when the entire payload to be hashed
|
||||
does not fit in memory or when the data is streamed through the application.
|
||||
Also useful when hashing a number of strings with a common prefix. A partial
|
||||
hash of a prefix string can be generated and reused for each suffix string.
|
||||
|
||||
2. Portability. Plain old C so that it should compile on any old compiler.
|
||||
Both CPU endian and access-alignment neutral, but avoiding inefficient code
|
||||
when possible depending on CPU capabilities.
|
||||
|
||||
3. Drop in. I personally like nice self contained public domain code, making it
|
||||
easy to pilfer without loads of refactoring to work properly in the existing
|
||||
application code & makefile structure and mucking around with licence files.
|
||||
Just copy PMurHash.h and PMurHash.c and you're ready to go.
|
||||
|
||||
|
||||
How does it work?
|
||||
|
||||
We can only process entire 32 bit chunks of input, except for the very end
|
||||
that may be shorter. So along with the partial hash we need to give back to
|
||||
the caller a carry containing up to 3 bytes that we were unable to process.
|
||||
This carry also needs to record the number of bytes the carry holds. I use
|
||||
the low 2 bits as a count (0..3) and the carry bytes are shifted into the
|
||||
high byte in stream order.
|
||||
|
||||
To handle endianess I simply use a macro that reads a uint32_t and define
|
||||
that macro to be a direct read on little endian machines, a read and swap
|
||||
on big endian machines, or a byte-by-byte read if the endianess is unknown.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "PMurHash.h"
|
||||
|
||||
/* I used ugly type names in the header to avoid potential conflicts with
|
||||
* application or system typedefs & defines. Since I'm not including any more
|
||||
* headers below here I can rename these so that the code reads like C99 */
|
||||
#undef uint32_t
|
||||
#define uint32_t MH_UINT32
|
||||
#undef uint8_t
|
||||
#define uint8_t MH_UINT8
|
||||
|
||||
/* MSVC warnings we choose to ignore */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4127) /* conditional expression is constant */
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Endianess, misalignment capabilities and util macros
|
||||
*
|
||||
* The following 3 macros are defined in this section. The other macros defined
|
||||
* are only needed to help derive these 3.
|
||||
*
|
||||
* READ_UINT32(x) Read a little endian unsigned 32-bit int
|
||||
* UNALIGNED_SAFE Defined if READ_UINT32 works on non-word boundaries
|
||||
* ROTL32(x,r) Rotate x left by r bits
|
||||
*/
|
||||
|
||||
/* Convention is to define __BYTE_ORDER == to one of these values */
|
||||
#if !defined(__BIG_ENDIAN)
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif
|
||||
#if !defined(__LITTLE_ENDIAN)
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
/* I386 */
|
||||
#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(i386)
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#define UNALIGNED_SAFE
|
||||
#endif
|
||||
|
||||
/* gcc 'may' define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ to 1 (Note the trailing __),
|
||||
* or even _LITTLE_ENDIAN or _BIG_ENDIAN (Note the single _ prefix) */
|
||||
#if !defined(__BYTE_ORDER)
|
||||
#if defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__==1 || defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN==1
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 || defined(_BIG_ENDIAN) && _BIG_ENDIAN==1
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* gcc (usually) defines xEL/EB macros for ARM and MIPS endianess */
|
||||
#if !defined(__BYTE_ORDER)
|
||||
#if defined(__ARMEL__) || defined(__MIPSEL__)
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
#if defined(__ARMEB__) || defined(__MIPSEB__)
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Now find best way we can to READ_UINT32 */
|
||||
#if __BYTE_ORDER==__LITTLE_ENDIAN
|
||||
/* CPU endian matches murmurhash algorithm, so read 32-bit word directly */
|
||||
#define READ_UINT32(ptr) (*((uint32_t*)(ptr)))
|
||||
#elif __BYTE_ORDER==__BIG_ENDIAN
|
||||
/* TODO: Add additional cases below where a compiler provided bswap32 is available */
|
||||
#if defined(__GNUC__) && (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3))
|
||||
#define READ_UINT32(ptr) (__builtin_bswap32(*((uint32_t*)(ptr))))
|
||||
#else
|
||||
/* Without a known fast bswap32 we're just as well off doing this */
|
||||
#define READ_UINT32(ptr) (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
|
||||
#define UNALIGNED_SAFE
|
||||
#endif
|
||||
#else
|
||||
/* Unknown endianess so last resort is to read individual bytes */
|
||||
#define READ_UINT32(ptr) (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
|
||||
|
||||
/* Since we're not doing word-reads we can skip the messing about with realignment */
|
||||
#define UNALIGNED_SAFE
|
||||
#endif
|
||||
|
||||
/* Find best way to ROTL32 */
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdlib.h> /* Microsoft put _rotl declaration in here */
|
||||
#define ROTL32(x,r) _rotl(x,r)
|
||||
#else
|
||||
/* gcc recognises this code and generates a rotate instruction for CPUs with one */
|
||||
#define ROTL32(x,r) (((uint32_t)x << r) | ((uint32_t)x >> (32 - r)))
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Core murmurhash algorithm macros */
|
||||
|
||||
#define C1 (0xcc9e2d51)
|
||||
#define C2 (0x1b873593)
|
||||
|
||||
/* This is the main processing body of the algorithm. It operates
|
||||
* on each full 32-bits of input. */
|
||||
#define DOBLOCK(h1, k1) do{ \
|
||||
k1 *= C1; \
|
||||
k1 = ROTL32(k1,15); \
|
||||
k1 *= C2; \
|
||||
\
|
||||
h1 ^= k1; \
|
||||
h1 = ROTL32(h1,13); \
|
||||
h1 = h1*5+0xe6546b64; \
|
||||
}while(0)
|
||||
|
||||
|
||||
/* Append unaligned bytes to carry, forcing hash churn if we have 4 bytes */
|
||||
/* cnt=bytes to process, h1=name of h1 var, c=carry, n=bytes in c, ptr/len=payload */
|
||||
#define DOBYTES(cnt, h1, c, n, ptr, len) do{ \
|
||||
int _i = cnt; \
|
||||
while(_i--) { \
|
||||
c = c>>8 | *ptr++<<24; \
|
||||
n++; len--; \
|
||||
if(n==4) { \
|
||||
DOBLOCK(h1, c); \
|
||||
n = 0; \
|
||||
} \
|
||||
} }while(0)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Main hashing function. Initialise carry to 0 and h1 to 0 or an initial seed
|
||||
* if wanted. Both ph1 and pcarry are required arguments. */
|
||||
void PMurHash32_Process(uint32_t *ph1, uint32_t *pcarry, const void *key, int len)
|
||||
{
|
||||
uint32_t h1 = *ph1;
|
||||
uint32_t c = *pcarry;
|
||||
|
||||
const uint8_t *ptr = (uint8_t*)key;
|
||||
const uint8_t *end;
|
||||
|
||||
/* Extract carry count from low 2 bits of c value */
|
||||
int n = c & 3;
|
||||
|
||||
#if defined(UNALIGNED_SAFE)
|
||||
/* This CPU handles unaligned word access */
|
||||
|
||||
/* Consume any carry bytes */
|
||||
int i = (4-n) & 3;
|
||||
if(i && i <= len) {
|
||||
DOBYTES(i, h1, c, n, ptr, len);
|
||||
}
|
||||
|
||||
/* Process 32-bit chunks */
|
||||
end = ptr + len/4*4;
|
||||
for( ; ptr < end ; ptr+=4) {
|
||||
uint32_t k1 = READ_UINT32(ptr);
|
||||
DOBLOCK(h1, k1);
|
||||
}
|
||||
|
||||
#else /*UNALIGNED_SAFE*/
|
||||
/* This CPU does not handle unaligned word access */
|
||||
|
||||
/* Consume enough so that the next data byte is word aligned */
|
||||
int i = -(long)ptr & 3;
|
||||
if(i && i <= len) {
|
||||
DOBYTES(i, h1, c, n, ptr, len);
|
||||
}
|
||||
|
||||
/* We're now aligned. Process in aligned blocks. Specialise for each possible carry count */
|
||||
end = ptr + len/4*4;
|
||||
switch(n) { /* how many bytes in c */
|
||||
case 0: /* c=[----] w=[3210] b=[3210]=w c'=[----] */
|
||||
for( ; ptr < end ; ptr+=4) {
|
||||
uint32_t k1 = READ_UINT32(ptr);
|
||||
DOBLOCK(h1, k1);
|
||||
}
|
||||
break;
|
||||
case 1: /* c=[0---] w=[4321] b=[3210]=c>>24|w<<8 c'=[4---] */
|
||||
for( ; ptr < end ; ptr+=4) {
|
||||
uint32_t k1 = c>>24;
|
||||
c = READ_UINT32(ptr);
|
||||
k1 |= c<<8;
|
||||
DOBLOCK(h1, k1);
|
||||
}
|
||||
break;
|
||||
case 2: /* c=[10--] w=[5432] b=[3210]=c>>16|w<<16 c'=[54--] */
|
||||
for( ; ptr < end ; ptr+=4) {
|
||||
uint32_t k1 = c>>16;
|
||||
c = READ_UINT32(ptr);
|
||||
k1 |= c<<16;
|
||||
DOBLOCK(h1, k1);
|
||||
}
|
||||
break;
|
||||
case 3: /* c=[210-] w=[6543] b=[3210]=c>>8|w<<24 c'=[654-] */
|
||||
for( ; ptr < end ; ptr+=4) {
|
||||
uint32_t k1 = c>>8;
|
||||
c = READ_UINT32(ptr);
|
||||
k1 |= c<<24;
|
||||
DOBLOCK(h1, k1);
|
||||
}
|
||||
}
|
||||
#endif /*UNALIGNED_SAFE*/
|
||||
|
||||
/* Advance over whole 32-bit chunks, possibly leaving 1..3 bytes */
|
||||
len -= len/4*4;
|
||||
|
||||
/* Append any remaining bytes into carry */
|
||||
DOBYTES(len, h1, c, n, ptr, len);
|
||||
|
||||
/* Copy out new running hash and carry */
|
||||
*ph1 = h1;
|
||||
*pcarry = (c & ~0xff) | n;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Finalize a hash. To match the original Murmur3A the total_length must be provided */
|
||||
uint32_t PMurHash32_Result(uint32_t h, uint32_t carry, uint32_t total_length)
|
||||
{
|
||||
uint32_t k1;
|
||||
int n = carry & 3;
|
||||
if(n) {
|
||||
k1 = carry >> (4-n)*8;
|
||||
k1 *= C1; k1 = ROTL32(k1,15); k1 *= C2; h ^= k1;
|
||||
}
|
||||
h ^= total_length;
|
||||
|
||||
/* fmix */
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Murmur3A compatable all-at-once */
|
||||
uint32_t PMurHash32(uint32_t seed, const void *key, int len)
|
||||
{
|
||||
uint32_t h1=seed, carry=0;
|
||||
PMurHash32_Process(&h1, &carry, key, len);
|
||||
return PMurHash32_Result(h1, carry, len);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Provide an API suitable for smhasher */
|
||||
void PMurHash32_test(const void *key, int len, uint32_t seed, void *out)
|
||||
{
|
||||
uint32_t h1=seed, carry=0;
|
||||
const uint8_t *ptr = (uint8_t*)key;
|
||||
const uint8_t *end = ptr + len;
|
||||
|
||||
#if 0 /* Exercise the progressive processing */
|
||||
while(ptr < end) {
|
||||
//const uint8_t *mid = ptr + rand()%(end-ptr)+1;
|
||||
const uint8_t *mid = ptr + (rand()&0xF);
|
||||
mid = mid<end?mid:end;
|
||||
PMurHash32_Process(&h1, &carry, ptr, mid-ptr);
|
||||
ptr = mid;
|
||||
}
|
||||
#else
|
||||
PMurHash32_Process(&h1, &carry, ptr, (int)(end-ptr));
|
||||
#endif
|
||||
h1 = PMurHash32_Result(h1, carry, len);
|
||||
*(uint32_t*)out = h1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
64
libraries/libapparmor/src/PMurHash.h
Normal file
64
libraries/libapparmor/src/PMurHash.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
* MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
* domain.
|
||||
*
|
||||
* This implementation was written by Shane Day, and is also public domain.
|
||||
*
|
||||
* This is a portable ANSI C implementation of MurmurHash3_x86_32 (Murmur3A)
|
||||
* with support for progressive processing.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Determine what native type to use for uint32_t */
|
||||
|
||||
/* We can't use the name 'uint32_t' here because it will conflict with
|
||||
* any version provided by the system headers or application. */
|
||||
|
||||
/* First look for special cases */
|
||||
#if defined(_MSC_VER)
|
||||
#define MH_UINT32 unsigned long
|
||||
#endif
|
||||
|
||||
/* If the compiler says it's C99 then take its word for it */
|
||||
#if !defined(MH_UINT32) && ( \
|
||||
defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L )
|
||||
#include <stdint.h>
|
||||
#define MH_UINT32 uint32_t
|
||||
#endif
|
||||
|
||||
/* Otherwise try testing against max value macros from limit.h */
|
||||
#if !defined(MH_UINT32)
|
||||
#include <limits.h>
|
||||
#if (USHRT_MAX == 0xffffffffUL)
|
||||
#define MH_UINT32 unsigned short
|
||||
#elif (UINT_MAX == 0xffffffffUL)
|
||||
#define MH_UINT32 unsigned int
|
||||
#elif (ULONG_MAX == 0xffffffffUL)
|
||||
#define MH_UINT32 unsigned long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(MH_UINT32)
|
||||
#error Unable to determine type name for unsigned 32-bit int
|
||||
#endif
|
||||
|
||||
/* I'm yet to work on a platform where 'unsigned char' is not 8 bits */
|
||||
#define MH_UINT8 unsigned char
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void PMurHash32_Process(MH_UINT32 *ph1, MH_UINT32 *pcarry, const void *key, int len);
|
||||
MH_UINT32 PMurHash32_Result(MH_UINT32 h1, MH_UINT32 carry, MH_UINT32 total_length);
|
||||
MH_UINT32 PMurHash32(MH_UINT32 seed, const void *key, int len);
|
||||
|
||||
void PMurHash32_test(const void *key, int len, MH_UINT32 seed, void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014
|
||||
* Copyright (c) 2014-2017
|
||||
* Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
@@ -31,13 +32,16 @@
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "PMurHash.h"
|
||||
|
||||
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
||||
|
||||
#define HASH_SIZE (8 + 1) /* 32 bits binary to hex + NUL terminator */
|
||||
#define STRING_SIZE 8192
|
||||
|
||||
struct aa_features {
|
||||
unsigned int ref_count;
|
||||
char hash[HASH_SIZE];
|
||||
char string[STRING_SIZE];
|
||||
};
|
||||
|
||||
@@ -205,6 +209,29 @@ static ssize_t load_features_dir(int dirfd, const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_features_hash(aa_features *features)
|
||||
{
|
||||
const char *string = features->string;
|
||||
uint32_t seed = 5381;
|
||||
uint32_t hash = seed, carry = 0;
|
||||
size_t len = strlen(string);
|
||||
|
||||
/* portable murmur3 hash
|
||||
* https://github.com/aappleby/smhasher/wiki/MurmurHash3
|
||||
*/
|
||||
PMurHash32_Process(&hash, &carry, features, len);
|
||||
hash = PMurHash32_Result(hash, carry, len);
|
||||
|
||||
if (snprintf(features->hash, HASH_SIZE,
|
||||
"%08" PRIx32, hash) >= HASH_SIZE) {
|
||||
errno = ENOBUFS;
|
||||
PERROR("Hash buffer full.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool islbrace(int c)
|
||||
{
|
||||
return c == '{';
|
||||
@@ -408,6 +435,14 @@ int aa_features_new(aa_features **features, int dirfd, const char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (init_features_hash(f) == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_features_unref(f);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*features = f;
|
||||
|
||||
return 0;
|
||||
@@ -443,6 +478,15 @@ int aa_features_new_from_string(aa_features **features,
|
||||
|
||||
memcpy(f->string, string, size);
|
||||
f->string[size] = '\0';
|
||||
|
||||
if (init_features_hash(f) == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_features_unref(f);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*features = f;
|
||||
|
||||
return 0;
|
||||
@@ -577,3 +621,21 @@ bool aa_features_supports(aa_features *features, const char *str)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_id - provides unique identifier for an aa_features object
|
||||
* @features: the features
|
||||
*
|
||||
* Allocates and returns a string representation of an identifier that can
|
||||
* be used to uniquely identify an aa_features object. The mechanism for
|
||||
* generating the string representation is internal to libapparmor and
|
||||
* subject to change but an example implementation is applying a hash
|
||||
* function to the features string.
|
||||
*
|
||||
* Returns: a string identifying @features which must be freed by the
|
||||
* caller or NULL, with errno set, upon error
|
||||
*/
|
||||
char *aa_features_id(aa_features *features)
|
||||
{
|
||||
return strdup(features->hash);
|
||||
}
|
||||
|
@@ -95,6 +95,26 @@ APPARMOR_2.11 {
|
||||
*;
|
||||
} APPARMOR_2.10;
|
||||
|
||||
APPARMOR_2.13 {
|
||||
global:
|
||||
aa_policy_cache_dir_path;
|
||||
aa_policy_cache_dir_path_preview;
|
||||
aa_policy_cache_no_dirs;
|
||||
aa_policy_cache_dirfd;
|
||||
aa_policy_cache_open;
|
||||
aa_policy_cache_filename;
|
||||
aa_features_id;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_2.11;
|
||||
|
||||
APPARMOR_2.13.1 {
|
||||
global:
|
||||
aa_policy_cache_add_ro_dir;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_2.13;
|
||||
|
||||
PRIVATE {
|
||||
global:
|
||||
_aa_is_blacklisted;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014
|
||||
* Copyright (c) 2014-2017
|
||||
* Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -16,8 +16,11 @@
|
||||
* Ltd.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -29,31 +32,155 @@
|
||||
#include "private.h"
|
||||
|
||||
#define CACHE_FEATURES_FILE ".features"
|
||||
#define MAX_POLICY_CACHE_OVERLAY_DIRS 4
|
||||
|
||||
struct aa_policy_cache {
|
||||
unsigned int ref_count;
|
||||
aa_features *features;
|
||||
aa_features *kernel_features;
|
||||
int dirfd;
|
||||
int n;
|
||||
int dirfd[MAX_POLICY_CACHE_OVERLAY_DIRS];
|
||||
};
|
||||
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
/* remove regular files */
|
||||
if (S_ISREG(st->st_mode))
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
/* remove regular files */
|
||||
return unlinkat(dirfd, path, 0);
|
||||
} else if (S_ISDIR(st->st_mode)) {
|
||||
int retval;
|
||||
|
||||
retval = _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return unlinkat(dirfd, path, AT_REMOVEDIR);
|
||||
}
|
||||
|
||||
/* do nothing with other file types */
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct replace_all_cb_data {
|
||||
aa_policy_cache *policy_cache;
|
||||
aa_kernel_interface *kernel_interface;
|
||||
};
|
||||
|
||||
static int replace_all_cb(int dirfd, const char *name, struct stat *st,
|
||||
void *cb_data)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (S_ISLNK(st->st_mode)) {
|
||||
/*
|
||||
* symlinks in that cache are used to track file merging.
|
||||
* In the scanned overlay situation they can be skipped
|
||||
* as the combined entry will be one of none skipped
|
||||
* entries
|
||||
*/
|
||||
} else if (S_ISREG(st->st_mode) && st->st_size == 0) {
|
||||
/*
|
||||
* empty file in the cache dir is used as a whiteout
|
||||
* to hide files in a lower layer. skip
|
||||
*/
|
||||
} else if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
|
||||
struct replace_all_cb_data *data;
|
||||
|
||||
data = (struct replace_all_cb_data *) cb_data;
|
||||
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
|
||||
dirfd,
|
||||
name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static char *path_from_fd(int fd)
|
||||
{
|
||||
autofree char *proc_path = NULL;
|
||||
autoclose int proc_fd = -1;
|
||||
struct stat proc_stat;
|
||||
char *path;
|
||||
ssize_t size, path_len;
|
||||
|
||||
if (asprintf(&proc_path, "/proc/self/fd/%d", fd) == -1) {
|
||||
proc_path = NULL;
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
proc_fd = open(proc_path, O_RDONLY | O_CLOEXEC | O_PATH | O_NOFOLLOW);
|
||||
if (proc_fd == -1)
|
||||
return NULL;
|
||||
|
||||
if (fstat(proc_fd, &proc_stat) == -1)
|
||||
return NULL;
|
||||
|
||||
if (!S_ISLNK(proc_stat.st_mode)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = proc_stat.st_size;
|
||||
repeat:
|
||||
path = malloc(size + 1);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
/**
|
||||
* Since 2.6.39, symlink file descriptors opened with
|
||||
* (O_PATH | O_NOFOLLOW) can be used as the dirfd with an empty string
|
||||
* as the path. readlinkat() will operate on the symlink inode.
|
||||
*/
|
||||
path_len = readlinkat(proc_fd, "", path, size);
|
||||
if (path_len == -1)
|
||||
return NULL;
|
||||
if (path_len == size) {
|
||||
free(path);
|
||||
size = size * 2;
|
||||
goto repeat;
|
||||
}
|
||||
path[path_len] = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
static int cache_check_features(int dirfd, const char *cache_name,
|
||||
aa_features *features)
|
||||
{
|
||||
aa_features *local_features = NULL;
|
||||
autofree char *name = NULL;
|
||||
bool rc;
|
||||
int len;
|
||||
|
||||
len = asprintf(&name, "%s/%s", cache_name, CACHE_FEATURES_FILE);
|
||||
if (len == -1) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* verify that cache dir .features matches */
|
||||
if (aa_features_new(&local_features, dirfd, name)) {
|
||||
PDEBUG("could not setup new features object for dirfd '%d' '%s'\n", dirfd, name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = aa_features_is_equal(local_features, features);
|
||||
aa_features_unref(local_features);
|
||||
if (!rc) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||
{
|
||||
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
|
||||
if (aa_policy_cache_remove(policy_cache->dirfd[0], "."))
|
||||
return -1;
|
||||
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd,
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd[0],
|
||||
CACHE_FEATURES_FILE) == -1)
|
||||
return -1;
|
||||
|
||||
@@ -65,51 +192,176 @@ static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||
aa_features *kernel_features, bool create)
|
||||
{
|
||||
bool call_create_cache = false;
|
||||
|
||||
if (aa_features_new(&policy_cache->features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE)) {
|
||||
policy_cache->features = NULL;
|
||||
if (!create || errno != ENOENT)
|
||||
if (cache_check_features(policy_cache->dirfd[0], ".",
|
||||
kernel_features)) {
|
||||
/* EEXIST must come before ENOENT for short circuit eval */
|
||||
if (!create || errno == EEXIST || errno != ENOENT)
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
/* The cache directory needs to be created */
|
||||
call_create_cache = true;
|
||||
} else if (!aa_features_is_equal(policy_cache->features,
|
||||
kernel_features)) {
|
||||
if (!create) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The cache directory needs to be refreshed */
|
||||
call_create_cache = true;
|
||||
}
|
||||
|
||||
return call_create_cache ?
|
||||
create_cache(policy_cache, kernel_features) : 0;
|
||||
return create_cache(policy_cache, kernel_features);
|
||||
}
|
||||
|
||||
struct replace_all_cb_data {
|
||||
aa_policy_cache *policy_cache;
|
||||
aa_kernel_interface *kernel_interface;
|
||||
struct miss_cb_data {
|
||||
aa_features *features;
|
||||
const char *path;
|
||||
char *pattern;
|
||||
char *cache_name; /* return */
|
||||
long n;
|
||||
};
|
||||
|
||||
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *cb_data)
|
||||
/* called on cache collision or miss where cache isn't present */
|
||||
static int cache_miss_cb(int dirfd, const struct dirent *ent, void *arg)
|
||||
{
|
||||
int retval = 0;
|
||||
struct miss_cb_data *data = arg;
|
||||
char *cache_name, *pos, *tmp;
|
||||
long n;
|
||||
int len;
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
|
||||
struct replace_all_cb_data *data;
|
||||
/* TODO: update to tighter pattern match of just trailing #s */
|
||||
if (fnmatch(data->pattern, ent->d_name, 0))
|
||||
return 0;
|
||||
|
||||
data = (struct replace_all_cb_data *) cb_data;
|
||||
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
|
||||
data->policy_cache->dirfd,
|
||||
name);
|
||||
/* entry matches <feature_id>.<n> pattern */
|
||||
len = asprintf(&cache_name, "%s/%s", data->path, ent->d_name);
|
||||
if (len == -1) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (!cache_check_features(dirfd, cache_name, data->features) || errno == ENOENT) {
|
||||
/* found cache dir matching pattern */
|
||||
data->cache_name = cache_name;
|
||||
/* return 1 to stop iteration and signal dir found */
|
||||
return 1;
|
||||
} else if (errno != EEXIST) {
|
||||
PDEBUG("cache_check_features() failed for dirfd '%d' '%s'\n", dirfd, cache_name);
|
||||
free(cache_name);
|
||||
return -1;
|
||||
}
|
||||
free(cache_name);
|
||||
|
||||
/* check the cache dir # */
|
||||
pos = strchr(ent->d_name, '.');
|
||||
n = strtol(pos+1, &tmp, 10);
|
||||
if (n == LONG_MIN || n == LONG_MAX || tmp == pos + 1)
|
||||
return -1;
|
||||
if (n > data->n)
|
||||
data->n = n;
|
||||
|
||||
/* continue processing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* will return cache_path on error if there is a collision */
|
||||
static int cache_dir_from_path_and_features(char **cache_path,
|
||||
int dirfd, const char *path,
|
||||
aa_features *features)
|
||||
{
|
||||
autofree const char *features_id = NULL;
|
||||
char *cache_dir;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
features_id = aa_features_id(features);
|
||||
if (!features_id)
|
||||
return -1;
|
||||
|
||||
len = asprintf(&cache_dir, "%s/%s.0", path, features_id);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
if (!cache_check_features(dirfd, cache_dir, features) || errno == ENOENT) {
|
||||
PDEBUG("cache_dir_from_path_and_features() found '%s'\n", cache_dir);
|
||||
*cache_path = cache_dir;
|
||||
return 0;
|
||||
} else if (errno != EEXIST) {
|
||||
PDEBUG("cache_check_features() failed for dirfd '%d' %s\n", dirfd, cache_dir);
|
||||
free(cache_dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
PDEBUG("Cache collision '%s' falling back to next dir on fd '%d' path %s", cache_dir, dirfd, path);
|
||||
free(cache_dir);
|
||||
|
||||
struct miss_cb_data data = {
|
||||
.features = features,
|
||||
.path = path,
|
||||
.cache_name = NULL,
|
||||
.n = -1,
|
||||
};
|
||||
|
||||
if (asprintf(&data.pattern, "%s.*", features_id) == -1)
|
||||
return -1;
|
||||
|
||||
rc = _aa_dirat_for_each2(dirfd, path, &data, cache_miss_cb);
|
||||
free(data.pattern);
|
||||
if (rc == 1) {
|
||||
/* found matching feature dir */
|
||||
PDEBUG("cache_dir_from_path_and_features() callback found '%s'\n", data.cache_name);
|
||||
*cache_path = data.cache_name;
|
||||
return 0;
|
||||
} else if (rc) {
|
||||
PDEBUG("cache_dir_from_path_and_features() callback returned an error'%m'\n");
|
||||
return -1;
|
||||
}
|
||||
/* no dir found use 1 higher than highest dir n searched */
|
||||
len = asprintf(&cache_dir, "%s/%s.%d", path, features_id, data.n + 1);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
PDEBUG("Cache collision no dir found using %d + 1 = %s\n", data.n + 1, cache_dir);
|
||||
*cache_path = cache_dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* will return the cache_dir or NULL */
|
||||
static int open_or_create_cache_dir(aa_features *features, int dirfd,
|
||||
const char *path, bool create,
|
||||
char **cache_dir)
|
||||
{
|
||||
int fd;
|
||||
|
||||
*cache_dir = NULL;
|
||||
if (cache_dir_from_path_and_features(cache_dir, dirfd, path,
|
||||
features))
|
||||
return -1;
|
||||
|
||||
open:
|
||||
fd = openat(dirfd, *cache_dir, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (fd < 0) {
|
||||
/* does the dir exist? */
|
||||
if (create && errno == ENOENT) {
|
||||
/**
|
||||
* 1) Attempt to create the cache location, such as
|
||||
* /etc/apparmor.d/cache.d/
|
||||
* 2) Attempt to create the cache directory, for the
|
||||
* passed in aa_features, such as
|
||||
* /etc/apparmor.d/cache.d/<features_id>/
|
||||
* 3) Try to reopen the cache directory
|
||||
*/
|
||||
if (mkdirat(dirfd, path, 0700) == -1 &&
|
||||
errno != EEXIST) {
|
||||
PERROR("Can't create cache location '%s': %m\n",
|
||||
path);
|
||||
} else if (mkdirat(dirfd, *cache_dir, 0700) == -1 &&
|
||||
errno != EEXIST) {
|
||||
PERROR("Can't create cache directory '%s': %m\n",
|
||||
*cache_dir);
|
||||
} else {
|
||||
goto open;
|
||||
}
|
||||
} else if (create) {
|
||||
PERROR("Can't update cache directory '%s': %m\n", *cache_dir);
|
||||
} else {
|
||||
PDEBUG("Cache directory '%s' does not exist\n", *cache_dir);
|
||||
}
|
||||
|
||||
PDEBUG("Could not open cache_dir: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,8 +385,11 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path, uint16_t max_caches)
|
||||
{
|
||||
autofree char *cache_dir = NULL;
|
||||
aa_policy_cache *pc;
|
||||
bool create = max_caches > 0;
|
||||
autofree const char *features_id = NULL;
|
||||
int i, fd;
|
||||
|
||||
*policy_cache = NULL;
|
||||
|
||||
@@ -143,55 +398,79 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (max_caches > 1) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: currently no reaping of caches in excess of max_caches */
|
||||
pc = calloc(1, sizeof(*pc));
|
||||
if (!pc) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
pc->dirfd = -1;
|
||||
pc->n = 0;
|
||||
for (i = 0; i < MAX_POLICY_CACHE_OVERLAY_DIRS; i++)
|
||||
pc->dirfd[i] = -1;
|
||||
aa_policy_cache_ref(pc);
|
||||
|
||||
open:
|
||||
pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (pc->dirfd < 0) {
|
||||
/* does the dir exist? */
|
||||
if (create && errno == ENOENT) {
|
||||
if (mkdirat(dirfd, path, 0700) == 0)
|
||||
goto open;
|
||||
PERROR("Can't create cache directory '%s': %m\n", path);
|
||||
} else if (create) {
|
||||
PERROR("Can't update cache directory '%s': %m\n", path);
|
||||
} else {
|
||||
PDEBUG("Cache directory '%s' does not exist\n", path);
|
||||
}
|
||||
|
||||
aa_policy_cache_unref(pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kernel_features) {
|
||||
aa_features_ref(kernel_features);
|
||||
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
aa_policy_cache_unref(pc);
|
||||
PDEBUG("%s: Failed to obtain features %m\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
pc->kernel_features = kernel_features;
|
||||
pc->features = kernel_features;
|
||||
|
||||
fd = open_or_create_cache_dir(kernel_features, dirfd, path, create,
|
||||
&cache_dir);
|
||||
if (fd == -1) {
|
||||
aa_policy_cache_unref(pc);
|
||||
PDEBUG("%s: Failed to open_or_create_dir %m\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
pc->dirfd[0] = fd;
|
||||
pc->n = 1;
|
||||
|
||||
if (init_cache_features(pc, kernel_features, create)) {
|
||||
PDEBUG("%s: failed init_cache_features for dirfd '%d' name '%s' opened as pc->dirfd '%d'\n", __FUNCTION__, dirfd, cache_dir, pc->dirfd);
|
||||
aa_policy_cache_unref(pc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PDEBUG("%s: created policy_cache for dirfd '%d' name '%s' opened as pc->dirfd '%d'\n", __FUNCTION__, dirfd, cache_dir, pc->dirfd);
|
||||
*policy_cache = pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_add_ro_dir - add an readonly dir layer to the policy cache
|
||||
* @policy_cache: policy_cache to add the readonly dir to
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to the readonly policy cache
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
|
||||
int aa_policy_cache_add_ro_dir(aa_policy_cache *policy_cache, int dirfd,
|
||||
const char *path)
|
||||
{
|
||||
autofree char *cache_dir = NULL;
|
||||
int fd;
|
||||
|
||||
if (policy_cache->n >= MAX_POLICY_CACHE_OVERLAY_DIRS) {
|
||||
errno = ENOSPC;
|
||||
PDEBUG("%s: exceeded number of supported cache overlays\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
fd = open_or_create_cache_dir(policy_cache->features, dirfd, path,
|
||||
false, &cache_dir);
|
||||
if (fd == -1) {
|
||||
PDEBUG("%s: failed to open_or_create_cache_dir %m\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
policy_cache->dirfd[policy_cache->n++] = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
|
||||
* @policy_cache: the policy_cache
|
||||
@@ -210,13 +489,14 @@ aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
|
||||
*/
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
int save = errno;
|
||||
int i, save = errno;
|
||||
|
||||
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
|
||||
aa_features_unref(policy_cache->features);
|
||||
aa_features_unref(policy_cache->kernel_features);
|
||||
if (policy_cache->dirfd != -1)
|
||||
close(policy_cache->dirfd);
|
||||
for (i = 0; i < MAX_POLICY_CACHE_OVERLAY_DIRS; i++) {
|
||||
if (policy_cache->dirfd[i] != -1)
|
||||
close(policy_cache->dirfd[i]);
|
||||
}
|
||||
free(policy_cache);
|
||||
}
|
||||
|
||||
@@ -254,7 +534,7 @@ int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
if (kernel_interface) {
|
||||
aa_kernel_interface_ref(kernel_interface);
|
||||
} else if (aa_kernel_interface_new(&kernel_interface,
|
||||
policy_cache->kernel_features,
|
||||
policy_cache->features,
|
||||
NULL) == -1) {
|
||||
kernel_interface = NULL;
|
||||
return -1;
|
||||
@@ -262,10 +542,158 @@ int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
|
||||
cb_data.policy_cache = policy_cache;
|
||||
cb_data.kernel_interface = kernel_interface;
|
||||
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data,
|
||||
replace_all_cb);
|
||||
retval = _aa_overlaydirat_for_each(policy_cache->dirfd, policy_cache->n,
|
||||
&cb_data, replace_all_cb);
|
||||
|
||||
aa_kernel_interface_unref(kernel_interface);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_no_dirs - return the number of dirs making up the cache
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: The number of directories that the policy cache is composed of
|
||||
*/
|
||||
int aa_policy_cache_no_dirs(aa_policy_cache *policy_cache)
|
||||
{
|
||||
return policy_cache->n;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_dir_path - returns the path to the aa_policy_cache directory
|
||||
* @policy_cache: the policy_cache
|
||||
* @dir: which dir in the policy cache to return the name of
|
||||
*
|
||||
* Returns: The path to the policy cache directory on success, NULL on
|
||||
* error with errno set.
|
||||
*/
|
||||
char *aa_policy_cache_dir_path(aa_policy_cache *policy_cache, int dir)
|
||||
{
|
||||
char *path = NULL;
|
||||
|
||||
if (dir < 0 || dir >= policy_cache->n) {
|
||||
PERROR("aa_policy_cache directory: %d does not exist\n", dir);
|
||||
errno = ERANGE;
|
||||
} else {
|
||||
path = path_from_fd(policy_cache->dirfd[dir]);
|
||||
}
|
||||
|
||||
if (!path)
|
||||
PERROR("Can't return the path to the aa_policy_cache directory: %m\n");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_dirfd - returns the dirfd for a aa_policy_cache directory
|
||||
* @policy_cache: the policy_cache
|
||||
* @dir: which dir in the policy cache to return the dirfd of
|
||||
*
|
||||
* Returns: The dirfd to the @dir policy cache directory on success, -1 on
|
||||
* error with errno set.
|
||||
*
|
||||
* caller is responsible for closing the returned dirfd
|
||||
*/
|
||||
int aa_policy_cache_dirfd(aa_policy_cache *policy_cache, int dir)
|
||||
{
|
||||
if (dir < 0 || dir >= policy_cache->n) {
|
||||
PERROR("aa_policy_cache directory: %d does not exist\n", dir);
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dup(policy_cache->dirfd[dir]);
|
||||
}
|
||||
|
||||
/* open cache file corresponding to name */
|
||||
int aa_policy_cache_open(aa_policy_cache *policy_cache, const char *name,
|
||||
int flags)
|
||||
{
|
||||
int i, fd;
|
||||
|
||||
for (i = 0; i < policy_cache->n; i++) {
|
||||
fd = openat(policy_cache->dirfd[i], name, flags);
|
||||
if (fd != -1)
|
||||
return fd;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *aa_policy_cache_filename(aa_policy_cache *policy_cache, const char *name)
|
||||
{
|
||||
char *path;
|
||||
autoclose int fd = aa_policy_cache_open(policy_cache, name, O_RDONLY);
|
||||
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
path = path_from_fd(fd);
|
||||
if (!path)
|
||||
PERROR("Can't return the path to the aa_policy_cache cachename: %m\n");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_dir_path_preview - returns the path to the aa_policy_cache directory
|
||||
* @kernel_features: features representing a kernel (may be NULL if you want to
|
||||
* use the features of the currently running kernel)
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to the policy cache
|
||||
*
|
||||
* Returns: The path to the policy cache directory on success, NULL on
|
||||
* error with errno set.
|
||||
*/
|
||||
char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
autofree char *cache_loc = NULL;
|
||||
autofree char *cache_dir = NULL;
|
||||
char *dir_path;
|
||||
|
||||
if (kernel_features) {
|
||||
aa_features_ref(kernel_features);
|
||||
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave cache_loc set to NULL if dirfd is AT_FDCWD and handle a
|
||||
* NULL cache_loc in the asprintf() below
|
||||
*/
|
||||
if (dirfd != AT_FDCWD) {
|
||||
cache_loc = path_from_fd(dirfd);
|
||||
if (!cache_loc) {
|
||||
int save = errno;
|
||||
|
||||
PERROR("Can't return the path to the aa_policy_cache cache location: %m\n");
|
||||
aa_features_unref(kernel_features);
|
||||
errno = save;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PDEBUG("Looking up cachedir path for AT_FDCWD\n");
|
||||
if (cache_dir_from_path_and_features(&cache_dir, dirfd, path,
|
||||
kernel_features)) {
|
||||
int save = errno;
|
||||
|
||||
PERROR("Can't return the path to the aa_policy_cache directory: %m\n");
|
||||
aa_features_unref(kernel_features);
|
||||
errno = save;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aa_features_unref(kernel_features);
|
||||
|
||||
if (asprintf(&dir_path, "%s%s%s",
|
||||
cache_loc ? : "", cache_loc ? "/" : "", cache_dir) == -1) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PDEBUG("aa_policy_cache_dir_path_preview() returning '%s'\n", dir_path);
|
||||
return dir_path;
|
||||
}
|
||||
|
@@ -38,11 +38,24 @@
|
||||
#ifndef HAVE_SECURE_GETENV
|
||||
#ifdef HAVE___SECURE_GETENV
|
||||
#define secure_getenv __secure_getenv
|
||||
#elif ENABLE_DEBUG_OUTPUT
|
||||
#error Debug output is not possible without a secure_getenv() implementation.
|
||||
#else
|
||||
#error neither secure_getenv nor __secure_getenv is available
|
||||
#define secure_getenv(env) NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allow libapparmor to build on older glibcs and other libcs that do
|
||||
* not support reallocarray.
|
||||
*/
|
||||
#ifndef HAVE_REALLOCARRY
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
return realloc(ptr, nmemb * size);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ignored_suffix_t {
|
||||
const char * text;
|
||||
int len;
|
||||
@@ -56,6 +69,10 @@ static struct ignored_suffix_t ignored_suffixes[] = {
|
||||
{ ".dpkg-old", 9, 1 },
|
||||
{ ".dpkg-dist", 10, 1 },
|
||||
{ ".dpkg-bak", 9, 1 },
|
||||
{ ".dpkg-remove", 12, 1 },
|
||||
/* Archlinux packaging files */
|
||||
{ ".pacsave", 8, 1 },
|
||||
{ ".pacnew", 7, 1 },
|
||||
/* RPM packaging files have traditionally not been silently
|
||||
ignored */
|
||||
{ ".rpmnew", 7, 0 },
|
||||
@@ -169,13 +186,252 @@ int _aa_asprintf(char **strp, const char *fmt, ...)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dot_or_dot_dot_filter(const struct dirent *ent)
|
||||
/* stops on first error, can use errno or return value to communicate
|
||||
* the goal is to use this to replace _aa_dirat_for_each, but that will
|
||||
* be a different patch.
|
||||
*/
|
||||
int _aa_dirat_for_each2(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const struct dirent *, void *))
|
||||
{
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
return 0;
|
||||
autoclose int cb_dirfd = -1;
|
||||
int fd_for_dir = -1;
|
||||
const struct dirent *ent;
|
||||
DIR *dir;
|
||||
int save, rc;
|
||||
|
||||
return 1;
|
||||
if (!cb || !name) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
save = errno;
|
||||
|
||||
cb_dirfd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (cb_dirfd == -1) {
|
||||
PDEBUG("could not open directory fd '%d' '%s': %m\n", dirfd, name);
|
||||
return -1;
|
||||
}
|
||||
/* dup cd_dirfd because fdopendir has claimed the fd passed to it */
|
||||
fd_for_dir = dup(cb_dirfd);
|
||||
if (fd_for_dir == -1) {
|
||||
PDEBUG("could not dup directory fd '%s': %m\n", name);
|
||||
return -1;
|
||||
}
|
||||
dir = fdopendir(fd_for_dir);
|
||||
if (!dir) {
|
||||
PDEBUG("could not open directory '%s' from fd '%d': %m\n", name, fd_for_dir);
|
||||
close(fd_for_dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir))) {
|
||||
if (cb) {
|
||||
rc = (*cb)(cb_dirfd, ent, data);
|
||||
if (rc) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
ent->d_name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
errno = save;
|
||||
|
||||
out:
|
||||
closedir(dir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#define max(a, b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
#define CHUNK 32
|
||||
struct overlaydir {
|
||||
int dirfd;
|
||||
struct dirent *dent;
|
||||
};
|
||||
|
||||
static int insert(struct overlaydir **overlayptr, int *max_size, int *size,
|
||||
int pos, int remaining, int dirfd, struct dirent *ent)
|
||||
{
|
||||
struct overlaydir *overlay = *overlayptr;
|
||||
int i, chunk = max(remaining, CHUNK);
|
||||
|
||||
if (size + 1 >= max_size) {
|
||||
struct overlaydir *tmp = reallocarray(overlay,
|
||||
*max_size + chunk,
|
||||
sizeof(*overlay));
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
overlay = tmp;
|
||||
}
|
||||
*max_size += chunk;
|
||||
(*size)++;
|
||||
for (i = *size; i > pos; i--)
|
||||
overlay[i] = overlay[i - 1];
|
||||
overlay[pos].dirfd = dirfd;
|
||||
overlay[pos].dent = ent;
|
||||
|
||||
*overlayptr = overlay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define merge(overlay, n_overlay, max_size, list, n_list, dirfd) \
|
||||
({ \
|
||||
int i, j; \
|
||||
int rc = 0; \
|
||||
\
|
||||
for (i = 0, j = 0; i < n_overlay && j < n_list; ) { \
|
||||
int res = strcmp(overlay[i].dent->d_name, list[j]->d_name);\
|
||||
if (res < 0) { \
|
||||
i++; \
|
||||
continue; \
|
||||
} else if (res == 0) { \
|
||||
free(list[j]); \
|
||||
list[j] = NULL; \
|
||||
i++; \
|
||||
j++; \
|
||||
} else { \
|
||||
if ((rc = insert(&overlay, &max_size, &n_overlay, i,\
|
||||
n_list - j, dirfd, list[j]))) \
|
||||
goto fail; \
|
||||
i++; \
|
||||
list[j++] = NULL; \
|
||||
} \
|
||||
} \
|
||||
while (j < n_list) { \
|
||||
if ((rc = insert(&overlay, &max_size, &n_overlay, i, \
|
||||
n_list - j, dirfd,list[j]))) \
|
||||
goto fail; \
|
||||
i++; \
|
||||
list[j++] = NULL; \
|
||||
} \
|
||||
\
|
||||
fail: \
|
||||
rc; \
|
||||
})
|
||||
|
||||
static ssize_t readdirfd(int dirfd, struct dirent ***out,
|
||||
int (*dircmp)(const struct dirent **, const struct dirent **))
|
||||
{
|
||||
struct dirent **dents = NULL, *dent;
|
||||
ssize_t n = 0;
|
||||
size_t i;
|
||||
int save;
|
||||
DIR *dir;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
/*
|
||||
* closedir(dir) will close the underlying fd, so we need
|
||||
* to dup first
|
||||
*/
|
||||
if ((dirfd = dup(dirfd)) < 0) {
|
||||
PDEBUG("dup of dirfd failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dir = fdopendir(dirfd)) == NULL) {
|
||||
PDEBUG("fdopendir of dirfd failed: %m\n");
|
||||
close(dirfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get number of directory entries */
|
||||
while ((dent = readdir(dir)) != NULL) {
|
||||
if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
|
||||
continue;
|
||||
n++;
|
||||
}
|
||||
rewinddir(dir);
|
||||
|
||||
dents = calloc(n, sizeof(struct dirent *));
|
||||
if (!dents)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < n; ) {
|
||||
if ((dent = readdir(dir)) == NULL) {
|
||||
PDEBUG("readdir of entry[%d] failed: %m\n", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
|
||||
continue;
|
||||
|
||||
dents[i] = malloc(sizeof(*dents[i]));
|
||||
if (!dents[i])
|
||||
goto fail;
|
||||
memcpy(dents[i], dent, sizeof(*dent));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (dircmp)
|
||||
qsort(dents, n, sizeof(*dent), (int (*)(const void *, const void *))dircmp);
|
||||
|
||||
*out = dents;
|
||||
closedir(dir);
|
||||
return n;
|
||||
|
||||
fail:
|
||||
save = errno;
|
||||
if (dents) {
|
||||
for (i = 0; i < n; i++)
|
||||
free(dents[i]);
|
||||
}
|
||||
free(dents);
|
||||
closedir(dir);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _aa_overlaydirat_for_each(int dirfd[], int n, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *))
|
||||
{
|
||||
autofree struct dirent **list = NULL;
|
||||
autofree struct overlaydir *overlay = NULL;
|
||||
int i, k;
|
||||
int n_list, size = 0, max_size = 0;
|
||||
int rc = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
n_list = readdirfd(dirfd[i], &list, alphasort);
|
||||
if (n_list == -1) {
|
||||
PDEBUG("scandirat of dirfd[%d] failed: %m\n", i);
|
||||
return -1;
|
||||
}
|
||||
if (merge(overlay, size, max_size, list, n_list, dirfd[i])) {
|
||||
for (k = 0; k < n_list; k++)
|
||||
free(list[i]);
|
||||
for (k = 0; k < size; k++)
|
||||
free(overlay[k].dent);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (rc = 0, i = 0; i < size; i++) {
|
||||
/* Must cycle through all dirs so that each one is autofreed */
|
||||
autofree struct dirent *dent = overlay[i].dent;
|
||||
struct stat my_stat;
|
||||
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
if (fstatat(overlay[i].dirfd, dent->d_name, &my_stat,
|
||||
AT_SYMLINK_NOFOLLOW)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", dent->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb(overlay[i].dirfd, dent->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
dent->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,8 +475,7 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_dirs = scandirat(cb_dirfd, ".", &namelist,
|
||||
dot_or_dot_dot_filter, NULL);
|
||||
num_dirs = readdirfd(cb_dirfd, &namelist, NULL);
|
||||
if (num_dirs == -1) {
|
||||
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
|
||||
return -1;
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#ifndef _AA_PRIVATE_H
|
||||
#define _AA_PRIVATE_H 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/apparmor_private.h>
|
||||
|
||||
@@ -51,4 +52,7 @@ void print_debug(const char *fmt, ...);
|
||||
void atomic_inc(unsigned int *v);
|
||||
bool atomic_dec_and_test(unsigned int *v);
|
||||
|
||||
int _aa_dirat_for_each2(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const struct dirent *, void *));
|
||||
|
||||
#endif /* _AA_PRIVATE_H */
|
||||
|
@@ -12,6 +12,7 @@ LibAppArmor.pm: libapparmor_wrap.c
|
||||
|
||||
Makefile.perl: Makefile.PL LibAppArmor.pm
|
||||
$(PERL) $< PREFIX=$(prefix) MAKEFILE=$@
|
||||
sed -ie 's/LD_RUN_PATH="\x24(LD_RUN_PATH)"//g' Makefile.perl
|
||||
sed -ie 's/^LD_RUN_PATH.*//g' Makefile.perl
|
||||
|
||||
LibAppArmor.so: libapparmor_wrap.c Makefile.perl
|
||||
|
@@ -5,7 +5,7 @@ setup(name = 'LibAppArmor',
|
||||
version = '@VERSION@',
|
||||
author = 'AppArmor Dev Team',
|
||||
author_email = 'apparmor@lists.ubuntu.com',
|
||||
url = 'http://wiki.apparmor.net',
|
||||
url = 'https://wiki.apparmor.net',
|
||||
description = 'AppArmor python bindings',
|
||||
download_url = 'https://launchpad.net/apparmor/+download',
|
||||
package_dir = {'LibAppArmor': '@srcdir@'},
|
||||
|
@@ -2,6 +2,8 @@
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
|
||||
# NOVELL (All rights reserved)
|
||||
#
|
||||
# Copyright (c) Christian Boltz 2018
|
||||
#
|
||||
# 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.
|
||||
@@ -22,14 +24,15 @@ include $(COMMONDIR)/Make.rules
|
||||
|
||||
DESTDIR=/
|
||||
APPARMOR_BIN_PREFIX=${DESTDIR}/lib/apparmor
|
||||
SYSTEMD_UNIT_DIR=${DESTDIR}/usr/lib/systemd/system
|
||||
CONFDIR=/etc/apparmor
|
||||
INSTALL_CONFDIR=${DESTDIR}${CONFDIR}
|
||||
LOCALEDIR=/usr/share/locale
|
||||
MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 subdomain.conf.5
|
||||
MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 subdomain.conf.5 aa-teardown.8
|
||||
|
||||
YACC := /usr/bin/bison
|
||||
YACC := bison
|
||||
YFLAGS := -d
|
||||
LEX := /usr/bin/flex
|
||||
LEX := flex
|
||||
LEXFLAGS = -B -v
|
||||
WARNINGS = -Wall
|
||||
EXTRA_WARNINGS = -Wsign-compare -Wmissing-field-initializers -Wformat-security -Wunused-parameter
|
||||
@@ -314,12 +317,9 @@ install-redhat:
|
||||
install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
|
||||
|
||||
.PHONY: install-suse
|
||||
install-suse:
|
||||
install -m 755 -d $(DESTDIR)/etc/init.d
|
||||
install -m 755 rc.apparmor.$(subst install-,,$(@)) $(DESTDIR)/etc/init.d/boot.apparmor
|
||||
install-suse: install-systemd
|
||||
install -m 755 -d $(DESTDIR)/sbin
|
||||
ln -sf /etc/init.d/boot.apparmor $(DESTDIR)/sbin/rcapparmor
|
||||
ln -sf rcapparmor $(DESTDIR)/sbin/rcsubdomain
|
||||
ln -sf service $(DESTDIR)/sbin/rcapparmor
|
||||
|
||||
.PHONY: install-slackware
|
||||
install-slackware:
|
||||
@@ -379,6 +379,14 @@ install-indep: indep
|
||||
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
|
||||
$(MAKE) install_manpages DESTDIR=${DESTDIR}
|
||||
|
||||
.PHONY: install-systemd
|
||||
install-systemd:
|
||||
install -m 755 -d $(SYSTEMD_UNIT_DIR)
|
||||
install -m 644 apparmor.service $(SYSTEMD_UNIT_DIR)
|
||||
install -m 755 apparmor.systemd $(APPARMOR_BIN_PREFIX)
|
||||
install -m 755 -d $(DESTDIR)/usr/sbin
|
||||
install -m 755 aa-teardown $(DESTDIR)/usr/sbin
|
||||
|
||||
ifndef VERBOSE
|
||||
.SILENT: clean
|
||||
endif
|
||||
|
@@ -2,19 +2,6 @@ The apparmor_parser allows you to add, replace, and remove AppArmor
|
||||
policy through the use of command line options. The default is to add.
|
||||
`apparmor_parser --help` shows what the command line options are.
|
||||
|
||||
You can also find more information at http://wiki.apparmor.net
|
||||
|
||||
Please send all complaints, feature requests, rants about the software,
|
||||
and questions to the apparmor@lists.ubuntu.com mailing list. Bug
|
||||
reports can be filed against the AppArmor project on launchpad.net at
|
||||
https://launchpad.net/apparmor or reported to the mailing list directly
|
||||
for those who wish not to register for an account on launchpad.
|
||||
|
||||
Security issues can be filed as security bugs on launchpad
|
||||
or directed to security@ubuntu.com. We will attempt to
|
||||
conform to the RFP vulnerability disclosure protocol:
|
||||
http://www.wiretrip.net/rfp/policy.html
|
||||
|
||||
Thanks.
|
||||
You can also find more information at https://wiki.apparmor.net
|
||||
|
||||
-- The AppArmor development team
|
||||
|
10
parser/aa-teardown
Normal file
10
parser/aa-teardown
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
test $# = 0 || {
|
||||
echo "Usage: $0"
|
||||
echo
|
||||
echo "Unloads all AppArmor profiles"
|
||||
exit 1
|
||||
}
|
||||
|
||||
/lib/apparmor/apparmor.systemd stop
|
40
parser/aa-teardown.pod
Normal file
40
parser/aa-teardown.pod
Normal file
@@ -0,0 +1,40 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2018 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
aa-teardown - unload all AppArmor profiles
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<aa-teardown>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
aa-teardown unloads all AppArmor profiles
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
If you find any bugs, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), and L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -55,7 +55,7 @@ B<VARIABLE> = '@{' I<ALPHA> [ ( I<ALPHANUMERIC> | '_' ) ... ] '}'
|
||||
|
||||
B<ALIAS RULE> = 'alias' I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH> ','
|
||||
|
||||
B<INCLUDE> = '#include' ( I<ABS PATH> | I<MAGIC PATH> )
|
||||
B<INCLUDE> = ( '#include' | 'include' ) [ 'if exists' ] ( I<ABS PATH> | I<MAGIC PATH> )
|
||||
|
||||
B<ABS PATH> = '"' path '"' (the path is passed to open(2))
|
||||
|
||||
@@ -1414,13 +1414,17 @@ rules into a rule block.
|
||||
|
||||
=head2 #include mechanism
|
||||
|
||||
AppArmor provides an easy abstraction mechanism to group common file
|
||||
AppArmor provides an easy abstraction mechanism to group common
|
||||
access requirements; this abstraction is an extremely flexible way to
|
||||
grant site-specific rights and makes writing new AppArmor profiles very
|
||||
simple by assembling the needed building blocks for any given program.
|
||||
|
||||
The use of '#include' is modelled directly after cpp(1); its use will
|
||||
replace the '#include' statement with the specified file's contents.
|
||||
The leading '#' is optional, and the '#include' keyword can be followed
|
||||
by an option conditional 'if exists' that specifies profile compilation
|
||||
should continue if the specified file or directory is not found.
|
||||
|
||||
B<#include "/absolute/path"> specifies that F</absolute/path> should be
|
||||
used. B<#include "relative/path"> specifies that F<relative/path> should
|
||||
be used, where the path is relative to the current working directory.
|
||||
@@ -1607,6 +1611,6 @@ negative values match when specifying one or the other. Eg, 'rw' matches when
|
||||
|
||||
apparmor(7), apparmor_parser(8), aa-complain(1),
|
||||
aa-enforce(1), aa_change_hat(2), mod_apparmor(5), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -70,9 +70,12 @@ with B<.> (except for the root B</>) so profiles are easier to manage
|
||||
(e.g. the F</usr/sbin/nscd> profile would be named F<usr.sbin.nscd>).
|
||||
|
||||
Profiles are applied to a process at exec(3) time (as seen through the
|
||||
execve(2) system call); an already running process cannot be confined.
|
||||
However, once a profile is loaded for a program, that program will be
|
||||
confined on the next exec(3).
|
||||
execve(2) system call): once a profile is loaded for a program, that
|
||||
program will be confined on the next exec(3). If a process is already
|
||||
running under a profile, when one replaces that profile in the kernel,
|
||||
the updated profile is applied immediately to that process.
|
||||
On the other hand, a process that is already running unconfined cannot
|
||||
be confined.
|
||||
|
||||
AppArmor supports the Linux kernel's securityfs filesystem, and makes
|
||||
available the list of the profiles currently loaded; to mount the
|
||||
@@ -162,6 +165,6 @@ apparmor_parser(8), aa_change_hat(2), apparmor.d(5),
|
||||
subdomain.conf(5), aa-autodep(1), clean(1),
|
||||
auditd(8),
|
||||
aa-unconfined(8), aa-enforce(1), aa-complain(1), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
26
parser/apparmor.service
Normal file
26
parser/apparmor.service
Normal file
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=Load AppArmor profiles
|
||||
DefaultDependencies=no
|
||||
Before=sysinit.target
|
||||
After=systemd-journald-audit.socket
|
||||
# profile cache
|
||||
After=var.mount var-lib.mount
|
||||
ConditionSecurity=apparmor
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/lib/apparmor/apparmor.systemd reload
|
||||
ExecReload=/lib/apparmor/apparmor.systemd reload
|
||||
|
||||
# systemd maps 'restart' to 'stop; start' which means removing AppArmor confinement
|
||||
# from running processes (and not being able to re-apply it later).
|
||||
# Upstream systemd developers refused to implement an option that allows overriding
|
||||
# this behaviour, therefore we have to make ExecStop a no-op to error out on the
|
||||
# safe side.
|
||||
#
|
||||
# If you really want to unload all AppArmor profiles, run aa-teardown
|
||||
ExecStop=/bin/true
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
100
parser/apparmor.systemd
Normal file
100
parser/apparmor.systemd
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# 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.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
||||
|
||||
aa_action()
|
||||
{
|
||||
echo $1
|
||||
shift
|
||||
"$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
aa_log_warning_msg()
|
||||
{
|
||||
echo "Warning: $@"
|
||||
}
|
||||
|
||||
aa_log_failure_msg()
|
||||
{
|
||||
echo "Error: $@"
|
||||
}
|
||||
|
||||
aa_log_action_start()
|
||||
{
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
aa_log_action_end()
|
||||
{
|
||||
echo -n
|
||||
}
|
||||
|
||||
aa_log_daemon_msg()
|
||||
{
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
aa_log_skipped_msg()
|
||||
{
|
||||
echo "Skipped: $@"
|
||||
}
|
||||
|
||||
aa_log_end_msg()
|
||||
{
|
||||
echo -n
|
||||
}
|
||||
|
||||
# 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=$?
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $rc
|
@@ -46,9 +46,10 @@ program. The B<profiles> may be specified by file name or a directory
|
||||
name containing a set of profiles. If a directory is specified then the
|
||||
B<apparmor_parser> will try to do a profile load for each file in the
|
||||
directory that is not a dot file, or explicitly black listed (*.dpkg-new,
|
||||
*.dpkg-old, *.dpkg-dist, *-dpkg-bak, *.repnew, *.rpmsave, *orig, *.rej,
|
||||
*~). The B<apparmor_parser> will fall back to taking input from standard
|
||||
input if a profile or directory is not supplied.
|
||||
*.dpkg-old, *.dpkg-dist, *.dpkg-bak, *.dpkg-remove, *.pacsave, *.pacnew,
|
||||
*.rpmnew, *.rpmsave, *.orig, *.rej, *~).
|
||||
The B<apparmor_parser> will fall back to taking input from standard input if
|
||||
a profile or directory is not supplied.
|
||||
|
||||
The input supplied to B<apparmor_parser> should be in the format described in
|
||||
apparmor.d(5).
|
||||
@@ -232,8 +233,28 @@ inconsistent state
|
||||
|
||||
=item -L, --cache-loc
|
||||
|
||||
Set the location of the cache directory. If not specified the cache location
|
||||
defaults to /etc/apparmor.d/cache
|
||||
Set the location(s) of the cache directory. This option can accept a
|
||||
comma separated list of directories, which will be searched in order
|
||||
to find a matching cache. The first matching cache file found is used
|
||||
even if a directory later in the search order may contain a newer cache
|
||||
file.
|
||||
|
||||
If multiple directories are specified and --write-cache has been specified
|
||||
then cache writes will be made to the first directory in the list, all
|
||||
other directories will be treated as read only.
|
||||
|
||||
If a cache directory name needs to have a comma as part of the name, it
|
||||
can be specified by using a backslash to escape the comma character in
|
||||
the directory name.
|
||||
|
||||
If not specified the cache location defaults to /var/cache/apparmor
|
||||
|
||||
=item --print-cache-dir
|
||||
|
||||
Print the cache directory location. This path will be a subdirectory of the
|
||||
directory specified by --cache-loc. The subdirectory used will be influenced by
|
||||
the features available in the currently running kernel or by the features
|
||||
specified with the --match-string or --features-file options.
|
||||
|
||||
=item -Q, --skip-kernel-load
|
||||
|
||||
@@ -334,6 +355,17 @@ 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 --config-file
|
||||
|
||||
Specify the config file to use instead of
|
||||
/etc/apparmor/parser.conf. This option will be processed early before
|
||||
regular options regardless of the order it is specified in.
|
||||
|
||||
=item --print-config-file
|
||||
|
||||
Print the config file location that will be used.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
=head1 CONFIG FILE
|
||||
@@ -376,6 +408,6 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), subdomain.conf(5), aa_change_hat(2), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "parser.h"
|
||||
#include "profile.h"
|
||||
|
||||
typedef int (*comparison_fn_t)(const void *, const void *);
|
||||
|
||||
struct alias_rule {
|
||||
char *from;
|
||||
char *to;
|
||||
|
@@ -144,7 +144,7 @@ static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void include_filename(char *filename, int search)
|
||||
void include_filename(char *filename, int search, bool if_exists)
|
||||
{
|
||||
FILE *include_file = NULL;
|
||||
struct stat my_stat;
|
||||
@@ -161,11 +161,14 @@ void include_filename(char *filename, int search)
|
||||
include_file = fopen(fullpath, "r");
|
||||
}
|
||||
|
||||
if (!include_file)
|
||||
if (!include_file) {
|
||||
if (if_exists)
|
||||
return;
|
||||
yyerror(_("Could not open '%s'"),
|
||||
fullpath ? fullpath: filename);
|
||||
}
|
||||
|
||||
if (fstat(fileno(include_file), &my_stat))
|
||||
if (fstat(fileno(include_file), &my_stat))
|
||||
yyerror(_("fstat failed for '%s'"), fullpath);
|
||||
|
||||
if (S_ISREG(my_stat.st_mode)) {
|
||||
@@ -200,7 +203,7 @@ MODES {MODE_CHARS}+
|
||||
WS [[:blank:]]
|
||||
NUMBER [[:digit:]]+
|
||||
|
||||
ID_CHARS [^ \t\n"!,]
|
||||
ID_CHARS [^ \t\r\n"!,]
|
||||
ID {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,)
|
||||
IDS {ID}+
|
||||
POST_VAR_ID_CHARS [^ \t\n"!,]{-}[=\+]
|
||||
@@ -257,6 +260,8 @@ LT_EQUAL <=
|
||||
%x UNIX_MODE
|
||||
%x CHANGE_PROFILE_MODE
|
||||
%x INCLUDE
|
||||
%x INCLUDE_EXISTS
|
||||
%x ABI_MODE
|
||||
|
||||
%%
|
||||
|
||||
@@ -269,21 +274,59 @@ LT_EQUAL <=
|
||||
}
|
||||
%}
|
||||
|
||||
<INITIAL,SUB_ID_WS,INCLUDE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE>{
|
||||
<INITIAL,SUB_ID_WS,INCLUDE,INCLUDE_EXISTS,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE>{
|
||||
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
|
||||
}
|
||||
|
||||
<INCLUDE>{
|
||||
(\<([^\> \t\n]+)\>|\"([^\" \t\n]+)\") { /* <filename> */
|
||||
<INCLUDE_EXISTS>{
|
||||
(\<([^"\>\t\r\n]+)\>|{QUOTED_ID}) { /* <filename> | "filename" */
|
||||
autofree char *filename = strndup(yytext, yyleng - 1);
|
||||
include_filename(filename + 1, *filename == '<');
|
||||
include_filename(filename + 1, *filename == '<', true);
|
||||
POP_NODUMP();
|
||||
}
|
||||
|
||||
[^\<\>\" \t\n]+ { /* filename */
|
||||
include_filename(yytext, 0);
|
||||
(\<{QUOTED_ID}\>) { /* <"filename"> */
|
||||
autofree char *filename = strndup(yytext, yyleng - 2);
|
||||
include_filename(filename + 2, true, true);
|
||||
POP_NODUMP();
|
||||
}
|
||||
|
||||
({IDS}|{QUOTED_ID}) { /* filename */
|
||||
include_filename(yytext, 0, true);
|
||||
POP_NODUMP();
|
||||
}
|
||||
}
|
||||
|
||||
<INCLUDE>{
|
||||
(\<([^"\>\t\r\n]+)\>|{QUOTED_ID}) { /* <filename> | "filename" */
|
||||
autofree char *filename = strndup(yytext, yyleng - 1);
|
||||
include_filename(filename + 1, *filename == '<', false);
|
||||
POP_NODUMP();
|
||||
}
|
||||
|
||||
(\<{QUOTED_ID}\>) { /* <"filename"> */
|
||||
autofree char *filename = strndup(yytext, yyleng - 2);
|
||||
include_filename(filename + 2, true, false);
|
||||
POP_NODUMP();
|
||||
}
|
||||
|
||||
({IDS}|{QUOTED_ID}) { /* filename */
|
||||
include_filename(yytext, 0, false);
|
||||
POP_NODUMP();
|
||||
}
|
||||
}
|
||||
|
||||
<ABI_MODE>{
|
||||
(\<(([^"\>\t\r\n]+)|{QUOTED_ID})\>|{QUOTED_ID}|{IDS}) { /* <filename> | <"filename"> | "filename" | filename */
|
||||
int lt = *yytext == '<' ? 1 : 0;
|
||||
char *filename = processid(yytext + lt, yyleng - lt*2);
|
||||
bool exists = YYSTATE == INCLUDE_EXISTS;
|
||||
|
||||
if (!filename)
|
||||
yyerror(_("Failed to process filename\n"));
|
||||
yylval.id = filename;
|
||||
POP_AND_RETURN(TOK_ID);
|
||||
}
|
||||
}
|
||||
|
||||
<<EOF>> {
|
||||
@@ -527,6 +570,20 @@ LT_EQUAL <=
|
||||
}
|
||||
}
|
||||
|
||||
#include{WS}+if{WS}+exists/{WS}.*\r?\n {
|
||||
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||
* It needs to be handled specially
|
||||
*/
|
||||
yy_push_state(INCLUDE_EXISTS);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
yy_push_state(INCLUDE_EXISTS);
|
||||
}
|
||||
|
||||
#include/.*\r?\n {
|
||||
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||
* It needs to be handled specially
|
||||
@@ -623,6 +680,9 @@ include/{WS} {
|
||||
case TOK_UNIX:
|
||||
state = UNIX_MODE;
|
||||
break;
|
||||
case TOK_ABI:
|
||||
state = ABI_MODE;
|
||||
break;
|
||||
default: /* nothing */
|
||||
break;
|
||||
}
|
||||
@@ -675,4 +735,6 @@ unordered_map<int, string> state_names = {
|
||||
STATE_TABLE_ENT(UNIX_MODE),
|
||||
STATE_TABLE_ENT(CHANGE_PROFILE_MODE),
|
||||
STATE_TABLE_ENT(INCLUDE),
|
||||
STATE_TABLE_ENT(INCLUDE_EXISTS),
|
||||
STATE_TABLE_ENT(ABI_MODE),
|
||||
};
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* Copyright (c) 2010 - 2013
|
||||
* Copyright (c) 2010 - 2018
|
||||
* Canonical Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -59,8 +59,10 @@
|
||||
#define PRIVILEGED_OPS (kernel_load)
|
||||
#define UNPRIVILEGED_OPS (!(PRIVILEGED_OPS))
|
||||
|
||||
#define EARLY_ARG_CONFIG_FILE 141
|
||||
|
||||
const char *parser_title = "AppArmor parser";
|
||||
const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2012 Canonical Ltd.";
|
||||
const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2018 Canonical Ltd.";
|
||||
|
||||
int opt_force_complain = 0;
|
||||
int binary_input = 0;
|
||||
@@ -97,12 +99,20 @@ long jobs_scale = 0; /* number of chance to resample online
|
||||
*/
|
||||
bool debug_jobs = false;
|
||||
|
||||
#define MAX_CACHE_LOCS 4
|
||||
|
||||
struct timespec cache_tstamp, mru_policy_tstamp;
|
||||
|
||||
static char *apparmorfs = NULL;
|
||||
static char *cacheloc = NULL;
|
||||
static const char *cacheloc[MAX_CACHE_LOCS];
|
||||
static int cacheloc_n = 0;
|
||||
static bool print_cache_dir = false;
|
||||
|
||||
static aa_features *compile_features = NULL;
|
||||
static aa_features *kernel_features = NULL;
|
||||
|
||||
static const char *config_file = "/etc/apparmor/parser.conf";
|
||||
|
||||
static aa_features *features = NULL;
|
||||
|
||||
/* 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:";
|
||||
@@ -133,9 +143,6 @@ struct option long_options[] = {
|
||||
{"skip-read-cache", 0, 0, 'T'},
|
||||
{"write-cache", 0, 0, 'W'},
|
||||
{"show-cache", 0, 0, 'k'},
|
||||
{"skip-bad-cache", 0, 0, 129}, /* no short option */
|
||||
{"purge-cache", 0, 0, 130}, /* no short option */
|
||||
{"create-cache-dir", 0, 0, 131}, /* no short option */
|
||||
{"cache-loc", 1, 0, 'L'},
|
||||
{"debug", 2, 0, 'd'},
|
||||
{"dump", 1, 0, 'D'},
|
||||
@@ -143,12 +150,21 @@ struct option long_options[] = {
|
||||
{"optimize", 1, 0, 'O'},
|
||||
{"Optimize", 1, 0, 'O'},
|
||||
{"preprocess", 0, 0, 'p'},
|
||||
{"jobs", 1, 0, 'j'},
|
||||
{"skip-bad-cache", 0, 0, 129}, /* no short option */
|
||||
{"purge-cache", 0, 0, 130}, /* no short option */
|
||||
{"create-cache-dir", 0, 0, 131}, /* no short option */
|
||||
{"abort-on-error", 0, 0, 132}, /* no short option */
|
||||
{"skip-bad-cache-rebuild", 0, 0, 133}, /* no short option */
|
||||
{"warn", 1, 0, 134}, /* no short option */
|
||||
{"debug-cache", 0, 0, 135}, /* no short option */
|
||||
{"jobs", 1, 0, 'j'},
|
||||
{"max-jobs", 1, 0, 136}, /* no short option */
|
||||
{"print-cache-dir", 0, 0, 137}, /* no short option */
|
||||
{"kernel-features", 1, 0, 138}, /* no short option */
|
||||
{"compile-features", 1, 0, 139}, /* no short option */
|
||||
{"print-config-file", 0, 0, 140}, /* no short option */
|
||||
{"config-file", 1, 0, EARLY_ARG_CONFIG_FILE}, /* early option, no short option */
|
||||
|
||||
{NULL, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -178,7 +194,8 @@ static void display_usage(const char *command)
|
||||
"-I n, --Include n Add n to the search path\n"
|
||||
"-f n, --subdomainfs n Set location of apparmor filesystem\n"
|
||||
"-m n, --match-string n Use only features n\n"
|
||||
"-M n, --features-file n Use only features in file n\n"
|
||||
"-M n, --features-file n Compile features set in file n\n"
|
||||
"--kernel-features n Kernel features set in file n\n"
|
||||
"-n n, --namespace n Set Namespace for the profile\n"
|
||||
"-X, --readimpliesX Map profile read permissions to mr\n"
|
||||
"-k, --show-cache Report cache hit/miss details\n"
|
||||
@@ -188,7 +205,8 @@ static void display_usage(const char *command)
|
||||
" --skip-bad-cache Don't clear cache if out of sync\n"
|
||||
" --purge-cache Clear cache regardless of its state\n"
|
||||
" --debug-cache Debug cache file checks\n"
|
||||
"-L, --cache-loc n Set the location of the profile cache\n"
|
||||
" --print-cache_dir Print the cache directory path\n"
|
||||
"-L, --cache-loc n Set the location of the profile caches\n"
|
||||
"-q, --quiet Don't emit warnings\n"
|
||||
"-v, --verbose Show profile names as they load\n"
|
||||
"-Q, --skip-kernel-load Do everything except loading into kernel\n"
|
||||
@@ -202,6 +220,8 @@ static void display_usage(const char *command)
|
||||
"--max-jobs n Hard cap on --jobs. Default 8*cpus\n"
|
||||
"--abort-on-error Abort processing of profiles on first error\n"
|
||||
"--skip-bad-cache-rebuild Do not try rebuilding the cache if it is rejected by the kernel\n"
|
||||
"--config-file n Specify the parser config file location, processed early before other options.\n"
|
||||
"--print-config Print config file location\n"
|
||||
"--warn n Enable warnings (see --help=warn)\n"
|
||||
,command);
|
||||
}
|
||||
@@ -222,6 +242,55 @@ void display_warn(const char *command)
|
||||
print_flag_table(warnflag_table);
|
||||
}
|
||||
|
||||
/* Parse comma separated cachelocations. Commas can be escaped by \, */
|
||||
static int parse_cacheloc(const char *arg, const char **cacheloc, int max_size)
|
||||
{
|
||||
const char *s = arg;
|
||||
const char *p = arg;
|
||||
int n = 0;
|
||||
|
||||
while(*p) {
|
||||
if (*p == '\\') {
|
||||
if (*(p + 1) != 0)
|
||||
p++;
|
||||
} else if (*p == ',') {
|
||||
if (p != s) {
|
||||
char *tmp;
|
||||
if (n == max_size) {
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
tmp = (char *) malloc(p - s + 1);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
memcpy(tmp, s, p - s);
|
||||
tmp[p - s] = 0;
|
||||
cacheloc[n] = tmp;
|
||||
n++;
|
||||
}
|
||||
p++;
|
||||
s = p;
|
||||
} else
|
||||
p++;
|
||||
}
|
||||
if (p != s) {
|
||||
char *tmp;
|
||||
if (n == max_size) {
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
tmp = (char *) malloc(p - s + 1);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
memcpy(tmp, s, p - s);
|
||||
tmp[p - s] = 0;
|
||||
cacheloc[n] = tmp;
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Treat conf file like options passed on command line
|
||||
*/
|
||||
static int getopt_long_file(FILE *f, const struct option *longopts,
|
||||
@@ -319,6 +388,16 @@ static long process_jobs_arg(const char *arg, const char *val) {
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
bool early_arg(int c) {
|
||||
switch(c) {
|
||||
case EARLY_ARG_CONFIG_FILE:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* process a single argment from getopt_long
|
||||
* Returns: 1 if an action arg, else 0
|
||||
*/
|
||||
@@ -329,8 +408,7 @@ static int process_arg(int c, char *optarg)
|
||||
switch (c) {
|
||||
case 0:
|
||||
PERROR("Assert, in getopt_long handling\n");
|
||||
display_usage(progname);
|
||||
exit(0);
|
||||
exit(1);
|
||||
break;
|
||||
case 'a':
|
||||
count++;
|
||||
@@ -449,7 +527,7 @@ static int process_arg(int c, char *optarg)
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (aa_features_new_from_string(&features,
|
||||
if (aa_features_new_from_string(&compile_features,
|
||||
optarg, strlen(optarg))) {
|
||||
fprintf(stderr,
|
||||
"Failed to parse features string: %m\n");
|
||||
@@ -457,13 +535,21 @@ static int process_arg(int c, char *optarg)
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
if (aa_features_new(&features, AT_FDCWD, optarg)) {
|
||||
if (aa_features_new(&compile_features, AT_FDCWD, optarg)) {
|
||||
fprintf(stderr,
|
||||
"Failed to load features from '%s': %m\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 138:
|
||||
if (aa_features_new(&kernel_features, AT_FDCWD, optarg)) {
|
||||
fprintf(stderr,
|
||||
"Failed to load kernel features from '%s': %m\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
conf_verbose = 0;
|
||||
conf_quiet = 1;
|
||||
@@ -507,7 +593,11 @@ static int process_arg(int c, char *optarg)
|
||||
skip_bad_cache_rebuild = 1;
|
||||
break;
|
||||
case 'L':
|
||||
cacheloc = strdup(optarg);
|
||||
cacheloc_n = parse_cacheloc(optarg, cacheloc, MAX_CACHE_LOCS);
|
||||
if (cacheloc_n == -1) {
|
||||
PERROR("%s: Invalid --cacheloc option '%s' %m\n", progname, optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
kernel_load = 0;
|
||||
@@ -536,8 +626,22 @@ static int process_arg(int c, char *optarg)
|
||||
case 136:
|
||||
jobs_max = process_jobs_arg("max-jobs", optarg);
|
||||
break;
|
||||
case 137:
|
||||
kernel_load = 0;
|
||||
print_cache_dir = true;
|
||||
break;
|
||||
case EARLY_ARG_CONFIG_FILE:
|
||||
config_file = strdup(optarg);
|
||||
if (!config_file) {
|
||||
PERROR("%s: %m", progname);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 140:
|
||||
printf("%s\n", config_file);
|
||||
break;
|
||||
default:
|
||||
display_usage(progname);
|
||||
/* 'unrecognized option' error message gets printed by getopt_long() */
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
@@ -545,21 +649,36 @@ static int process_arg(int c, char *optarg)
|
||||
return count;
|
||||
}
|
||||
|
||||
static void process_early_args(int argc, char *argv[])
|
||||
{
|
||||
int c, o;
|
||||
|
||||
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1)
|
||||
{
|
||||
if (early_arg(c))
|
||||
process_arg(c, optarg);
|
||||
}
|
||||
|
||||
/* reset args, so we are ready for a second pass */
|
||||
optind = 1;
|
||||
}
|
||||
|
||||
static int process_args(int argc, char *argv[])
|
||||
{
|
||||
int c, o;
|
||||
int count = 0;
|
||||
option = OPTION_ADD;
|
||||
|
||||
opterr = 1;
|
||||
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1)
|
||||
{
|
||||
count += process_arg(c, optarg);
|
||||
if (!early_arg(c))
|
||||
count += process_arg(c, optarg);
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
PERROR("%s: Too many actions given on the command line.\n",
|
||||
progname);
|
||||
display_usage(progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -574,8 +693,10 @@ static int process_config_file(const char *name)
|
||||
int c, o;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f)
|
||||
if (!f) {
|
||||
pwarn("config file '%s' not found\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1)
|
||||
process_arg(c, optarg);
|
||||
@@ -592,7 +713,6 @@ int have_enough_privilege(void)
|
||||
if (uid != 0 && euid != 0) {
|
||||
PERROR(_("%s: Sorry. You need root privileges to run this program.\n\n"),
|
||||
progname);
|
||||
display_usage(progname);
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
@@ -623,33 +743,37 @@ no_match:
|
||||
perms_create = 1;
|
||||
}
|
||||
|
||||
static void set_supported_features(void)
|
||||
static void set_supported_features(aa_features *kernel_features unused)
|
||||
{
|
||||
/* has process_args() already assigned a match string? */
|
||||
if (!features && aa_features_new_from_kernel(&features) == -1) {
|
||||
if (!compile_features && aa_features_new_from_kernel(&compile_features) == -1) {
|
||||
set_features_by_match_file();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: intersect with actual kernel features to get proper
|
||||
* rule down grades for a give kernel
|
||||
*/
|
||||
perms_create = 1;
|
||||
kernel_supports_policydb = aa_features_supports(features, "file");
|
||||
kernel_supports_network = aa_features_supports(features, "network");
|
||||
kernel_supports_unix = aa_features_supports(features,
|
||||
kernel_supports_policydb = aa_features_supports(compile_features, "file");
|
||||
kernel_supports_network = aa_features_supports(compile_features, "network");
|
||||
kernel_supports_unix = aa_features_supports(compile_features,
|
||||
"network/af_unix");
|
||||
kernel_supports_mount = aa_features_supports(features, "mount");
|
||||
kernel_supports_dbus = aa_features_supports(features, "dbus");
|
||||
kernel_supports_signal = aa_features_supports(features, "signal");
|
||||
kernel_supports_ptrace = aa_features_supports(features, "ptrace");
|
||||
kernel_supports_setload = aa_features_supports(features,
|
||||
kernel_supports_mount = aa_features_supports(compile_features, "mount");
|
||||
kernel_supports_dbus = aa_features_supports(compile_features, "dbus");
|
||||
kernel_supports_signal = aa_features_supports(compile_features, "signal");
|
||||
kernel_supports_ptrace = aa_features_supports(compile_features, "ptrace");
|
||||
kernel_supports_setload = aa_features_supports(compile_features,
|
||||
"policy/set_load");
|
||||
kernel_supports_diff_encode = aa_features_supports(features,
|
||||
kernel_supports_diff_encode = aa_features_supports(compile_features,
|
||||
"policy/diff_encode");
|
||||
kernel_supports_stacking = aa_features_supports(features,
|
||||
kernel_supports_stacking = aa_features_supports(compile_features,
|
||||
"domain/stack");
|
||||
|
||||
if (aa_features_supports(features, "policy/versions/v7"))
|
||||
if (aa_features_supports(compile_features, "policy/versions/v7"))
|
||||
kernel_abi_version = 7;
|
||||
else if (aa_features_supports(features, "policy/versions/v6"))
|
||||
else if (aa_features_supports(compile_features, "policy/versions/v6"))
|
||||
kernel_abi_version = 6;
|
||||
|
||||
if (!kernel_supports_diff_encode)
|
||||
@@ -657,6 +781,33 @@ static void set_supported_features(void)
|
||||
dfaflags &= ~DFA_CONTROL_DIFF_ENCODE;
|
||||
}
|
||||
|
||||
static bool do_print_cache_dir(aa_features *features, int dirfd, const char *path)
|
||||
{
|
||||
autofree char *cache_dir = NULL;
|
||||
|
||||
cache_dir = aa_policy_cache_dir_path_preview(features, dirfd, path);
|
||||
if (!cache_dir) {
|
||||
PERROR(_("Unable to print the cache directory: %m\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%s\n", cache_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_print_cache_dirs(aa_features *features, const char **cacheloc,
|
||||
int cacheloc_n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cacheloc_n; i++) {
|
||||
if (!do_print_cache_dir(features, AT_FDCWD, cacheloc[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int process_binary(int option, aa_kernel_interface *kernel_interface,
|
||||
const char *profilename)
|
||||
{
|
||||
@@ -741,10 +892,11 @@ int test_for_dir_mode(const char *basename, const char *linkdir)
|
||||
}
|
||||
|
||||
int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
const char *profilename, const char *cachedir)
|
||||
const char *profilename, aa_policy_cache *pc)
|
||||
{
|
||||
int retval = 0;
|
||||
autofree const char *cachename = NULL;
|
||||
autofree const char *writecachename = NULL;
|
||||
autofree const char *cachetmpname = NULL;
|
||||
autoclose int cachetmp = -1;
|
||||
const char *basename = NULL;
|
||||
@@ -759,7 +911,9 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
return errno;
|
||||
}
|
||||
} else {
|
||||
pwarn("%s: cannot use or update cache, disable, or force-complain via stdin\n", progname);
|
||||
if (write_cache)
|
||||
pwarn("%s: cannot use or update cache, disable, or force-complain via stdin\n", progname);
|
||||
skip_cache = write_cache = 0;
|
||||
}
|
||||
|
||||
reset_parser(profilename);
|
||||
@@ -784,9 +938,17 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
}
|
||||
|
||||
/* setup cachename and tstamp */
|
||||
if (!force_complain && !skip_cache) {
|
||||
cachename = cache_filename(cachedir, basename);
|
||||
valid_read_cache(cachename);
|
||||
if (!force_complain && pc) {
|
||||
cachename = aa_policy_cache_filename(pc, basename);
|
||||
if (!cachename) {
|
||||
autoclose int fd = aa_policy_cache_open(pc,
|
||||
basename,
|
||||
O_RDONLY);
|
||||
if (fd != -1)
|
||||
pwarn(_("Could not get cachename for '%s'\n"), basename);
|
||||
} else {
|
||||
valid_read_cache(cachename);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -818,8 +980,6 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
if (!retval || skip_bad_cache_rebuild)
|
||||
return retval;
|
||||
}
|
||||
|
||||
cachetmp = setup_cache_tmp(&cachetmpname, cachename);
|
||||
}
|
||||
|
||||
if (show_cache)
|
||||
@@ -855,15 +1015,27 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pc && write_cache && !force_complain) {
|
||||
writecachename = cache_filename(pc, 0, basename);
|
||||
if (!writecachename) {
|
||||
pwarn("Cache write disabled: Cannot create cache file name '%s': %m\n", basename);
|
||||
write_cache = 0;
|
||||
}
|
||||
cachetmp = setup_cache_tmp(&cachetmpname, writecachename);
|
||||
if (cachetmp == -1) {
|
||||
pwarn("Cache write disabled: Cannot create setup tmp cache file '%s': %m\n", writecachename);
|
||||
write_cache = 0;
|
||||
}
|
||||
}
|
||||
/* cache file generated by load_policy */
|
||||
retval = load_policy(option, kernel_interface, cachetmp);
|
||||
if (retval == 0 && write_cache) {
|
||||
if (cachetmp == -1) {
|
||||
unlink(cachetmpname);
|
||||
PERROR("Warning failed to create cache: %s\n",
|
||||
pwarn("Warning failed to create cache: %s\n",
|
||||
basename);
|
||||
} else {
|
||||
install_cache(cachetmpname, cachename);
|
||||
install_cache(cachetmpname, writecachename);
|
||||
}
|
||||
}
|
||||
out:
|
||||
@@ -1005,7 +1177,7 @@ static void setup_parallel_compile(void)
|
||||
struct dir_cb_data {
|
||||
aa_kernel_interface *kernel_interface;
|
||||
const char *dirname; /* name of the parent dir */
|
||||
const char *cachedir; /* path to the cache sub directory */
|
||||
aa_policy_cache *policy_cache; /* policy_cache to use */
|
||||
};
|
||||
|
||||
/* data - pointer to a dir_cb_data */
|
||||
@@ -1020,7 +1192,7 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
||||
PERROR(_("Out of memory"));
|
||||
work_spawn(process_profile(option, cb_data->kernel_interface,
|
||||
path, cb_data->cachedir),
|
||||
path, cb_data->policy_cache),
|
||||
handle_work_result);
|
||||
}
|
||||
return rc;
|
||||
@@ -1046,17 +1218,17 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
|
||||
static void setup_flags(void)
|
||||
{
|
||||
/* Get the match string to determine type of regex support needed */
|
||||
set_supported_features();
|
||||
|
||||
/* Gracefully handle AppArmor kernel without compatibility patch */
|
||||
if (!features) {
|
||||
if (!kernel_features && aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
PERROR("Cache read/write disabled: interface file missing. "
|
||||
"(Kernel needs AppArmor 2.4 compatibility patch.)\n");
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the match string to determine type of regex support needed */
|
||||
set_supported_features(kernel_features);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -1072,7 +1244,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
init_base_dir();
|
||||
|
||||
process_config_file("/etc/apparmor/parser.conf");
|
||||
process_early_args(argc, argv);
|
||||
process_config_file(config_file);
|
||||
optind = process_args(argc, argv);
|
||||
|
||||
setup_parallel_compile();
|
||||
@@ -1092,7 +1265,7 @@ int main(int argc, char *argv[])
|
||||
setup_flags();
|
||||
|
||||
if (!(UNPRIVILEGED_OPS) &&
|
||||
aa_kernel_interface_new(&kernel_interface, features, apparmorfs) == -1) {
|
||||
aa_kernel_interface_new(&kernel_interface, kernel_features, apparmorfs) == -1) {
|
||||
PERROR(_("Warning: unable to find a suitable fs in %s, is it "
|
||||
"mounted?\nUse --subdomainfs to override.\n"),
|
||||
MOUNTED_FS);
|
||||
@@ -1100,18 +1273,22 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if ((!skip_cache && (write_cache || !skip_read_cache)) ||
|
||||
force_clear_cache) {
|
||||
uint16_t max_caches = write_cache && cond_clear_cache ? 1 : 0;
|
||||
print_cache_dir || force_clear_cache) {
|
||||
uint16_t max_caches = write_cache && cond_clear_cache ? (uint16_t) (-1) : 0;
|
||||
|
||||
if (!cacheloc && asprintf(&cacheloc, "%s/cache", basedir) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
return 1;
|
||||
if (!cacheloc[0]) {
|
||||
cacheloc[0] = "/var/cache/apparmor";
|
||||
cacheloc_n = 1;
|
||||
}
|
||||
if (print_cache_dir)
|
||||
return do_print_cache_dirs(kernel_features, cacheloc,
|
||||
cacheloc_n) ? 0 : 1;
|
||||
|
||||
if (force_clear_cache) {
|
||||
if (aa_policy_cache_remove(AT_FDCWD, cacheloc)) {
|
||||
/* only ever write to the first cacheloc location */
|
||||
if (aa_policy_cache_remove(AT_FDCWD, cacheloc[0])) {
|
||||
PERROR(_("Failed to clear cache files (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
cacheloc[0], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1120,26 +1297,34 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (create_cache_dir)
|
||||
pwarn(_("The --create-cache-dir option is deprecated. Please use --write-cache.\n"));
|
||||
|
||||
retval = aa_policy_cache_new(&policy_cache, features,
|
||||
AT_FDCWD, cacheloc, max_caches);
|
||||
retval = aa_policy_cache_new(&policy_cache, kernel_features,
|
||||
AT_FDCWD, cacheloc[0], max_caches);
|
||||
if (retval) {
|
||||
if (errno != ENOENT && errno != EEXIST) {
|
||||
if (errno != ENOENT && errno != EEXIST && errno != EROFS) {
|
||||
PERROR(_("Failed setting up policy cache (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
cacheloc[0], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (show_cache) {
|
||||
if (max_caches > 0)
|
||||
PERROR("Cache write disabled: Cannot create cache '%s': %m\n",
|
||||
cacheloc);
|
||||
cacheloc[0]);
|
||||
else
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid\n");
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid: %m\n");
|
||||
}
|
||||
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
} else {
|
||||
if (show_cache)
|
||||
PERROR("Cache: added primary location '%s'\n", cacheloc[0]);
|
||||
for (i = 1; i < cacheloc_n; i++) {
|
||||
if (aa_policy_cache_add_ro_dir(policy_cache, AT_FDCWD,
|
||||
cacheloc[i])) {
|
||||
pwarn("Cache: failed to add read only location '%s', does not contain valid cache directory for the specified feature set\n", cacheloc[i]);
|
||||
} else if (show_cache)
|
||||
pwarn("Cache: added readonly location '%s'\n", cacheloc[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1170,7 +1355,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
memset(&cb_data, 0, sizeof(struct dir_cb_data));
|
||||
cb_data.dirname = profilename;
|
||||
cb_data.cachedir = cacheloc;
|
||||
cb_data.policy_cache = policy_cache;
|
||||
cb_data.kernel_interface = kernel_interface;
|
||||
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||
@@ -1184,7 +1369,7 @@ int main(int argc, char *argv[])
|
||||
handle_work_result);
|
||||
} else {
|
||||
work_spawn(process_profile(option, kernel_interface,
|
||||
profilename, cacheloc),
|
||||
profilename, policy_cache),
|
||||
handle_work_result);
|
||||
}
|
||||
|
||||
|
@@ -111,6 +111,7 @@ static struct keyword_table keyword_table[] = {
|
||||
{"trace", TOK_TRACE},
|
||||
{"tracedby", TOK_TRACEDBY},
|
||||
{"readby", TOK_READBY},
|
||||
{"abi", TOK_ABI},
|
||||
|
||||
/* terminate */
|
||||
{NULL, 0}
|
||||
|
@@ -25,6 +25,9 @@
|
||||
#include "immunix.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef int (*comparison_fn_t)(const void *, const void *);
|
||||
typedef void (*__free_fn_t)(void *);
|
||||
|
||||
enum var_type {
|
||||
sd_boolean,
|
||||
sd_set,
|
||||
|
@@ -152,6 +152,7 @@ void add_local_entry(Profile *prof);
|
||||
%token TOK_TRACE
|
||||
%token TOK_TRACEDBY
|
||||
%token TOK_READBY
|
||||
%token TOK_ABI
|
||||
|
||||
/* rlimits */
|
||||
%token TOK_RLIMIT
|
||||
@@ -400,6 +401,7 @@ hat: hat_start profile_base
|
||||
preamble: { /* nothing */ }
|
||||
| preamble alias { /* nothing */ };
|
||||
| preamble varassign { /* nothing */ };
|
||||
| preamble abi_rule { /* nothing */ };
|
||||
|
||||
alias: TOK_ALIAS TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
|
||||
{
|
||||
@@ -615,6 +617,8 @@ rules: { /* nothing */
|
||||
$$ = prof;
|
||||
};
|
||||
|
||||
rules: rules abi_rule { /* nothing */ }
|
||||
|
||||
rules: rules opt_prefix rule
|
||||
{
|
||||
PDEBUG("matched: rules rule\n");
|
||||
@@ -1065,6 +1069,12 @@ opt_named_transition: { /* nothing */ $$ = NULL; }
|
||||
rule: file_rule { $$ = $1; }
|
||||
| link_rule { $$ = $1; }
|
||||
|
||||
abi_rule: TOK_ABI TOK_ID TOK_END_OF_RULE
|
||||
{
|
||||
pwarn(_("%s: Profile abi not supported, falling back to system abi.\n"), progname);
|
||||
free($2);
|
||||
};
|
||||
|
||||
opt_exec_mode: { /* nothing */ $$ = EXEC_MODE_EMPTY; }
|
||||
| TOK_UNSAFE { $$ = EXEC_MODE_UNSAFE; };
|
||||
| TOK_SAFE { $$ = EXEC_MODE_SAFE; };
|
||||
|
217
parser/po/de.po
217
parser/po/de.po
@@ -6,24 +6,24 @@ msgstr ""
|
||||
"Project-Id-Version: apparmor-parser\n"
|
||||
"Report-Msgid-Bugs-To: <apparmor@lists.ubuntu.com>\n"
|
||||
"POT-Creation-Date: 2014-09-13 00:11-0700\n"
|
||||
"PO-Revision-Date: 2015-09-05 20:55+0000\n"
|
||||
"PO-Revision-Date: 2018-04-06 14:39+0000\n"
|
||||
"Last-Translator: Tobias Bannert <tobannert@gmail.com>\n"
|
||||
"Language-Team: Novell Language <language@novell.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
|
||||
"X-Generator: Launchpad (build 18053)\n"
|
||||
"X-Launchpad-Export-Date: 2018-04-07 05:20+0000\n"
|
||||
"X-Generator: Launchpad (build 18599)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#: ../parser_include.c:113
|
||||
#: ../parser_include.c:113 ../parser_include.c:111
|
||||
msgid "Error: Out of memory.\n"
|
||||
msgstr "Fehler: Kein Speicher vorhanden.\n"
|
||||
msgstr "Fehler: nicht genügend Speicher!\n"
|
||||
|
||||
#: ../parser_include.c:123
|
||||
#: ../parser_include.c:123 ../parser_include.c:121
|
||||
#, c-format
|
||||
msgid "Error: basedir %s is not a directory, skipping.\n"
|
||||
msgstr "Fehler: basedir »%s« ist kein Verzeichnis - es wird übersprungen.\n"
|
||||
msgstr "Fehler: basedir »%s« ist kein Verzeichnis, es wird übersprungen.\n"
|
||||
|
||||
#: ../parser_include.c:137
|
||||
#, c-format
|
||||
@@ -31,99 +31,108 @@ msgid "Error: Could not add directory %s to search path.\n"
|
||||
msgstr ""
|
||||
"Fehler: Verzeichnis »%s« konnte nicht zu Suchpfad hinzugefügt werden.\n"
|
||||
|
||||
#: ../parser_include.c:147
|
||||
#: ../parser_include.c:147 ../parser_include.c:151
|
||||
msgid "Error: Could not allocate memory.\n"
|
||||
msgstr "Fehler: Es konnte kein Speicher zugeordnet werden.\n"
|
||||
|
||||
#: ../parser_interface.c:69 ../parser_interface.c:72
|
||||
#: ../parser_interface.c:69 ../parser_interface.c:72 ../parser_interface.c:49
|
||||
msgid "Bad write position\n"
|
||||
msgstr "Ungültige Schreibposition\n"
|
||||
|
||||
#: ../parser_interface.c:72 ../parser_interface.c:75
|
||||
#: ../parser_interface.c:72 ../parser_interface.c:75 ../parser_interface.c:52
|
||||
msgid "Permission denied\n"
|
||||
msgstr "Zugriff verweigert\n"
|
||||
|
||||
#: ../parser_interface.c:75 ../parser_interface.c:78
|
||||
#: ../parser_interface.c:75 ../parser_interface.c:78 ../parser_interface.c:55
|
||||
msgid "Out of memory\n"
|
||||
msgstr "Kein Speicher vorhanden\n"
|
||||
msgstr "Nicht genügend Speicher!\n"
|
||||
|
||||
#: ../parser_interface.c:78 ../parser_interface.c:81
|
||||
#: ../parser_interface.c:78 ../parser_interface.c:81 ../parser_interface.c:58
|
||||
msgid "Couldn't copy profile: Bad memory address\n"
|
||||
msgstr "Profil konnte nicht kopiert werden: Keine Speicheradresse\n"
|
||||
msgstr "Profil konnte nicht kopiert werden: falsche Speicheradresse\n"
|
||||
|
||||
#: ../parser_interface.c:81 ../parser_interface.c:84
|
||||
#: ../parser_interface.c:81 ../parser_interface.c:84 ../parser_interface.c:61
|
||||
msgid "Profile doesn't conform to protocol\n"
|
||||
msgstr "Das Profil entspricht nicht dem Protokoll\n"
|
||||
|
||||
#: ../parser_interface.c:84 ../parser_interface.c:87
|
||||
#: ../parser_interface.c:84 ../parser_interface.c:87 ../parser_interface.c:64
|
||||
msgid "Profile does not match signature\n"
|
||||
msgstr "Das Profil stimmt nicht mit der Signatur überein\n"
|
||||
|
||||
#: ../parser_interface.c:87 ../parser_interface.c:90
|
||||
#: ../parser_interface.c:87 ../parser_interface.c:90 ../parser_interface.c:67
|
||||
msgid "Profile version not supported by Apparmor module\n"
|
||||
msgstr "Profilversion wird vom Apparmor-Modul nicht unterstützt\n"
|
||||
|
||||
#: ../parser_interface.c:90 ../parser_interface.c:93
|
||||
#: ../parser_interface.c:90 ../parser_interface.c:93 ../parser_interface.c:70
|
||||
msgid "Profile already exists\n"
|
||||
msgstr "Profil ist bereits vorhanden\n"
|
||||
|
||||
#: ../parser_interface.c:93 ../parser_interface.c:96
|
||||
#: ../parser_interface.c:93 ../parser_interface.c:96 ../parser_interface.c:73
|
||||
msgid "Profile doesn't exist\n"
|
||||
msgstr "Profil ist nicht vorhanden\n"
|
||||
|
||||
#: ../parser_interface.c:96 ../parser_interface.c:99
|
||||
#: ../parser_interface.c:96 ../parser_interface.c:99 ../parser_interface.c:76
|
||||
msgid "Permission denied; attempted to load a profile while confined?\n"
|
||||
msgstr ""
|
||||
"Zugriff verweigert! Haben Sie versucht ein Profil zu laden, während Sie "
|
||||
"eingeschränkt waren?\n"
|
||||
|
||||
#: ../parser_interface.c:99 ../parser_interface.c:102
|
||||
#: ../parser_interface.c:99 ../parser_interface.c:102 ../parser_interface.c:79
|
||||
#, c-format
|
||||
msgid "Unknown error (%d): %s\n"
|
||||
msgstr "Unbekannter Fehler (%d): %s\n"
|
||||
|
||||
#: ../parser_interface.c:116 ../parser_interface.c:119
|
||||
#: ../parser_interface.c:96
|
||||
#, c-format
|
||||
msgid "%s: Unable to add \"%s\". "
|
||||
msgstr "%s: Hinzufügen von »%s« nicht möglich. "
|
||||
|
||||
#: ../parser_interface.c:121 ../parser_interface.c:124
|
||||
#: ../parser_interface.c:101
|
||||
#, c-format
|
||||
msgid "%s: Unable to replace \"%s\". "
|
||||
msgstr "%s: »%s« kann nicht ersetzt werden. "
|
||||
|
||||
#: ../parser_interface.c:126 ../parser_interface.c:129
|
||||
#: ../parser_interface.c:106
|
||||
#, c-format
|
||||
msgid "%s: Unable to remove \"%s\". "
|
||||
msgstr "%s: »%s« kann nicht entfernt werden. "
|
||||
|
||||
#: ../parser_interface.c:131 ../parser_interface.c:134
|
||||
#: ../parser_interface.c:111
|
||||
#, c-format
|
||||
msgid "%s: Unable to write to stdout\n"
|
||||
msgstr "%s: Schreiben in Standardausgabe nicht möglich\n"
|
||||
|
||||
#: ../parser_interface.c:135 ../parser_interface.c:138
|
||||
#: ../parser_interface.c:115
|
||||
#, c-format
|
||||
msgid "%s: Unable to write to output file\n"
|
||||
msgstr "%s: Schreiben in Ausgabedatei nicht möglich\n"
|
||||
|
||||
#: ../parser_interface.c:138 ../parser_interface.c:162
|
||||
#: ../parser_interface.c:141 ../parser_interface.c:165
|
||||
#: ../parser_interface.c:118 ../parser_interface.c:142
|
||||
#, c-format
|
||||
msgid "%s: ASSERT: Invalid option: %d\n"
|
||||
msgstr "%s: ASSERT: Ungültige Option: %d\n"
|
||||
|
||||
#: ../parser_interface.c:147 ../parser_interface.c:150
|
||||
#: ../parser_interface.c:127
|
||||
#, c-format
|
||||
msgid "Addition succeeded for \"%s\".\n"
|
||||
msgstr "Hinzufügen für »%s« erfolgreich.\n"
|
||||
|
||||
#: ../parser_interface.c:151 ../parser_interface.c:154
|
||||
#: ../parser_interface.c:131
|
||||
#, c-format
|
||||
msgid "Replacement succeeded for \"%s\".\n"
|
||||
msgstr "Ersetzungsvorgang für »%s« erfolgreich.\n"
|
||||
|
||||
#: ../parser_interface.c:155 ../parser_interface.c:158
|
||||
#: ../parser_interface.c:135
|
||||
#, c-format
|
||||
msgid "Removal succeeded for \"%s\".\n"
|
||||
msgstr "Entfernen für »%s« erfolgreich.\n"
|
||||
@@ -136,6 +145,7 @@ msgstr ""
|
||||
"Auflösung %p\n"
|
||||
|
||||
#: ../parser_interface.c:656 ../parser_interface.c:658
|
||||
#: ../parser_interface.c:446
|
||||
#, c-format
|
||||
msgid "profile %s network rules not enforced\n"
|
||||
msgstr "Netzwerkregeln für Profil %s werden nicht erzwungen\n"
|
||||
@@ -146,16 +156,19 @@ msgstr "Unbekannter Mustertyp\n"
|
||||
|
||||
#: ../parser_interface.c:750 ../parser_interface.c:902
|
||||
#: ../parser_interface.c:743 ../parser_interface.c:894
|
||||
#: ../parser_interface.c:518 ../parser_interface.c:669
|
||||
#, c-format
|
||||
msgid "Unable to open %s - %s\n"
|
||||
msgstr "%s kann nicht geöffnet werden - %s\n"
|
||||
msgstr "%s kann nicht geöffnet werden – %s\n"
|
||||
|
||||
#: ../parser_interface.c:776 ../parser_interface.c:768
|
||||
#: ../parser_interface.c:543
|
||||
#, c-format
|
||||
msgid "Memory Allocation Error: Unable to remove ^%s\n"
|
||||
msgstr "Speicherzuordnungsfehler: ^%s kann nicht entfernt werden\n"
|
||||
|
||||
#: ../parser_interface.c:789 ../parser_interface.c:781
|
||||
#: ../parser_interface.c:556
|
||||
#, c-format
|
||||
msgid "Memory Allocation Error: Unable to remove %s:%s."
|
||||
msgstr "Speicherzuordnungsfehler: %s:%s kann nicht entfernt werden."
|
||||
@@ -171,22 +184,24 @@ msgstr "Serialisierung von Profil %s nicht möglich\n"
|
||||
|
||||
#: ../parser_interface.c:829 ../parser_interface.c:916
|
||||
#: ../parser_interface.c:821 ../parser_interface.c:908
|
||||
#: ../parser_interface.c:582
|
||||
#, c-format
|
||||
msgid "%s: Unable to write entire profile entry\n"
|
||||
msgstr "%s: Profileintrag kann nicht geschrieben werden\n"
|
||||
|
||||
#: ../parser_interface.c:839 ../parser_interface.c:831
|
||||
#: ../parser_interface.c:593
|
||||
#, c-format
|
||||
msgid "%s: Unable to write entire profile entry to cache\n"
|
||||
msgstr ""
|
||||
"%s: Schreiben des gesamten Profileintrags in den Puffer nicht möglich\n"
|
||||
|
||||
#: parser_lex.l:100 parser_lex.l:163
|
||||
#: parser_lex.l:100 parser_lex.l:163 parser_lex.l:169
|
||||
#, c-format
|
||||
msgid "Could not open '%s'"
|
||||
msgstr "»%s« konnte nicht geöffnet werden"
|
||||
|
||||
#: parser_lex.l:104 parser_lex.l:167
|
||||
#: parser_lex.l:104 parser_lex.l:167 parser_lex.l:173
|
||||
#, c-format
|
||||
msgid "fstat failed for '%s'"
|
||||
msgstr "fstat fehlgeschlagen für »%s«"
|
||||
@@ -201,18 +216,18 @@ msgstr "opendir fehlgeschlagen für »%s«"
|
||||
msgid "stat failed for '%s'"
|
||||
msgstr "stat fehlgeschlagen für »%s«"
|
||||
|
||||
#: parser_lex.l:155 parser_lex.l:133
|
||||
#: parser_lex.l:155 parser_lex.l:133 parser_lex.l:139
|
||||
#, c-format
|
||||
msgid "Could not open '%s' in '%s'"
|
||||
msgstr "»%s« konnte nicht in »%s« geöffnet werden"
|
||||
|
||||
#: parser_lex.l:284 parser_lex.l:322 parser_lex.l:362 parser_lex.l:399
|
||||
#: parser_lex.l:469 parser_lex.l:655 parser_lex.l:586
|
||||
#: parser_lex.l:469 parser_lex.l:655 parser_lex.l:586 parser_lex.l:638
|
||||
#, c-format
|
||||
msgid "Found unexpected character: '%s'"
|
||||
msgstr "Unerwartetes Zeichen gefunden: »%s«"
|
||||
|
||||
#: parser_lex.l:386 parser_lex.l:418
|
||||
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428
|
||||
msgid "Variable declarations do not accept trailing commas"
|
||||
msgstr "Variablendeklarationen dürfen nicht mit Kommata enden"
|
||||
|
||||
@@ -221,7 +236,7 @@ msgstr "Variablendeklarationen dürfen nicht mit Kommata enden"
|
||||
msgid "(network_mode) Found unexpected character: '%s'"
|
||||
msgstr "(network_mode) Unerwartetes Zeichen gefunden: »%s«"
|
||||
|
||||
#: ../parser_main.c:333 ../parser_common.c:61
|
||||
#: ../parser_main.c:333 ../parser_common.c:61 ../parser_common.c:106
|
||||
#, c-format
|
||||
msgid "Warning from %s (%s%sline %d): %s"
|
||||
msgstr "Warnung aus %s (%s%sZeile %d): %s"
|
||||
@@ -233,7 +248,7 @@ msgstr ""
|
||||
"%s: Dem Einhängepunkt der Unterdomänenbasis konnte kein Speicher zugeordnet "
|
||||
"werden\n"
|
||||
|
||||
#: ../parser_main.c:577 ../parser_main.c:616
|
||||
#: ../parser_main.c:577 ../parser_main.c:616 ../parser_main.c:479
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: unable to find a suitable fs in %s, is it mounted?\n"
|
||||
@@ -243,7 +258,7 @@ msgstr ""
|
||||
"es eingehängt?\n"
|
||||
"Verwenden Sie --subdomainfs, um es außer Kraft zu setzen.\n"
|
||||
|
||||
#: ../parser_main.c:597 ../parser_main.c:635
|
||||
#: ../parser_main.c:597 ../parser_main.c:635 ../parser_main.c:498
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Sorry. You need root privileges to run this program.\n"
|
||||
@@ -252,7 +267,7 @@ msgstr ""
|
||||
"»%s«: Sie benötigen Systemverwalterrechte zum Ausführen dieses Programms.\n"
|
||||
"\n"
|
||||
|
||||
#: ../parser_main.c:604 ../parser_main.c:642
|
||||
#: ../parser_main.c:604 ../parser_main.c:642 ../parser_main.c:505
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Warning! You've set this program setuid root.\n"
|
||||
@@ -265,7 +280,7 @@ msgstr ""
|
||||
"\n"
|
||||
|
||||
#: ../parser_main.c:704 ../parser_main.c:813 ../parser_main.c:836
|
||||
#: ../parser_main.c:946
|
||||
#: ../parser_main.c:946 ../parser_main.c:860
|
||||
#, c-format
|
||||
msgid "Error: Could not read profile %s: %s.\n"
|
||||
msgstr "Fehler: Profil »%s« konnte nicht gelesen werden: »%s«.\n"
|
||||
@@ -281,26 +296,33 @@ msgstr "Fehler: Profil »%s« konnte nicht gelesen werden: »%s«.\n"
|
||||
#: parser_yacc.y:1042 parser_yacc.y:1078 parser_yacc.y:1082 parser_yacc.y:1092
|
||||
#: parser_yacc.y:1102 parser_yacc.y:1201 parser_yacc.y:1223 parser_yacc.y:1234
|
||||
#: parser_yacc.y:1309 parser_yacc.y:1327 parser_yacc.y:1334 parser_yacc.y:1385
|
||||
#: ../parser_main.c:735 ../parser_main.c:923 ../parser_main.c:1133
|
||||
#: ../parser_main.c:1187 parser_yacc.y:311 parser_yacc.y:462 parser_yacc.y:472
|
||||
#: parser_yacc.y:583 parser_yacc.y:662 parser_yacc.y:669 parser_yacc.y:1130
|
||||
#: parser_yacc.y:1166 parser_yacc.y:1170 parser_yacc.y:1180 parser_yacc.y:1190
|
||||
#: parser_yacc.y:1298 parser_yacc.y:1376 parser_yacc.y:1479 parser_yacc.y:1490
|
||||
#: parser_yacc.y:1565 parser_yacc.y:1583 parser_yacc.y:1590 parser_yacc.y:1639
|
||||
#: ../network.c:314 ../af_unix.cc:203
|
||||
msgid "Memory allocation error."
|
||||
msgstr "Speicherzuordnungsfehler."
|
||||
|
||||
#: ../parser_main.c:740 ../parser_main.c:872
|
||||
#: ../parser_main.c:740 ../parser_main.c:872 ../parser_main.c:757
|
||||
#, c-format
|
||||
msgid "Cached load succeeded for \"%s\".\n"
|
||||
msgstr "Zwischengespeichertes Laden für »%s« erfolgreich.\n"
|
||||
|
||||
#: ../parser_main.c:744 ../parser_main.c:876
|
||||
#: ../parser_main.c:744 ../parser_main.c:876 ../parser_main.c:761
|
||||
#, c-format
|
||||
msgid "Cached reload succeeded for \"%s\".\n"
|
||||
msgstr "Zwischengespeichertes Neuladen für »%s« erfolgreich.\n"
|
||||
|
||||
#: ../parser_main.c:910 ../parser_main.c:1058
|
||||
#: ../parser_main.c:910 ../parser_main.c:1058 ../parser_main.c:967
|
||||
#, c-format
|
||||
msgid "%s: Errors found in file. Aborting.\n"
|
||||
msgstr ""
|
||||
"%s: In der Datei wurde ein Fehler gefunden. Der Vorgang wird abgebrochen.\n"
|
||||
|
||||
#: ../parser_misc.c:426 ../parser_misc.c:597
|
||||
#: ../parser_misc.c:426 ../parser_misc.c:597 ../parser_misc.c:339
|
||||
msgid ""
|
||||
"Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
|
||||
"See the apparmor.d(5) manpage for details.\n"
|
||||
@@ -310,17 +332,17 @@ msgstr ""
|
||||
"Weitere Informationen auf der Handbuchseite apparmor.d(5).\n"
|
||||
|
||||
#: ../parser_misc.c:467 ../parser_misc.c:474 ../parser_misc.c:638
|
||||
#: ../parser_misc.c:645
|
||||
#: ../parser_misc.c:645 ../parser_misc.c:380 ../parser_misc.c:387
|
||||
msgid "Conflict 'a' and 'w' perms are mutually exclusive."
|
||||
msgstr "Die Parameter »a« und »w« schließen sich gegenseitig aus."
|
||||
|
||||
#: ../parser_misc.c:491 ../parser_misc.c:662
|
||||
#: ../parser_misc.c:491 ../parser_misc.c:662 ../parser_misc.c:404
|
||||
msgid "Exec qualifier 'i' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
"Ausführungskennzeichner »i« ist ungültig, ein Kennzeichner, mit dem ein "
|
||||
"Konflikt besteht, wurde bereits angegeben."
|
||||
|
||||
#: ../parser_misc.c:502 ../parser_misc.c:673
|
||||
#: ../parser_misc.c:502 ../parser_misc.c:673 ../parser_misc.c:415
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Unconfined exec qualifier (%c%c) allows some dangerous environment variables "
|
||||
@@ -331,7 +353,7 @@ msgstr ""
|
||||
"Einzelheiten mit »man 5 apparmor.d«.\n"
|
||||
|
||||
#: ../parser_misc.c:510 ../parser_misc.c:551 ../parser_misc.c:681
|
||||
#: ../parser_misc.c:722
|
||||
#: ../parser_misc.c:722 ../parser_misc.c:423 ../parser_misc.c:464
|
||||
#, c-format
|
||||
msgid "Exec qualifier '%c' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
@@ -339,7 +361,7 @@ msgstr ""
|
||||
"Konflikt besteht, wurde bereits angegeben."
|
||||
|
||||
#: ../parser_misc.c:537 ../parser_misc.c:545 ../parser_misc.c:708
|
||||
#: ../parser_misc.c:716
|
||||
#: ../parser_misc.c:716 ../parser_misc.c:450 ../parser_misc.c:458
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Exec qualifier '%c%c' invalid, conflicting qualifier already specified"
|
||||
@@ -347,12 +369,12 @@ msgstr ""
|
||||
"Ausführungskennzeichner »%c%c« ist ungültig, ein Kennzeichner, mit dem ein "
|
||||
"Konflikt besteht, wurde bereits angegeben."
|
||||
|
||||
#: ../parser_misc.c:593 ../parser_misc.c:764
|
||||
#: ../parser_misc.c:593 ../parser_misc.c:764 ../parser_misc.c:506
|
||||
#, c-format
|
||||
msgid "Internal: unexpected mode character '%c' in input"
|
||||
msgstr "Intern: Unerwartetes Moduszeichen »%c« in der Eingabe"
|
||||
|
||||
#: ../parser_misc.c:615 ../parser_misc.c:786
|
||||
#: ../parser_misc.c:615 ../parser_misc.c:786 ../parser_misc.c:528
|
||||
#, c-format
|
||||
msgid "Internal error generated invalid perm 0x%llx\n"
|
||||
msgstr "Interner Fehler erzeugte ungültige Zugriffsrechte 0x%llx\n"
|
||||
@@ -363,68 +385,69 @@ msgstr "Interner Fehler erzeugte ungültige Zugriffsrechte 0x%llx\n"
|
||||
msgid "AppArmor parser error: %s\n"
|
||||
msgstr "AppArmor-Analysefehler: %s\n"
|
||||
|
||||
#: ../parser_merge.c:92 ../parser_merge.c:91
|
||||
#: ../parser_merge.c:92 ../parser_merge.c:91 ../parser_merge.c:83
|
||||
msgid "Couldn't merge entries. Out of Memory\n"
|
||||
msgstr ""
|
||||
"Einträge konnten nicht zusammengeführt werden. Kein Speicher vorhanden\n"
|
||||
|
||||
#: ../parser_merge.c:111 ../parser_merge.c:113
|
||||
#: ../parser_merge.c:111 ../parser_merge.c:113 ../parser_merge.c:105
|
||||
#, c-format
|
||||
msgid "profile %s: has merged rule %s with conflicting x modifiers\n"
|
||||
msgstr ""
|
||||
"Profil %s: enthält zusammengeführte Regel %s mit in Konflikt stehenden x-"
|
||||
"Modifizierern\n"
|
||||
|
||||
#: parser_yacc.y:236 parser_yacc.y:277
|
||||
#: parser_yacc.y:236 parser_yacc.y:277 parser_yacc.y:320
|
||||
msgid "Profile attachment must begin with a '/'."
|
||||
msgstr "Profilanhang muss mit einem »/« beginnen."
|
||||
|
||||
#: parser_yacc.y:260 parser_yacc.y:302
|
||||
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348
|
||||
msgid ""
|
||||
"Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."
|
||||
msgstr ""
|
||||
"Profilnamen müssen mit einem »/«, Namensraum oder dem Schlüsselwort "
|
||||
"»profile« oder »hat« beginnen."
|
||||
|
||||
#: parser_yacc.y:296 parser_yacc.y:338
|
||||
#: parser_yacc.y:296 parser_yacc.y:338 parser_yacc.y:384
|
||||
#, c-format
|
||||
msgid "Failed to create alias %s -> %s\n"
|
||||
msgstr "Alias %s → %s konnte nicht erstellt werden\n"
|
||||
|
||||
#: parser_yacc.y:417 parser_yacc.y:460
|
||||
#: parser_yacc.y:417 parser_yacc.y:460 parser_yacc.y:506
|
||||
msgid "Profile flag chroot_relative conflicts with namespace_relative"
|
||||
msgstr ""
|
||||
"Profil-Marker chroot_relative steht in Konflikt mit namespace_relative"
|
||||
|
||||
#: parser_yacc.y:421 parser_yacc.y:464
|
||||
#: parser_yacc.y:421 parser_yacc.y:464 parser_yacc.y:510
|
||||
msgid "Profile flag mediate_deleted conflicts with delegate_deleted"
|
||||
msgstr "Profil-Marker mediate_deleted steht in Konflikt mit delegate_deleted"
|
||||
|
||||
#: parser_yacc.y:424 parser_yacc.y:467
|
||||
#: parser_yacc.y:424 parser_yacc.y:467 parser_yacc.y:513
|
||||
msgid ""
|
||||
"Profile flag attach_disconnected conflicts with no_attach_disconnected"
|
||||
msgstr ""
|
||||
"Profil-Marker attach_disconnected steht in Konflikt mit "
|
||||
"no_attach_disconnected"
|
||||
|
||||
#: parser_yacc.y:427 parser_yacc.y:470
|
||||
#: parser_yacc.y:427 parser_yacc.y:470 parser_yacc.y:516
|
||||
msgid "Profile flag chroot_attach conflicts with chroot_no_attach"
|
||||
msgstr "Profil-Marker chroot_attach steht in Konflikt mit chroot_no_attach"
|
||||
|
||||
#: parser_yacc.y:441 parser_yacc.y:484
|
||||
#: parser_yacc.y:441 parser_yacc.y:484 parser_yacc.y:530
|
||||
msgid "Profile flag 'debug' is no longer valid."
|
||||
msgstr "Profil-Marker »debug« ist nicht mehr gültig."
|
||||
|
||||
#: parser_yacc.y:463 parser_yacc.y:506
|
||||
#: parser_yacc.y:463 parser_yacc.y:506 parser_yacc.y:552
|
||||
#, c-format
|
||||
msgid "Invalid profile flag: %s."
|
||||
msgstr "Ungültiger Profil-Marker: %s."
|
||||
|
||||
#: parser_yacc.y:498 parser_yacc.y:520 parser_yacc.y:548
|
||||
#: parser_yacc.y:498 parser_yacc.y:520 parser_yacc.y:548 parser_yacc.y:594
|
||||
msgid "Assert: `rule' returned NULL."
|
||||
msgstr "Assert: Für »rule« wurde NULL zurückgegeben."
|
||||
|
||||
#: parser_yacc.y:501 parser_yacc.y:546 parser_yacc.y:552 parser_yacc.y:584
|
||||
#: parser_yacc.y:598 parser_yacc.y:630
|
||||
msgid ""
|
||||
"Invalid mode, in deny rules 'x' must not be preceded by exec qualifier 'i', "
|
||||
"'p', or 'u'"
|
||||
@@ -432,80 +455,81 @@ msgstr ""
|
||||
"Ungültiger Modus, in den Verweigernregeln darf vor »x« keiner der "
|
||||
"Ausführungskennzeichner »i«, »p« oder »u« stehen"
|
||||
|
||||
#: parser_yacc.y:524 parser_yacc.y:556
|
||||
#: parser_yacc.y:524 parser_yacc.y:556 parser_yacc.y:602
|
||||
msgid ""
|
||||
"Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', 'c', or 'u'"
|
||||
msgstr ""
|
||||
"Ungültiger Modus, in Verbotsregeln muss vor »x« einer der exec-Qualifier "
|
||||
"»i«, »p«, »c« oder »u« stehen"
|
||||
|
||||
#: parser_yacc.y:549 parser_yacc.y:587
|
||||
#: parser_yacc.y:549 parser_yacc.y:587 parser_yacc.y:633
|
||||
msgid "Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', or 'u'"
|
||||
msgstr ""
|
||||
"Ungültiger Modus, in Verbotsregeln muss vor »x« einer der exec-Qualifier "
|
||||
"»i«, »p« oder »u« stehen"
|
||||
|
||||
#: parser_yacc.y:574 parser_yacc.y:612 parser_yacc.y:614
|
||||
#: parser_yacc.y:574 parser_yacc.y:612 parser_yacc.y:614 parser_yacc.y:660
|
||||
msgid "Assert: `network_rule' return invalid protocol."
|
||||
msgstr "Assert: Für »network_rule« wurde NULL zurückgegeben."
|
||||
|
||||
#: parser_yacc.y:649 parser_yacc.y:696
|
||||
#: parser_yacc.y:649 parser_yacc.y:696 parser_yacc.y:786
|
||||
msgid "Assert: `change_profile' returned NULL."
|
||||
msgstr "Assert: Für »change_profile« wurde NULL zurückgegeben."
|
||||
|
||||
#: parser_yacc.y:680 parser_yacc.y:720
|
||||
#: parser_yacc.y:680 parser_yacc.y:720 parser_yacc.y:810
|
||||
msgid "Assert: 'hat rule' returned NULL."
|
||||
msgstr "Assert: Für »hat rule« wurde NULL zurückgegeben."
|
||||
|
||||
#: parser_yacc.y:689 parser_yacc.y:729
|
||||
#: parser_yacc.y:689 parser_yacc.y:729 parser_yacc.y:819
|
||||
msgid "Assert: 'local_profile rule' returned NULL."
|
||||
msgstr "Assert: Für »local_profile rule« wurde NULL zurückgegeben."
|
||||
|
||||
#: parser_yacc.y:824 parser_yacc.y:885
|
||||
#: parser_yacc.y:824 parser_yacc.y:885 parser_yacc.y:992
|
||||
#, c-format
|
||||
msgid "Unset boolean variable %s used in if-expression"
|
||||
msgstr "In Bedingungssatz verwendete Boolsche-Variable »%s« deaktivieren"
|
||||
|
||||
#: parser_yacc.y:882 parser_yacc.y:986
|
||||
#: parser_yacc.y:882 parser_yacc.y:986 parser_yacc.y:1092
|
||||
msgid "unsafe rule missing exec permissions"
|
||||
msgstr "Fehlende Ausführungsrechte bei unsicherer Regel"
|
||||
|
||||
#: parser_yacc.y:901 parser_yacc.y:954
|
||||
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060
|
||||
msgid "subset can only be used with link rules."
|
||||
msgstr "subset kann nur mit Link-Regeln verwendet werden."
|
||||
|
||||
#: parser_yacc.y:903 parser_yacc.y:956
|
||||
#: parser_yacc.y:903 parser_yacc.y:956 parser_yacc.y:1062
|
||||
msgid "link and exec perms conflict on a file rule using ->"
|
||||
msgstr ""
|
||||
"Verknüpfungs- und Ausführungsberechtigungen stehen in Konflikt mit einer "
|
||||
"Dateiregel, in der »->« verwendet wird"
|
||||
|
||||
#: parser_yacc.y:905 parser_yacc.y:958
|
||||
#: parser_yacc.y:905 parser_yacc.y:958 parser_yacc.y:1064
|
||||
msgid "link perms are not allowed on a named profile transition.\n"
|
||||
msgstr ""
|
||||
"Verknüpfungsberechtigungen sind bei einem benannten Profilübergang nicht "
|
||||
"erlaubt.\n"
|
||||
|
||||
#: parser_yacc.y:921 parser_yacc.y:1003
|
||||
#: parser_yacc.y:921 parser_yacc.y:1003 parser_yacc.y:1109
|
||||
#, c-format
|
||||
msgid "missing an end of line character? (entry: %s)"
|
||||
msgstr "Fehlt ein Zeilenumbruch? (Eintrag: %s)"
|
||||
|
||||
#: parser_yacc.y:975 parser_yacc.y:985 parser_yacc.y:1057 parser_yacc.y:1067
|
||||
#: parser_yacc.y:1145 parser_yacc.y:1155
|
||||
msgid "Invalid network entry."
|
||||
msgstr "Ungültiger Netzwerkeintrag."
|
||||
|
||||
#: parser_yacc.y:1039 parser_yacc.y:1048 parser_yacc.y:1254
|
||||
#: parser_yacc.y:1039 parser_yacc.y:1048 parser_yacc.y:1254 parser_yacc.y:1510
|
||||
#, c-format
|
||||
msgid "Invalid capability %s."
|
||||
msgstr "Ungültige Fähigkeit %s."
|
||||
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525
|
||||
#, c-format
|
||||
msgid "AppArmor parser error for %s%s%s at line %d: %s\n"
|
||||
msgstr "AppArmor-Analysefehler für %s%s%s in Zeile %d: %s\n"
|
||||
|
||||
#: parser_yacc.y:1072 parser_yacc.y:1275
|
||||
#: parser_yacc.y:1072 parser_yacc.y:1275 parser_yacc.y:1531
|
||||
#, c-format
|
||||
msgid "AppArmor parser error,%s%s line %d: %s\n"
|
||||
msgstr "AppArmor-Analysefehler,%s%s Zeile %d: %s\n"
|
||||
@@ -516,13 +540,13 @@ msgid "%s: Illegal open {, nesting groupings not allowed\n"
|
||||
msgstr ""
|
||||
"%s: Öffnen mit { ungültig, verschachtelte Gruppierungen sind nicht zulässig\n"
|
||||
|
||||
#: ../parser_regex.c:265 ../parser_regex.c:274
|
||||
#: ../parser_regex.c:265 ../parser_regex.c:274 ../parser_regex.c:278
|
||||
#, c-format
|
||||
msgid "%s: Regex grouping error: Invalid number of items between {}\n"
|
||||
msgstr ""
|
||||
"%s: Regex-Gruppierungsfehler: Ungültige Anzahl an Einträgen zwischen {}\n"
|
||||
|
||||
#: ../parser_regex.c:271 ../parser_regex.c:280
|
||||
#: ../parser_regex.c:271 ../parser_regex.c:280 ../parser_regex.c:284
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close }, no matching open { detected\n"
|
||||
@@ -530,7 +554,7 @@ msgstr ""
|
||||
"%s: Regex-Gruppierungsfehler: Ungültiges schließendes Zeichen }, kein "
|
||||
"passendes öffnendes Zeichen { gefunden\n"
|
||||
|
||||
#: ../parser_regex.c:337 ../parser_regex.c:343
|
||||
#: ../parser_regex.c:337 ../parser_regex.c:343 ../parser_regex.c:361
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Unclosed grouping or character class, expecting "
|
||||
@@ -544,17 +568,17 @@ msgstr ""
|
||||
msgid "%s: Internal buffer overflow detected, %d characters exceeded\n"
|
||||
msgstr "%s: Interner Pufferüberlauf erkannt, %d Zeichen überschritten\n"
|
||||
|
||||
#: ../parser_regex.c:355 ../parser_regex.c:361
|
||||
#: ../parser_regex.c:355 ../parser_regex.c:361 ../parser_regex.c:377
|
||||
#, c-format
|
||||
msgid "%s: Unable to parse input line '%s'\n"
|
||||
msgstr "%s: Eingabezeile »%s« kann nicht analysiert werden\n"
|
||||
|
||||
#: ../parser_regex.c:397 ../parser_regex.c:405
|
||||
#: ../parser_regex.c:397 ../parser_regex.c:405 ../parser_regex.c:421
|
||||
#, c-format
|
||||
msgid "%s: Invalid profile name '%s' - bad regular expression\n"
|
||||
msgstr "%s: Ungültiger Profilname »%s« – Fehlerhafter regulärer Ausdruck\n"
|
||||
|
||||
#: ../parser_policy.c:202 ../parser_policy.c:402
|
||||
#: ../parser_policy.c:202 ../parser_policy.c:402 ../parser_policy.c:375
|
||||
#, c-format
|
||||
msgid "ERROR merging rules for profile %s, failed to load\n"
|
||||
msgstr "FEHLER Vereinigungsregeln für Profil »%s«, Laden gescheitert\n"
|
||||
@@ -572,18 +596,18 @@ msgstr ""
|
||||
"erlaubt.\n"
|
||||
"\t»**« kann am Ende einer Regel verwendet werden.\n"
|
||||
|
||||
#: ../parser_policy.c:279 ../parser_policy.c:359
|
||||
#: ../parser_policy.c:279 ../parser_policy.c:359 ../parser_policy.c:332
|
||||
#, c-format
|
||||
msgid "ERROR processing regexs for profile %s, failed to load\n"
|
||||
msgstr "FEHLER Verarbeitung der Regexs für Profil »%s«, Laden gescheitert\n"
|
||||
|
||||
#: ../parser_policy.c:306 ../parser_policy.c:389
|
||||
#: ../parser_policy.c:306 ../parser_policy.c:389 ../parser_policy.c:362
|
||||
#, c-format
|
||||
msgid "ERROR expanding variables for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
"FEHLER beim Erweitern der Variablen für Profil »%s«, Laden gescheitert\n"
|
||||
|
||||
#: ../parser_policy.c:390 ../parser_policy.c:382
|
||||
#: ../parser_policy.c:390 ../parser_policy.c:382 ../parser_policy.c:355
|
||||
#, c-format
|
||||
msgid "ERROR adding hat access rule for profile %s\n"
|
||||
msgstr "FEHLER Hinzufügen von »hat«-Zugriffsregel für Profil %s\n"
|
||||
@@ -617,31 +641,32 @@ msgstr ""
|
||||
"%s: Beim Kombinieren von Regeln in der Nachverarbeitung sind Fehler "
|
||||
"aufgetreten. Der Vorgang wird abgebrochen.\n"
|
||||
|
||||
#: parser_lex.l:180
|
||||
#: parser_lex.l:180 parser_lex.l:186
|
||||
#, c-format
|
||||
msgid "Could not process include directory '%s' in '%s'"
|
||||
msgstr ""
|
||||
"Das enthaltene Verzeichnis »%s« in »%s« kann nicht verarbeitet werden"
|
||||
|
||||
#: ../parser_main.c:660
|
||||
#: ../parser_main.c:660 ../parser_main.c:523
|
||||
msgid "Feature buffer full."
|
||||
msgstr "Funktionspuffer ist voll."
|
||||
|
||||
#: ../parser_main.c:1115 ../parser_main.c:1132
|
||||
#: ../parser_main.c:1115 ../parser_main.c:1132 ../parser_main.c:1024
|
||||
#: ../parser_main.c:1041
|
||||
msgid "Out of memory"
|
||||
msgstr "Nicht genug Speicher"
|
||||
msgstr "Nicht genügend Speicher!"
|
||||
|
||||
#: ../parser_main.c:1182
|
||||
#: ../parser_main.c:1182 ../parser_main.c:1091
|
||||
#, c-format
|
||||
msgid "Can't create cache directory: %s\n"
|
||||
msgstr "Pufferverzeichnis kann nicht erstellt werden: %s\n"
|
||||
|
||||
#: ../parser_main.c:1185
|
||||
#: ../parser_main.c:1185 ../parser_main.c:1094
|
||||
#, c-format
|
||||
msgid "File in cache directory location: %s\n"
|
||||
msgstr "Datei im Pufferverzeichnisort: %s\n"
|
||||
|
||||
#: ../parser_main.c:1188
|
||||
#: ../parser_main.c:1188 ../parser_main.c:1097
|
||||
#, c-format
|
||||
msgid "Can't update cache directory: %s\n"
|
||||
msgstr "Pufferverzeichnis kann nicht aktualisiert werden: %s\n"
|
||||
@@ -656,11 +681,11 @@ msgstr "Intern: Unerwartetes D-Bus-Moduszeichen »%c« in der Eingabe"
|
||||
msgid "Internal error generated invalid DBus perm 0x%x\n"
|
||||
msgstr "Interner Fehler hat ungültige D-Bus-Zugriffsrechte 0x%x erstellt\n"
|
||||
|
||||
#: parser_yacc.y:575
|
||||
#: parser_yacc.y:575 parser_yacc.y:621
|
||||
msgid "deny prefix not allowed"
|
||||
msgstr "Verweigernpräfix nicht erlaubt"
|
||||
|
||||
#: parser_yacc.y:612
|
||||
#: parser_yacc.y:612 parser_yacc.y:658
|
||||
msgid "owner prefix not allowed"
|
||||
msgstr "Eigentümerpräfix nicht erlaubt"
|
||||
|
||||
@@ -676,25 +701,25 @@ msgstr "Eigentümerpräfix nicht bei D-Bus-Regeln erlauben"
|
||||
msgid "owner prefix not allow on capability rules"
|
||||
msgstr "Eigentümerpräfix nicht bei Fähigkeitsregeln erlauben"
|
||||
|
||||
#: parser_yacc.y:1357
|
||||
#: parser_yacc.y:1357 parser_yacc.y:1613
|
||||
#, c-format
|
||||
msgid "invalid mount conditional %s%s"
|
||||
msgstr "Ungültige Einhängebedingung %s%s"
|
||||
|
||||
#: parser_yacc.y:1374
|
||||
#: parser_yacc.y:1374 parser_yacc.y:1628
|
||||
msgid "bad mount rule"
|
||||
msgstr "Ungültige Einhängeregel"
|
||||
|
||||
#: parser_yacc.y:1381
|
||||
#: parser_yacc.y:1381 parser_yacc.y:1635
|
||||
msgid "mount point conditions not currently supported"
|
||||
msgstr "Einhängepunktbedingungen werden derzeit nicht unterstützt"
|
||||
|
||||
#: parser_yacc.y:1398
|
||||
#: parser_yacc.y:1398 parser_yacc.y:1650
|
||||
#, c-format
|
||||
msgid "invalid pivotroot conditional '%s'"
|
||||
msgstr "Ungültige pivotroot-Bedingung »%s«"
|
||||
|
||||
#: ../parser_regex.c:241
|
||||
#: ../parser_regex.c:241 ../parser_regex.c:236
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close ], no matching open [ detected\n"
|
||||
@@ -702,20 +727,20 @@ msgstr ""
|
||||
"%s: Regex-Gruppierungsfehler: Ungültiges schließendes Zeichen ], kein "
|
||||
"passendes öffnendes Zeichen [ gefunden\n"
|
||||
|
||||
#: ../parser_regex.c:257
|
||||
#: ../parser_regex.c:257 ../parser_regex.c:256
|
||||
#, c-format
|
||||
msgid "%s: Regex grouping error: Exceeded maximum nesting of {}\n"
|
||||
msgstr ""
|
||||
"%s: Regex-Gruppierungsfehler: maximale Verschachtelung von {} überschritten\n"
|
||||
|
||||
#: ../parser_policy.c:366
|
||||
#: ../parser_policy.c:366 ../parser_policy.c:339
|
||||
#, c-format
|
||||
msgid "ERROR processing policydb rules for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
"FEHLER beim Verarbeiten der policydb-Regeln für das Profil %s. Das Laden ist "
|
||||
"fehlgeschlagen.\n"
|
||||
|
||||
#: ../parser_policy.c:396
|
||||
#: ../parser_policy.c:396 ../parser_policy.c:369
|
||||
#, c-format
|
||||
msgid "ERROR replacing aliases for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
|
@@ -95,13 +95,15 @@ void update_mru_tstamp(FILE *file, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
char *cache_filename(const char *cachedir, const char *basename)
|
||||
char *cache_filename(aa_policy_cache *pc, int dir, const char *basename)
|
||||
{
|
||||
char *cachename;
|
||||
autofree char *path;
|
||||
|
||||
if (asprintf(&cachename, "%s/%s", cachedir, basename) < 0) {
|
||||
path = aa_policy_cache_dir_path(pc, dir);
|
||||
if (!path || asprintf(&cachename, "%s/%s", path, basename) < 0) {
|
||||
PERROR("Memory allocation error.");
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cachename;
|
||||
@@ -147,13 +149,13 @@ int setup_cache_tmp(const char **cachetmpname, const char *cachename)
|
||||
*cachetmpname = NULL;
|
||||
if (write_cache) {
|
||||
/* Otherwise, set up to save a cached copy */
|
||||
if (asprintf(&tmpname, "%s-XXXXXX", cachename)<0) {
|
||||
if (asprintf(&tmpname, "%s-XXXXXX", cachename) < 0) {
|
||||
perror("asprintf");
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
if ((cache_fd = mkstemp(tmpname)) < 0) {
|
||||
perror("mkstemp");
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
*cachetmpname = tmpname;
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ extern int debug_cache;
|
||||
void set_cache_tstamp(struct timespec t);
|
||||
void update_mru_tstamp(FILE *file, const char *path);
|
||||
bool valid_cached_file_version(const char *cachename);
|
||||
char *cache_filename(const char *cachedir, const char *basename);
|
||||
char *cache_filename(aa_policy_cache *pc, int dir, const char *basename);
|
||||
void valid_read_cache(const char *cachename);
|
||||
int cache_hit(const char *cachename);
|
||||
int setup_cache_tmp(const char **cachetmpname, const char *cachename);
|
||||
|
@@ -117,13 +117,19 @@ skip_profile() {
|
||||
"${profile%\~}" != "${profile}" ] ; then
|
||||
return 1
|
||||
fi
|
||||
# Silently ignore the dpkg files
|
||||
# Silently ignore the dpkg, pacman, and xbps files
|
||||
if [ "${profile%.dpkg-new}" != "${profile}" -o \
|
||||
"${profile%.dpkg-old}" != "${profile}" -o \
|
||||
"${profile%.dpkg-dist}" != "${profile}" -o \
|
||||
"${profile%.dpkg-bak}" != "${profile}" ] ; then
|
||||
"${profile%.dpkg-bak}" != "${profile}" -o \
|
||||
"${profile%.dpkg-remove}" != "${profile}" -o \
|
||||
"${profile%.pacsave}" != "${profile}" -o \
|
||||
"${profile%.pacnew}" != "${profile}" ] ; then
|
||||
return 2
|
||||
fi
|
||||
if echo "${profile}" | egrep -q '^.+\.new-[0-9\.]+_[0-9]+$'; then
|
||||
return 2 ;;
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
@@ -1,149 +0,0 @@
|
||||
#!/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/boot.apparmor
|
||||
# and its symbolic link
|
||||
# /sbin/rcapparmor
|
||||
#
|
||||
# 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: boot.cleanup
|
||||
# Required-Stop: $null
|
||||
# Should-Start: $local_fs
|
||||
# Should-Stop: $null
|
||||
# Default-Start: B
|
||||
# Default-Stop:
|
||||
# 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
|
||||
|
||||
# Ugh, SUSE doesn't implement action
|
||||
aa_action() { STRING=$1
|
||||
shift
|
||||
"$@"
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ] ; then
|
||||
log_success_msg $"$STRING "
|
||||
else
|
||||
log_failure_msg $"$STRING "
|
||||
fi
|
||||
return $rc
|
||||
}
|
||||
|
||||
aa_log_success_msg() {
|
||||
log_success_msg $*
|
||||
}
|
||||
|
||||
aa_log_warning_msg() {
|
||||
log_warning_msg $*
|
||||
}
|
||||
|
||||
aa_log_failure_msg() {
|
||||
log_failure_msg '\n'$*
|
||||
}
|
||||
|
||||
aa_log_action_start() {
|
||||
echo -n
|
||||
}
|
||||
|
||||
aa_log_action_end() {
|
||||
echo -n
|
||||
}
|
||||
|
||||
aa_log_daemon_msg() {
|
||||
echo -en "$@ "
|
||||
}
|
||||
|
||||
aa_log_skipped_msg() {
|
||||
echo -en "$@"
|
||||
echo -e "$rc_skipped"
|
||||
}
|
||||
|
||||
_set_status() {
|
||||
return $1
|
||||
}
|
||||
|
||||
aa_log_end_msg() {
|
||||
_set_status $1
|
||||
rc_status -v
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
@@ -101,4 +101,4 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor_parser(8), and
|
||||
L<http://wiki.apparmor.net>.
|
||||
L<https://wiki.apparmor.net>.
|
||||
|
@@ -4,6 +4,8 @@ TESTS=simple.pl
|
||||
PARSER_DIR=..
|
||||
PARSER_BIN=apparmor_parser
|
||||
PARSER=$(PARSER_DIR)/$(PARSER_BIN)
|
||||
# parser.conf to use in tests. Note that some test scripts have the parser options hardcoded, so passing PARSER_ARGS=... is not enough to override it.
|
||||
PARSER_ARGS=--config-file=./parser.conf
|
||||
PROVE_ARG=-f
|
||||
|
||||
ifeq ($(VERBOSE),1)
|
||||
@@ -30,14 +32,14 @@ gen_dbus: $(GEN_TRANS_DIRS)
|
||||
./gen-dbus.pl
|
||||
|
||||
error_output: $(PARSER)
|
||||
LANG=C $(PARSER) -S -I errors >/dev/null errors/okay.sd
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/single.sd | \
|
||||
LANG=C $(PARSER) $(PARSER_ARGS) -S -I errors >/dev/null errors/okay.sd
|
||||
LANG=C $(PARSER) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/single.sd | \
|
||||
grep -q "AppArmor parser error for errors/single.sd in errors/single.sd at line 3: Could not open 'failure'"
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/double.sd | \
|
||||
LANG=C $(PARSER) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/double.sd | \
|
||||
grep -q "AppArmor parser error for errors/double.sd in errors/includes/busted at line 66: Could not open 'does-not-exist'"
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/modefail.sd | \
|
||||
LANG=C $(PARSER) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/modefail.sd | \
|
||||
grep -q "AppArmor parser error for errors/modefail.sd in errors/modefail.sd at line 6: syntax error"
|
||||
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/multi_include.sd | \
|
||||
LANG=C $(PARSER) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/multi_include.sd | \
|
||||
grep -q "AppArmor parser error for errors/multi_include.sd in errors/multi_include.sd at line 12: Could not open 'failure'"
|
||||
@echo "Error Output: PASS"
|
||||
|
||||
@@ -48,13 +50,13 @@ caching: $(PARSER)
|
||||
LANG=C ./caching.py -p "$(PARSER)" $(PYTEST_ARG)
|
||||
|
||||
minimize: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER)" ./minimize.sh
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./minimize.sh
|
||||
|
||||
equality: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER)" ./equality.sh
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./equality.sh
|
||||
|
||||
valgrind: $(PARSER) gen_xtrans gen_dbus
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER)" -v simple_tests
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER) $(PARSER_ARGS)" -v simple_tests
|
||||
|
||||
$(PARSER):
|
||||
$(MAKE) -C $(PARSER_DIR) $(PARSER_BIN)
|
||||
|
@@ -60,13 +60,6 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
self.tmp_dir = tempfile.mkdtemp(prefix='aa-caching-')
|
||||
os.chmod(self.tmp_dir, 0o755)
|
||||
|
||||
# create directory for cached blobs
|
||||
self.cache_dir = os.path.join(self.tmp_dir, 'cache')
|
||||
os.mkdir(self.cache_dir)
|
||||
|
||||
# default path of the output cache file
|
||||
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||
|
||||
# write our sample abstraction and profile out
|
||||
self.abstraction = testlib.write_file(self.tmp_dir, ABSTRACTION, ABSTRACTION_CONTENTS)
|
||||
self.profile = testlib.write_file(self.tmp_dir, PROFILE, PROFILE_CONTENTS)
|
||||
@@ -75,11 +68,26 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
self.do_cleanup = False
|
||||
self.debug = True
|
||||
|
||||
self.cmd_prefix = [config.parser, '--base', self.tmp_dir, '--skip-kernel-load']
|
||||
# Warnings break the test harness, but chroots may not be setup
|
||||
# to have the config file, etc.
|
||||
self.cmd_prefix = [config.parser, '--config-file=./parser.conf', '--base', self.tmp_dir, '--skip-kernel-load']
|
||||
|
||||
if not self.is_apparmorfs_mounted():
|
||||
self.cmd_prefix += ['-M', './features_files/features.all']
|
||||
|
||||
# Otherwise get_cache_dir() will try to create /var/cache/apparmor
|
||||
# and will fail when the test suite is run as non-root.
|
||||
self.cmd_prefix += [
|
||||
'--cache-loc', os.path.join(self.tmp_dir, 'cache')
|
||||
]
|
||||
|
||||
# create directory for cached blobs
|
||||
# NOTE: get_cache_dir() requires cmd_prefix to be fully initialized
|
||||
self.cache_dir = self.get_cache_dir(create=True)
|
||||
|
||||
# default path of the output cache file
|
||||
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||
|
||||
def tearDown(self):
|
||||
'''teardown for each test'''
|
||||
|
||||
@@ -89,6 +97,22 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
if os.path.exists(self.tmp_dir):
|
||||
shutil.rmtree(self.tmp_dir)
|
||||
|
||||
def get_cache_dir(self, create=False):
|
||||
cmd = [config.parser, '--print-cache-dir'] + self.cmd_prefix
|
||||
rc, report = self.run_cmd(cmd)
|
||||
if rc != 0:
|
||||
if "unrecognized option '--print-cache-dir'" not in report:
|
||||
self.fail('Unknown apparmor_parser error:\n%s' % report)
|
||||
|
||||
cache_dir = os.path.join(self.tmp_dir, 'cache')
|
||||
else:
|
||||
cache_dir = report.strip()
|
||||
|
||||
if create:
|
||||
os.makedirs(cache_dir)
|
||||
|
||||
return cache_dir
|
||||
|
||||
def assert_path_exists(self, path, expected=True):
|
||||
if expected is True:
|
||||
self.assertTrue(os.path.exists(path),
|
||||
@@ -178,16 +202,16 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
|
||||
def setUp(self):
|
||||
super(AAParserAltCacheBasicTests, self).setUp()
|
||||
|
||||
alt_cache_dir = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_dir, 0o755)
|
||||
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
|
||||
self.unused_cache_dir = self.cache_dir
|
||||
self.cache_dir = alt_cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_dir])
|
||||
self.unused_cache_loc = self.cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir()
|
||||
|
||||
def tearDown(self):
|
||||
if len(os.listdir(self.unused_cache_dir)) > 0:
|
||||
self.fail('original cache dir \'%s\' not empty' % self.unused_cache_dir)
|
||||
if len(os.listdir(self.unused_cache_loc)) > 0:
|
||||
self.fail('original cache dir \'%s\' not empty' % self.unused_cache_loc)
|
||||
super(AAParserAltCacheBasicTests, self).tearDown()
|
||||
|
||||
|
||||
@@ -314,18 +338,22 @@ class AAParserCachingTests(AAParserCachingCommon):
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(self.cache_file, expected=False)
|
||||
|
||||
def test_cache_writing_updates_features(self):
|
||||
'''test cache writing updates features'''
|
||||
|
||||
def test_cache_writing_collision_of_features(self):
|
||||
'''test cache writing collision of features'''
|
||||
# cache dir with different features causes a collision resulting
|
||||
# in a new cache dir
|
||||
self.require_apparmorfs()
|
||||
|
||||
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||
new_file = self.get_cache_dir()
|
||||
new_features_file = new_file + '/.features';
|
||||
|
||||
cmd = list(self.cmd_prefix)
|
||||
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||
self.assert_path_exists(features_file)
|
||||
self.compare_features_file(features_file)
|
||||
self.assert_path_exists(new_features_file)
|
||||
self.compare_features_file(new_features_file)
|
||||
|
||||
def test_cache_writing_updates_cache_file(self):
|
||||
'''test cache writing updates cache file'''
|
||||
@@ -494,13 +522,13 @@ class AAParserAltCacheTests(AAParserCachingTests):
|
||||
def setUp(self):
|
||||
super(AAParserAltCacheTests, self).setUp()
|
||||
|
||||
alt_cache_dir = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_dir, 0o755)
|
||||
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
|
||||
self.orig_cache_dir = self.cache_dir
|
||||
self.cache_dir = alt_cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir(create=True)
|
||||
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_dir])
|
||||
|
||||
def tearDown(self):
|
||||
if self.check_orig_cache and len(os.listdir(self.orig_cache_dir)) > 0:
|
||||
|
0
parser/tst/parser.conf
Normal file
0
parser/tst/parser.conf
Normal file
@@ -81,7 +81,7 @@ sub test_profile {
|
||||
# child
|
||||
open(STDOUT, ">/dev/null") or die "Failed to redirect STDOUT";
|
||||
open(STDERR, ">/dev/null") or die "Failed to redirect STDERR";
|
||||
exec("$config{'parser'}", "-M", "features_files/features.all", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
|
||||
exec("$config{'parser'}", "--config-file=./parser.conf", "-M", "features_files/features.all", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
|
||||
# noreturn
|
||||
}
|
||||
|
||||
|
9
parser/tst/simple_tests/abi/bad_1.sd
Normal file
9
parser/tst/simple_tests/abi/bad_1.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path in quotes
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
|
||||
abi "abi/4.19,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_10.sd
Normal file
9
parser/tst/simple_tests/abi/bad_10.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi < "abi/4.19">,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_11.sd
Normal file
9
parser/tst/simple_tests/abi/bad_11.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi <"abi/4.19" >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_12.sd
Normal file
9
parser/tst/simple_tests/abi/bad_12.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi < "abi/4.19" >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_2.sd
Normal file
9
parser/tst/simple_tests/abi/bad_2.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path in quotes with spaces
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi abi/4.19",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_3.sd
Normal file
9
parser/tst/simple_tests/abi/bad_3.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi abs path in quotes
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi "/abi/4.19"
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_4.sd
Normal file
9
parser/tst/simple_tests/abi/bad_4.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi abs path in quotes with space
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi "/abi/4.19 ubuntu,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_5.sd
Normal file
9
parser/tst/simple_tests/abi/bad_5.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path no quotes missing ,
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
|
||||
abi abi/4.19
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/bad_6.sd
Normal file
9
parser/tst/simple_tests/abi/bad_6.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
|
||||
abi <abi/4.19,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_1.sd
Normal file
9
parser/tst/simple_tests/abi/ok_1.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path in quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi "abi/4.19",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_10.sd
Normal file
9
parser/tst/simple_tests/abi/ok_10.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
|
||||
abi < "abi/4.19">,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_11.sd
Normal file
9
parser/tst/simple_tests/abi/ok_11.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#=DISABLED
|
||||
|
||||
abi <"abi/4.19" >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_12.sd
Normal file
9
parser/tst/simple_tests/abi/ok_12.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
|
||||
abi < "abi/4.19" >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_13.sd
Normal file
9
parser/tst/simple_tests/abi/ok_13.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path quotes in <> with spaces
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi <"abi/4.19 ubuntu">,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_14.sd
Normal file
9
parser/tst/simple_tests/abi/ok_14.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path with space between path and ,
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi <abi/4.19> ,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_15.sd
Normal file
9
parser/tst/simple_tests/abi/ok_15.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path with space between path and ,
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi "abi/4.19" ,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_16.sd
Normal file
9
parser/tst/simple_tests/abi/ok_16.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path with space between path and ,
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi abi/4.19 ,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_17.sd
Normal file
9
parser/tst/simple_tests/abi/ok_17.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path no space between and and path
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi<abi/4.19>,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_18.sd
Normal file
9
parser/tst/simple_tests/abi/ok_18.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path no space between and and path
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi"abi/4.19",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_2.sd
Normal file
9
parser/tst/simple_tests/abi/ok_2.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path in quotes with spaces
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi "abi/4.19 ubuntu",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
10
parser/tst/simple_tests/abi/ok_20.sd
Normal file
10
parser/tst/simple_tests/abi/ok_20.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path in profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
|
||||
/does/not/exist {
|
||||
abi <abi/4.19>,
|
||||
|
||||
}
|
10
parser/tst/simple_tests/abi/ok_21.sd
Normal file
10
parser/tst/simple_tests/abi/ok_21.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path in profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
|
||||
/does/not/exist {
|
||||
abi "abi/4.19",
|
||||
|
||||
}
|
10
parser/tst/simple_tests/abi/ok_22.sd
Normal file
10
parser/tst/simple_tests/abi/ok_22.sd
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path in profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
|
||||
/does/not/exist {
|
||||
abi abi/4.19,
|
||||
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_3.sd
Normal file
9
parser/tst/simple_tests/abi/ok_3.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi abs path in quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi "/abi/4.19",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_4.sd
Normal file
9
parser/tst/simple_tests/abi/ok_4.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi abs path in quotes with space
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi "/abi/4.19 ubuntu",
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_5.sd
Normal file
9
parser/tst/simple_tests/abi/ok_5.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi relative path no quotes
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi abi/4.19,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_6.sd
Normal file
9
parser/tst/simple_tests/abi/ok_6.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi <abi/4.19>,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_7.sd
Normal file
9
parser/tst/simple_tests/abi/ok_7.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path spaces
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi < abi/4.19>,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_8.sd
Normal file
9
parser/tst/simple_tests/abi/ok_8.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path spaces
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi <abi/4.19 >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
9
parser/tst/simple_tests/abi/ok_9.sd
Normal file
9
parser/tst/simple_tests/abi/ok_9.sd
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
#=DESCRIPTION abi testing - abi path spaces
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
abi < abi/4.19 >,
|
||||
|
||||
/does/not/exist {
|
||||
}
|
7
parser/tst/simple_tests/bare_include_tests/bad_11.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/bad_11.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - non-existent include should fail
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/does/not/exist {
|
||||
#include "does-not-exist/does-not-exist"
|
||||
}
|
7
parser/tst/simple_tests/bare_include_tests/bad_12.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/bad_12.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - mis-parsing include should fail
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/does/not/exist {
|
||||
#include "/does-not-exist/does-not-exist"
|
||||
}
|
8
parser/tst/simple_tests/bare_include_tests/bad_13.sd
Normal file
8
parser/tst/simple_tests/bare_include_tests/bad_13.sd
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - non-existent include should fail
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/does/not/exist {
|
||||
#include "does-not-exist/does-not-exist"
|
||||
#include <includes/base>
|
||||
}
|
8
parser/tst/simple_tests/bare_include_tests/bad_14.sd
Normal file
8
parser/tst/simple_tests/bare_include_tests/bad_14.sd
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - non-existent include should fail
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/does/not/exist {
|
||||
#include <includes/base>
|
||||
#include "../does-not-exist/does-not-exist"
|
||||
}
|
7
parser/tst/simple_tests/bare_include_tests/ok_11.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/ok_11.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - basic include of global and local include
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/does/not/exist {
|
||||
include "simple_tests/include_tests/includes_okay_helper.include"
|
||||
}
|
7
parser/tst/simple_tests/bare_include_tests/ok_12.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/ok_12.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=DESCRIPTION includes testing - basic include of global and local include
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/does/not/exist {
|
||||
include "../tst/simple_tests/include_tests/includes_okay_helper.include"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user