mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 15:25:27 +00:00
Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4633658232 | ||
|
e48533b156 | ||
|
c5f45ab3fc | ||
|
963c896d91 | ||
|
70733be5c2 | ||
|
8020e36be9 | ||
|
a12e1b31dd | ||
|
d57f775d73 | ||
|
9ae7b1059f | ||
|
a1ca25db2d | ||
|
362a2db73c | ||
|
7c1a704c78 | ||
|
e1a8793ea1 | ||
|
0ed6607dc2 | ||
|
06b0a9ad37 | ||
|
32e226fe71 | ||
|
d68c4f5ac9 | ||
|
ebe3b8408a | ||
|
dc2e7d4a45 | ||
|
fa82a51523 | ||
|
15770576f8 | ||
|
b28ce5a2a0 | ||
|
69e0c2010a | ||
|
0865aa2301 | ||
|
9db3bba874 | ||
|
e3d924755b | ||
|
897072ce66 | ||
|
9ae44d3791 | ||
|
e32c437bfd | ||
|
ae7471667c | ||
|
5bbe6b769a | ||
|
2dea9d6dc9 | ||
|
a5e4fa835d | ||
|
531e53b577 | ||
|
410352c5ae | ||
|
0f6554a851 | ||
|
ac66f9cbea | ||
|
6896017481 | ||
|
5b7209c040 | ||
|
549bdef505 | ||
|
da47860e77 | ||
|
3c74f77b8d | ||
|
bb6505e8fc | ||
|
5d4b4ae3c7 | ||
|
de7796957d | ||
|
21015d2e7b | ||
|
325139f435 | ||
|
1c656dfebd | ||
|
18cf8d86bc | ||
|
bd3f0e5ffe | ||
|
f4c2ac7342 | ||
|
5d397373b5 | ||
|
fc058486d7 | ||
|
7ecceb9e12 | ||
|
a1b08c2f65 | ||
|
e490484b90 | ||
|
d303ee9393 | ||
|
995c0e96f8 | ||
|
baee295e63 | ||
|
99b3c562be | ||
|
173b8cd70a | ||
|
b22faedbfc | ||
|
bda6b297b8 | ||
|
57e5d6cc4e | ||
|
43bf2028c4 | ||
|
ab3e53d7f7 | ||
|
0fb49edfcd | ||
|
01bc13dee4 | ||
|
fccfaa6bfc | ||
|
1aaffa6e1b | ||
|
612701ec4d | ||
|
29102a2d04 | ||
|
02193447bf | ||
|
8f58475e94 | ||
|
0078215941 | ||
|
e05e08a00e | ||
|
35febe2c82 | ||
|
81e5699248 | ||
|
2c85212428 | ||
|
e73079b46a | ||
|
d8d80d8111 | ||
|
03af33b1d5 | ||
|
efd52522a6 | ||
|
968adf9467 | ||
|
d788de3787 | ||
|
608f230c75 | ||
|
d8c315114b | ||
|
cbd68a6126 | ||
|
f8dc00d915 | ||
|
f0f2933f49 | ||
|
cc022e61a4 | ||
|
deaada8dd2 | ||
|
e1174d196b | ||
|
f9bd0b4c5d | ||
|
2755f5e9c6 | ||
|
3954504651 | ||
|
e0249e219e | ||
|
441ecdd434 | ||
|
0a657f4acd | ||
|
6eac722531 | ||
|
5578276177 | ||
|
520dd4fab0 | ||
|
84391104f4 | ||
|
f7f3d4e6f2 | ||
|
e3d4200453 | ||
|
6f31a83c5a |
2
Makefile
2
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?=apparmor-2.13
|
||||
REPO_BRANCH?=apparmor-2.12
|
||||
|
||||
COVERITY_DIR=cov-int
|
||||
RELEASE_DIR=apparmor-${VERSION}
|
||||
|
@@ -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: 2018-02-09 23:55+0000\n"
|
||||
"Last-Translator: Tobias Bannert <tobannert@gmail.com>\n"
|
||||
"PO-Revision-Date: 2017-12-21 12:20+0000\n"
|
||||
"Last-Translator: Christian Boltz <Unknown>\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: 2018-02-11 05:14+0000\n"
|
||||
"X-Generator: Launchpad (build 18544)\n"
|
||||
"X-Launchpad-Export-Date: 2017-12-22 05:12+0000\n"
|
||||
"X-Generator: Launchpad (build 18521)\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 "Vielleicht – Richtlinienschnittstelle nicht verfügbar.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../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"
|
||||
|
@@ -82,7 +82,7 @@ SECDIR ?= ${DESTDIR}/lib/security
|
||||
.PHONY: install
|
||||
install: $(NAME).so
|
||||
install -m 755 -d $(SECDIR)
|
||||
install -m 755 $(NAME).so $(SECDIR)/
|
||||
install -m 555 $(NAME).so $(SECDIR)/
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
@@ -1 +1 @@
|
||||
2.13.1
|
||||
2.12.1
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 50 KiB |
@@ -1,13 +1,12 @@
|
||||
From 2e7f6d0dc0f1d3642950f529b451af73fa1baf9c Mon Sep 17 00:00:00 2001
|
||||
From a3b0cb6676a04cdad5cc357bc422d0398083b435 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 2/2] apparmor: af_unix mediation
|
||||
Subject: [PATCH 17/17] UBUNTU: SAUCE: 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 ++++++++++++++++++++++++++++++++++++
|
||||
@@ -24,10 +23,10 @@ Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
create mode 100644 security/apparmor/include/af_unix.h
|
||||
|
||||
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
|
||||
index e7ff2183532a..90c118f39e13 100644
|
||||
index dafdd387d42b..ef39226ff4aa 100644
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -5,7 +5,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
|
||||
@@ -4,7 +4,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 \
|
||||
@@ -695,7 +694,7 @@ index 000000000000..c6876db2dbde
|
||||
+ return error;
|
||||
+}
|
||||
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
|
||||
index 518d5928661b..63a8a462fc96 100644
|
||||
index 125dad5c3fde..20cdb1c4b266 100644
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -2187,6 +2187,11 @@ static struct aa_sfs_entry aa_sfs_entry_ns[] = {
|
||||
@@ -921,7 +920,7 @@ index 4364088a0b9e..26660a1a50b0 100644
|
||||
if (!state)
|
||||
return 0;
|
||||
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
|
||||
index 72b915dfcaf7..5533d2f1d9de 100644
|
||||
index cc5ab23a2d84..0ede66d80a53 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -26,6 +26,7 @@
|
||||
@@ -1391,5 +1390,5 @@ index 33d54435f8d6..dd1953b08e58 100644
|
||||
+ aa_label_sk_perm(label, op, request, sock->sk));
|
||||
}
|
||||
--
|
||||
2.14.1
|
||||
2.11.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
This is based on v4.14 final
|
||||
This series is based on what is currently in linux-next scheduled for
|
||||
inclusion in 4.14
|
||||
|
||||
base socket mediation and af_unix-mediation are the last two remaining
|
||||
patches that are out of tree
|
||||
af_unix-mediation is the last remaining patch that is out of tree
|
||||
|
File diff suppressed because it is too large
Load Diff
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 reallocarray])
|
||||
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_C_CONST
|
||||
|
@@ -40,8 +40,6 @@ 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>>
|
||||
@@ -64,8 +62,6 @@ 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
|
||||
@@ -112,12 +108,6 @@ 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>
|
||||
@@ -136,20 +126,15 @@ 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 or NULL on error.
|
||||
I<aa_features> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
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.
|
||||
All aa_features functions described above are present in libapparmor version
|
||||
2.10 and newer.
|
||||
|
||||
aa_features_unref() saves the value of errno when called and restores errno
|
||||
before exiting in libapparmor version 2.12 and newer.
|
||||
|
@@ -34,10 +34,6 @@ 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>>
|
||||
@@ -46,8 +42,6 @@ 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);>
|
||||
@@ -56,10 +50,6 @@ 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
|
||||
@@ -69,35 +59,19 @@ 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. 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.
|
||||
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().
|
||||
|
||||
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
|
||||
object.
|
||||
@@ -116,18 +90,6 @@ 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>
|
||||
@@ -140,29 +102,15 @@ 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 or NULL on error.
|
||||
I<aa_policy_cache> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
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.
|
||||
All aa_policy_cache functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
|
||||
aa_policy_cache_unref() saves the value of errno when called and restores errno
|
||||
before exiting in libapparmor version 2.12 and newer.
|
||||
|
@@ -154,7 +154,6 @@ 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,
|
||||
@@ -187,22 +186,12 @@ 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,8 +34,6 @@ 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 = 7
|
||||
AA_LIB_REVISION = 0
|
||||
AA_LIB_AGE = 6
|
||||
AA_LIB_CURRENT = 5
|
||||
AA_LIB_REVISION = 2
|
||||
AA_LIB_AGE = 4
|
||||
|
||||
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 PMurHash.h
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
|
||||
|
||||
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_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.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
|
||||
|
||||
|
@@ -1,317 +0,0 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
@@ -1,64 +0,0 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
* 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-2017
|
||||
* Copyright (c) 2014
|
||||
* Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
@@ -32,16 +31,13 @@
|
||||
#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];
|
||||
};
|
||||
|
||||
@@ -209,29 +205,6 @@ 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 == '{';
|
||||
@@ -435,14 +408,6 @@ 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;
|
||||
@@ -478,15 +443,6 @@ 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;
|
||||
@@ -621,21 +577,3 @@ 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,26 +95,6 @@ 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-2017
|
||||
* Copyright (c) 2014
|
||||
* Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -16,11 +16,8 @@
|
||||
* 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>
|
||||
@@ -32,155 +29,31 @@
|
||||
#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 n;
|
||||
int dirfd[MAX_POLICY_CACHE_OVERLAY_DIRS];
|
||||
int dirfd;
|
||||
};
|
||||
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
/* remove regular files */
|
||||
/* remove regular files */
|
||||
if (S_ISREG(st->st_mode))
|
||||
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[0], "."))
|
||||
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
|
||||
return -1;
|
||||
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd[0],
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE) == -1)
|
||||
return -1;
|
||||
|
||||
@@ -192,176 +65,51 @@ 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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return create_cache(policy_cache, kernel_features);
|
||||
}
|
||||
|
||||
struct miss_cb_data {
|
||||
aa_features *features;
|
||||
const char *path;
|
||||
char *pattern;
|
||||
char *cache_name; /* return */
|
||||
long n;
|
||||
};
|
||||
|
||||
/* called on cache collision or miss where cache isn't present */
|
||||
static int cache_miss_cb(int dirfd, const struct dirent *ent, void *arg)
|
||||
{
|
||||
struct miss_cb_data *data = arg;
|
||||
char *cache_name, *pos, *tmp;
|
||||
long n;
|
||||
int len;
|
||||
|
||||
/* TODO: update to tighter pattern match of just trailing #s */
|
||||
if (fnmatch(data->pattern, ent->d_name, 0))
|
||||
return 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
PDEBUG("Could not open cache_dir: %m");
|
||||
return -1;
|
||||
/* The cache directory needs to be refreshed */
|
||||
call_create_cache = true;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return call_create_cache ?
|
||||
create_cache(policy_cache, kernel_features) : 0;
|
||||
}
|
||||
|
||||
struct replace_all_cb_data {
|
||||
aa_policy_cache *policy_cache;
|
||||
aa_kernel_interface *kernel_interface;
|
||||
};
|
||||
|
||||
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *cb_data)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
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,
|
||||
data->policy_cache->dirfd,
|
||||
name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,11 +133,8 @@ 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;
|
||||
|
||||
@@ -398,79 +143,55 @@ int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: currently no reaping of caches in excess of max_caches */
|
||||
if (max_caches > 1) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc = calloc(1, sizeof(*pc));
|
||||
if (!pc) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
pc->n = 0;
|
||||
for (i = 0; i < MAX_POLICY_CACHE_OVERLAY_DIRS; i++)
|
||||
pc->dirfd[i] = -1;
|
||||
pc->dirfd = -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->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;
|
||||
pc->kernel_features = kernel_features;
|
||||
|
||||
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
|
||||
@@ -489,14 +210,13 @@ aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
|
||||
*/
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
int i, save = errno;
|
||||
int save = errno;
|
||||
|
||||
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
|
||||
aa_features_unref(policy_cache->features);
|
||||
for (i = 0; i < MAX_POLICY_CACHE_OVERLAY_DIRS; i++) {
|
||||
if (policy_cache->dirfd[i] != -1)
|
||||
close(policy_cache->dirfd[i]);
|
||||
}
|
||||
aa_features_unref(policy_cache->kernel_features);
|
||||
if (policy_cache->dirfd != -1)
|
||||
close(policy_cache->dirfd);
|
||||
free(policy_cache);
|
||||
}
|
||||
|
||||
@@ -534,7 +254,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->features,
|
||||
policy_cache->kernel_features,
|
||||
NULL) == -1) {
|
||||
kernel_interface = NULL;
|
||||
return -1;
|
||||
@@ -542,158 +262,10 @@ 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_overlaydirat_for_each(policy_cache->dirfd, policy_cache->n,
|
||||
&cb_data, replace_all_cb);
|
||||
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &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,24 +38,11 @@
|
||||
#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
|
||||
#define secure_getenv(env) NULL
|
||||
#error neither secure_getenv nor __secure_getenv is available
|
||||
#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;
|
||||
@@ -69,10 +56,6 @@ 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 },
|
||||
@@ -186,252 +169,13 @@ int _aa_asprintf(char **strp, const char *fmt, ...)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 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 *))
|
||||
static int dot_or_dot_dot_filter(const struct dirent *ent)
|
||||
{
|
||||
autoclose int cb_dirfd = -1;
|
||||
int fd_for_dir = -1;
|
||||
const struct dirent *ent;
|
||||
DIR *dir;
|
||||
int save, rc;
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,7 +219,8 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_dirs = readdirfd(cb_dirfd, &namelist, NULL);
|
||||
num_dirs = scandirat(cb_dirfd, ".", &namelist,
|
||||
dot_or_dot_dot_filter, NULL);
|
||||
if (num_dirs == -1) {
|
||||
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
|
||||
return -1;
|
||||
|
@@ -17,7 +17,6 @@
|
||||
#ifndef _AA_PRIVATE_H
|
||||
#define _AA_PRIVATE_H 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/apparmor_private.h>
|
||||
|
||||
@@ -52,7 +51,4 @@ 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 */
|
||||
|
@@ -2,8 +2,6 @@
|
||||
# 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.
|
||||
@@ -24,11 +22,10 @@ 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 aa-teardown.8
|
||||
MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 subdomain.conf.5
|
||||
|
||||
YACC := bison
|
||||
YFLAGS := -d
|
||||
@@ -317,9 +314,12 @@ install-redhat:
|
||||
install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
|
||||
|
||||
.PHONY: install-suse
|
||||
install-suse: install-systemd
|
||||
install-suse:
|
||||
install -m 755 -d $(DESTDIR)/etc/init.d
|
||||
install -m 755 rc.apparmor.$(subst install-,,$(@)) $(DESTDIR)/etc/init.d/boot.apparmor
|
||||
install -m 755 -d $(DESTDIR)/sbin
|
||||
ln -sf service $(DESTDIR)/sbin/rcapparmor
|
||||
ln -sf /etc/init.d/boot.apparmor $(DESTDIR)/sbin/rcapparmor
|
||||
ln -sf rcapparmor $(DESTDIR)/sbin/rcsubdomain
|
||||
|
||||
.PHONY: install-slackware
|
||||
install-slackware:
|
||||
@@ -379,14 +379,6 @@ 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
|
||||
|
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
test $# = 0 || {
|
||||
echo "Usage: $0"
|
||||
echo
|
||||
echo "Unloads all AppArmor profiles"
|
||||
exit 1
|
||||
}
|
||||
|
||||
/lib/apparmor/apparmor.systemd stop
|
@@ -1,40 +0,0 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# 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
|
@@ -1,26 +0,0 @@
|
||||
[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
|
@@ -1,100 +0,0 @@
|
||||
#!/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,10 +46,9 @@ 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, *.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.
|
||||
*.dpkg-old, *.dpkg-dist, *-dpkg-bak, *.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).
|
||||
@@ -233,28 +232,8 @@ inconsistent state
|
||||
|
||||
=item -L, --cache-loc
|
||||
|
||||
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.
|
||||
Set the location of the cache directory. If not specified the cache location
|
||||
defaults to /etc/apparmor.d/cache
|
||||
|
||||
=item -Q, --skip-kernel-load
|
||||
|
||||
@@ -355,17 +334,6 @@ This option tells the parser to not attempt to rebuild the cache on
|
||||
failure, instead the parser continues on with processing the remaining
|
||||
profiles.
|
||||
|
||||
=item --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
|
||||
|
@@ -25,8 +25,6 @@
|
||||
#include "parser.h"
|
||||
#include "profile.h"
|
||||
|
||||
typedef int (*comparison_fn_t)(const void *, const void *);
|
||||
|
||||
struct alias_rule {
|
||||
char *from;
|
||||
char *to;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* Copyright (c) 2010 - 2018
|
||||
* Copyright (c) 2010 - 2013
|
||||
* Canonical Ltd. (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -59,10 +59,8 @@
|
||||
#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-2018 Canonical Ltd.";
|
||||
const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2012 Canonical Ltd.";
|
||||
|
||||
int opt_force_complain = 0;
|
||||
int binary_input = 0;
|
||||
@@ -99,20 +97,12 @@ 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 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 char *cacheloc = NULL;
|
||||
|
||||
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:";
|
||||
@@ -143,6 +133,9 @@ 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'},
|
||||
@@ -150,21 +143,12 @@ 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},
|
||||
};
|
||||
|
||||
@@ -194,8 +178,7 @@ 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 Compile features set in file n\n"
|
||||
"--kernel-features n Kernel features set in file n\n"
|
||||
"-M n, --features-file n Use only features 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"
|
||||
@@ -205,8 +188,7 @@ 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"
|
||||
" --print-cache_dir Print the cache directory path\n"
|
||||
"-L, --cache-loc n Set the location of the profile caches\n"
|
||||
"-L, --cache-loc n Set the location of the profile cache\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"
|
||||
@@ -220,8 +202,6 @@ 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);
|
||||
}
|
||||
@@ -242,55 +222,6 @@ 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,
|
||||
@@ -388,16 +319,6 @@ 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
|
||||
*/
|
||||
@@ -408,7 +329,8 @@ static int process_arg(int c, char *optarg)
|
||||
switch (c) {
|
||||
case 0:
|
||||
PERROR("Assert, in getopt_long handling\n");
|
||||
exit(1);
|
||||
display_usage(progname);
|
||||
exit(0);
|
||||
break;
|
||||
case 'a':
|
||||
count++;
|
||||
@@ -527,7 +449,7 @@ static int process_arg(int c, char *optarg)
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (aa_features_new_from_string(&compile_features,
|
||||
if (aa_features_new_from_string(&features,
|
||||
optarg, strlen(optarg))) {
|
||||
fprintf(stderr,
|
||||
"Failed to parse features string: %m\n");
|
||||
@@ -535,21 +457,13 @@ static int process_arg(int c, char *optarg)
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
if (aa_features_new(&compile_features, AT_FDCWD, optarg)) {
|
||||
if (aa_features_new(&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;
|
||||
@@ -593,11 +507,7 @@ static int process_arg(int c, char *optarg)
|
||||
skip_bad_cache_rebuild = 1;
|
||||
break;
|
||||
case 'L':
|
||||
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);
|
||||
}
|
||||
cacheloc = strdup(optarg);
|
||||
break;
|
||||
case 'Q':
|
||||
kernel_load = 0;
|
||||
@@ -626,22 +536,8 @@ 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:
|
||||
/* 'unrecognized option' error message gets printed by getopt_long() */
|
||||
display_usage(progname);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
@@ -649,36 +545,21 @@ 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)
|
||||
{
|
||||
if (!early_arg(c))
|
||||
count += process_arg(c, optarg);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -693,10 +574,8 @@ static int process_config_file(const char *name)
|
||||
int c, o;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if (!f) {
|
||||
pwarn("config file '%s' not found\n", name);
|
||||
if (!f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1)
|
||||
process_arg(c, optarg);
|
||||
@@ -713,6 +592,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -743,37 +623,33 @@ no_match:
|
||||
perms_create = 1;
|
||||
}
|
||||
|
||||
static void set_supported_features(aa_features *kernel_features unused)
|
||||
static void set_supported_features(void)
|
||||
{
|
||||
/* has process_args() already assigned a match string? */
|
||||
if (!compile_features && aa_features_new_from_kernel(&compile_features) == -1) {
|
||||
if (!features && aa_features_new_from_kernel(&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(compile_features, "file");
|
||||
kernel_supports_network = aa_features_supports(compile_features, "network");
|
||||
kernel_supports_unix = aa_features_supports(compile_features,
|
||||
kernel_supports_policydb = aa_features_supports(features, "file");
|
||||
kernel_supports_network = aa_features_supports(features, "network");
|
||||
kernel_supports_unix = aa_features_supports(features,
|
||||
"network/af_unix");
|
||||
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,
|
||||
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,
|
||||
"policy/set_load");
|
||||
kernel_supports_diff_encode = aa_features_supports(compile_features,
|
||||
kernel_supports_diff_encode = aa_features_supports(features,
|
||||
"policy/diff_encode");
|
||||
kernel_supports_stacking = aa_features_supports(compile_features,
|
||||
kernel_supports_stacking = aa_features_supports(features,
|
||||
"domain/stack");
|
||||
|
||||
if (aa_features_supports(compile_features, "policy/versions/v7"))
|
||||
if (aa_features_supports(features, "policy/versions/v7"))
|
||||
kernel_abi_version = 7;
|
||||
else if (aa_features_supports(compile_features, "policy/versions/v6"))
|
||||
else if (aa_features_supports(features, "policy/versions/v6"))
|
||||
kernel_abi_version = 6;
|
||||
|
||||
if (!kernel_supports_diff_encode)
|
||||
@@ -781,33 +657,6 @@ static void set_supported_features(aa_features *kernel_features unused)
|
||||
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)
|
||||
{
|
||||
@@ -892,11 +741,10 @@ int test_for_dir_mode(const char *basename, const char *linkdir)
|
||||
}
|
||||
|
||||
int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
const char *profilename, aa_policy_cache *pc)
|
||||
const char *profilename, const char *cachedir)
|
||||
{
|
||||
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;
|
||||
@@ -913,7 +761,6 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
} else {
|
||||
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);
|
||||
@@ -938,17 +785,9 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
|
||||
}
|
||||
|
||||
/* setup cachename and tstamp */
|
||||
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);
|
||||
}
|
||||
if (!force_complain && !skip_cache) {
|
||||
cachename = cache_filename(cachedir, basename);
|
||||
valid_read_cache(cachename);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -980,6 +819,8 @@ 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)
|
||||
@@ -1015,27 +856,15 @@ 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);
|
||||
pwarn("Warning failed to create cache: %s\n",
|
||||
PERROR("Warning failed to create cache: %s\n",
|
||||
basename);
|
||||
} else {
|
||||
install_cache(cachetmpname, writecachename);
|
||||
install_cache(cachetmpname, cachename);
|
||||
}
|
||||
}
|
||||
out:
|
||||
@@ -1177,7 +1006,7 @@ static void setup_parallel_compile(void)
|
||||
struct dir_cb_data {
|
||||
aa_kernel_interface *kernel_interface;
|
||||
const char *dirname; /* name of the parent dir */
|
||||
aa_policy_cache *policy_cache; /* policy_cache to use */
|
||||
const char *cachedir; /* path to the cache sub directory */
|
||||
};
|
||||
|
||||
/* data - pointer to a dir_cb_data */
|
||||
@@ -1192,7 +1021,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->policy_cache),
|
||||
path, cb_data->cachedir),
|
||||
handle_work_result);
|
||||
}
|
||||
return rc;
|
||||
@@ -1218,17 +1047,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 (!kernel_features && aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
if (!features) {
|
||||
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[])
|
||||
@@ -1244,8 +1073,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
init_base_dir();
|
||||
|
||||
process_early_args(argc, argv);
|
||||
process_config_file(config_file);
|
||||
process_config_file("/etc/apparmor/parser.conf");
|
||||
optind = process_args(argc, argv);
|
||||
|
||||
setup_parallel_compile();
|
||||
@@ -1265,7 +1093,7 @@ int main(int argc, char *argv[])
|
||||
setup_flags();
|
||||
|
||||
if (!(UNPRIVILEGED_OPS) &&
|
||||
aa_kernel_interface_new(&kernel_interface, kernel_features, apparmorfs) == -1) {
|
||||
aa_kernel_interface_new(&kernel_interface, features, apparmorfs) == -1) {
|
||||
PERROR(_("Warning: unable to find a suitable fs in %s, is it "
|
||||
"mounted?\nUse --subdomainfs to override.\n"),
|
||||
MOUNTED_FS);
|
||||
@@ -1273,22 +1101,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if ((!skip_cache && (write_cache || !skip_read_cache)) ||
|
||||
print_cache_dir || force_clear_cache) {
|
||||
uint16_t max_caches = write_cache && cond_clear_cache ? (uint16_t) (-1) : 0;
|
||||
force_clear_cache) {
|
||||
uint16_t max_caches = write_cache && cond_clear_cache ? 1 : 0;
|
||||
|
||||
if (!cacheloc[0]) {
|
||||
cacheloc[0] = "/var/cache/apparmor";
|
||||
cacheloc_n = 1;
|
||||
if (!cacheloc && asprintf(&cacheloc, "%s/cache", basedir) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
return 1;
|
||||
}
|
||||
if (print_cache_dir)
|
||||
return do_print_cache_dirs(kernel_features, cacheloc,
|
||||
cacheloc_n) ? 0 : 1;
|
||||
|
||||
if (force_clear_cache) {
|
||||
/* only ever write to the first cacheloc location */
|
||||
if (aa_policy_cache_remove(AT_FDCWD, cacheloc[0])) {
|
||||
if (aa_policy_cache_remove(AT_FDCWD, cacheloc)) {
|
||||
PERROR(_("Failed to clear cache files (%s): %s\n"),
|
||||
cacheloc[0], strerror(errno));
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1297,34 +1121,26 @@ 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, kernel_features,
|
||||
AT_FDCWD, cacheloc[0], max_caches);
|
||||
|
||||
retval = aa_policy_cache_new(&policy_cache, features,
|
||||
AT_FDCWD, cacheloc, max_caches);
|
||||
if (retval) {
|
||||
if (errno != ENOENT && errno != EEXIST && errno != EROFS) {
|
||||
PERROR(_("Failed setting up policy cache (%s): %s\n"),
|
||||
cacheloc[0], strerror(errno));
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (show_cache) {
|
||||
if (max_caches > 0)
|
||||
PERROR("Cache write disabled: Cannot create cache '%s': %m\n",
|
||||
cacheloc[0]);
|
||||
cacheloc);
|
||||
else
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid: %m\n");
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid\n");
|
||||
}
|
||||
|
||||
write_cache = 0;
|
||||
} 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]);
|
||||
}
|
||||
skip_read_cache = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1355,7 +1171,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
memset(&cb_data, 0, sizeof(struct dir_cb_data));
|
||||
cb_data.dirname = profilename;
|
||||
cb_data.policy_cache = policy_cache;
|
||||
cb_data.cachedir = cacheloc;
|
||||
cb_data.kernel_interface = kernel_interface;
|
||||
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||
@@ -1369,7 +1185,7 @@ int main(int argc, char *argv[])
|
||||
handle_work_result);
|
||||
} else {
|
||||
work_spawn(process_profile(option, kernel_interface,
|
||||
profilename, policy_cache),
|
||||
profilename, cacheloc),
|
||||
handle_work_result);
|
||||
}
|
||||
|
||||
|
@@ -25,9 +25,6 @@
|
||||
#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,
|
||||
|
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: 2018-04-06 14:39+0000\n"
|
||||
"PO-Revision-Date: 2015-09-05 20:55+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: 2018-04-07 05:20+0000\n"
|
||||
"X-Generator: Launchpad (build 18599)\n"
|
||||
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
|
||||
"X-Generator: Launchpad (build 18053)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#: ../parser_include.c:113 ../parser_include.c:111
|
||||
#: ../parser_include.c:113
|
||||
msgid "Error: Out of memory.\n"
|
||||
msgstr "Fehler: nicht genügend Speicher!\n"
|
||||
msgstr "Fehler: Kein Speicher vorhanden.\n"
|
||||
|
||||
#: ../parser_include.c:123 ../parser_include.c:121
|
||||
#: ../parser_include.c:123
|
||||
#, 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,108 +31,99 @@ 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:151
|
||||
#: ../parser_include.c:147
|
||||
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:49
|
||||
#: ../parser_interface.c:69 ../parser_interface.c:72
|
||||
msgid "Bad write position\n"
|
||||
msgstr "Ungültige Schreibposition\n"
|
||||
|
||||
#: ../parser_interface.c:72 ../parser_interface.c:75 ../parser_interface.c:52
|
||||
#: ../parser_interface.c:72 ../parser_interface.c:75
|
||||
msgid "Permission denied\n"
|
||||
msgstr "Zugriff verweigert\n"
|
||||
|
||||
#: ../parser_interface.c:75 ../parser_interface.c:78 ../parser_interface.c:55
|
||||
#: ../parser_interface.c:75 ../parser_interface.c:78
|
||||
msgid "Out of memory\n"
|
||||
msgstr "Nicht genügend Speicher!\n"
|
||||
msgstr "Kein Speicher vorhanden\n"
|
||||
|
||||
#: ../parser_interface.c:78 ../parser_interface.c:81 ../parser_interface.c:58
|
||||
#: ../parser_interface.c:78 ../parser_interface.c:81
|
||||
msgid "Couldn't copy profile: Bad memory address\n"
|
||||
msgstr "Profil konnte nicht kopiert werden: falsche Speicheradresse\n"
|
||||
msgstr "Profil konnte nicht kopiert werden: Keine Speicheradresse\n"
|
||||
|
||||
#: ../parser_interface.c:81 ../parser_interface.c:84 ../parser_interface.c:61
|
||||
#: ../parser_interface.c:81 ../parser_interface.c:84
|
||||
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:64
|
||||
#: ../parser_interface.c:84 ../parser_interface.c:87
|
||||
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:67
|
||||
#: ../parser_interface.c:87 ../parser_interface.c:90
|
||||
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:70
|
||||
#: ../parser_interface.c:90 ../parser_interface.c:93
|
||||
msgid "Profile already exists\n"
|
||||
msgstr "Profil ist bereits vorhanden\n"
|
||||
|
||||
#: ../parser_interface.c:93 ../parser_interface.c:96 ../parser_interface.c:73
|
||||
#: ../parser_interface.c:93 ../parser_interface.c:96
|
||||
msgid "Profile doesn't exist\n"
|
||||
msgstr "Profil ist nicht vorhanden\n"
|
||||
|
||||
#: ../parser_interface.c:96 ../parser_interface.c:99 ../parser_interface.c:76
|
||||
#: ../parser_interface.c:96 ../parser_interface.c:99
|
||||
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:79
|
||||
#: ../parser_interface.c:99 ../parser_interface.c:102
|
||||
#, 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"
|
||||
@@ -145,7 +136,6 @@ 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"
|
||||
@@ -156,19 +146,16 @@ 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."
|
||||
@@ -184,24 +171,22 @@ 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:169
|
||||
#: parser_lex.l:100 parser_lex.l:163
|
||||
#, 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:173
|
||||
#: parser_lex.l:104 parser_lex.l:167
|
||||
#, c-format
|
||||
msgid "fstat failed for '%s'"
|
||||
msgstr "fstat fehlgeschlagen für »%s«"
|
||||
@@ -216,18 +201,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:139
|
||||
#: parser_lex.l:155 parser_lex.l:133
|
||||
#, 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:638
|
||||
#: parser_lex.l:469 parser_lex.l:655 parser_lex.l:586
|
||||
#, c-format
|
||||
msgid "Found unexpected character: '%s'"
|
||||
msgstr "Unerwartetes Zeichen gefunden: »%s«"
|
||||
|
||||
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428
|
||||
#: parser_lex.l:386 parser_lex.l:418
|
||||
msgid "Variable declarations do not accept trailing commas"
|
||||
msgstr "Variablendeklarationen dürfen nicht mit Kommata enden"
|
||||
|
||||
@@ -236,7 +221,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_common.c:106
|
||||
#: ../parser_main.c:333 ../parser_common.c:61
|
||||
#, c-format
|
||||
msgid "Warning from %s (%s%sline %d): %s"
|
||||
msgstr "Warnung aus %s (%s%sZeile %d): %s"
|
||||
@@ -248,7 +233,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:479
|
||||
#: ../parser_main.c:577 ../parser_main.c:616
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: unable to find a suitable fs in %s, is it mounted?\n"
|
||||
@@ -258,7 +243,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:498
|
||||
#: ../parser_main.c:597 ../parser_main.c:635
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Sorry. You need root privileges to run this program.\n"
|
||||
@@ -267,7 +252,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:505
|
||||
#: ../parser_main.c:604 ../parser_main.c:642
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Warning! You've set this program setuid root.\n"
|
||||
@@ -280,7 +265,7 @@ msgstr ""
|
||||
"\n"
|
||||
|
||||
#: ../parser_main.c:704 ../parser_main.c:813 ../parser_main.c:836
|
||||
#: ../parser_main.c:946 ../parser_main.c:860
|
||||
#: ../parser_main.c:946
|
||||
#, c-format
|
||||
msgid "Error: Could not read profile %s: %s.\n"
|
||||
msgstr "Fehler: Profil »%s« konnte nicht gelesen werden: »%s«.\n"
|
||||
@@ -296,33 +281,26 @@ 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:757
|
||||
#: ../parser_main.c:740 ../parser_main.c:872
|
||||
#, 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:761
|
||||
#: ../parser_main.c:744 ../parser_main.c:876
|
||||
#, 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:967
|
||||
#: ../parser_main.c:910 ../parser_main.c:1058
|
||||
#, 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:339
|
||||
#: ../parser_misc.c:426 ../parser_misc.c:597
|
||||
msgid ""
|
||||
"Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
|
||||
"See the apparmor.d(5) manpage for details.\n"
|
||||
@@ -332,17 +310,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:380 ../parser_misc.c:387
|
||||
#: ../parser_misc.c:645
|
||||
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:404
|
||||
#: ../parser_misc.c:491 ../parser_misc.c:662
|
||||
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:415
|
||||
#: ../parser_misc.c:502 ../parser_misc.c:673
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Unconfined exec qualifier (%c%c) allows some dangerous environment variables "
|
||||
@@ -353,7 +331,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:423 ../parser_misc.c:464
|
||||
#: ../parser_misc.c:722
|
||||
#, c-format
|
||||
msgid "Exec qualifier '%c' invalid, conflicting qualifier already specified"
|
||||
msgstr ""
|
||||
@@ -361,7 +339,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:450 ../parser_misc.c:458
|
||||
#: ../parser_misc.c:716
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Exec qualifier '%c%c' invalid, conflicting qualifier already specified"
|
||||
@@ -369,12 +347,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:506
|
||||
#: ../parser_misc.c:593 ../parser_misc.c:764
|
||||
#, 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:528
|
||||
#: ../parser_misc.c:615 ../parser_misc.c:786
|
||||
#, c-format
|
||||
msgid "Internal error generated invalid perm 0x%llx\n"
|
||||
msgstr "Interner Fehler erzeugte ungültige Zugriffsrechte 0x%llx\n"
|
||||
@@ -385,69 +363,68 @@ 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:83
|
||||
#: ../parser_merge.c:92 ../parser_merge.c:91
|
||||
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:105
|
||||
#: ../parser_merge.c:111 ../parser_merge.c:113
|
||||
#, 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:320
|
||||
#: parser_yacc.y:236 parser_yacc.y:277
|
||||
msgid "Profile attachment must begin with a '/'."
|
||||
msgstr "Profilanhang muss mit einem »/« beginnen."
|
||||
|
||||
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348
|
||||
#: parser_yacc.y:260 parser_yacc.y:302
|
||||
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:384
|
||||
#: parser_yacc.y:296 parser_yacc.y:338
|
||||
#, 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:506
|
||||
#: parser_yacc.y:417 parser_yacc.y:460
|
||||
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:510
|
||||
#: parser_yacc.y:421 parser_yacc.y:464
|
||||
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:513
|
||||
#: parser_yacc.y:424 parser_yacc.y:467
|
||||
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:516
|
||||
#: parser_yacc.y:427 parser_yacc.y:470
|
||||
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:530
|
||||
#: parser_yacc.y:441 parser_yacc.y:484
|
||||
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:552
|
||||
#: parser_yacc.y:463 parser_yacc.y:506
|
||||
#, 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:594
|
||||
#: parser_yacc.y:498 parser_yacc.y:520 parser_yacc.y:548
|
||||
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'"
|
||||
@@ -455,81 +432,80 @@ 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:602
|
||||
#: parser_yacc.y:524 parser_yacc.y:556
|
||||
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:633
|
||||
#: parser_yacc.y:549 parser_yacc.y:587
|
||||
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:660
|
||||
#: parser_yacc.y:574 parser_yacc.y:612 parser_yacc.y:614
|
||||
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:786
|
||||
#: parser_yacc.y:649 parser_yacc.y:696
|
||||
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:810
|
||||
#: parser_yacc.y:680 parser_yacc.y:720
|
||||
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:819
|
||||
#: parser_yacc.y:689 parser_yacc.y:729
|
||||
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:992
|
||||
#: parser_yacc.y:824 parser_yacc.y:885
|
||||
#, 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:1092
|
||||
#: parser_yacc.y:882 parser_yacc.y:986
|
||||
msgid "unsafe rule missing exec permissions"
|
||||
msgstr "Fehlende Ausführungsrechte bei unsicherer Regel"
|
||||
|
||||
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060
|
||||
#: parser_yacc.y:901 parser_yacc.y:954
|
||||
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:1062
|
||||
#: parser_yacc.y:903 parser_yacc.y:956
|
||||
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:1064
|
||||
#: parser_yacc.y:905 parser_yacc.y:958
|
||||
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:1109
|
||||
#: parser_yacc.y:921 parser_yacc.y:1003
|
||||
#, 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:1510
|
||||
#: parser_yacc.y:1039 parser_yacc.y:1048 parser_yacc.y:1254
|
||||
#, c-format
|
||||
msgid "Invalid capability %s."
|
||||
msgstr "Ungültige Fähigkeit %s."
|
||||
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525
|
||||
#: parser_yacc.y:1066 parser_yacc.y:1269
|
||||
#, 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:1531
|
||||
#: parser_yacc.y:1072 parser_yacc.y:1275
|
||||
#, c-format
|
||||
msgid "AppArmor parser error,%s%s line %d: %s\n"
|
||||
msgstr "AppArmor-Analysefehler,%s%s Zeile %d: %s\n"
|
||||
@@ -540,13 +516,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:278
|
||||
#: ../parser_regex.c:265 ../parser_regex.c:274
|
||||
#, 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:284
|
||||
#: ../parser_regex.c:271 ../parser_regex.c:280
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close }, no matching open { detected\n"
|
||||
@@ -554,7 +530,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:361
|
||||
#: ../parser_regex.c:337 ../parser_regex.c:343
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Unclosed grouping or character class, expecting "
|
||||
@@ -568,17 +544,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:377
|
||||
#: ../parser_regex.c:355 ../parser_regex.c:361
|
||||
#, 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:421
|
||||
#: ../parser_regex.c:397 ../parser_regex.c:405
|
||||
#, 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:375
|
||||
#: ../parser_policy.c:202 ../parser_policy.c:402
|
||||
#, c-format
|
||||
msgid "ERROR merging rules for profile %s, failed to load\n"
|
||||
msgstr "FEHLER Vereinigungsregeln für Profil »%s«, Laden gescheitert\n"
|
||||
@@ -596,18 +572,18 @@ msgstr ""
|
||||
"erlaubt.\n"
|
||||
"\t»**« kann am Ende einer Regel verwendet werden.\n"
|
||||
|
||||
#: ../parser_policy.c:279 ../parser_policy.c:359 ../parser_policy.c:332
|
||||
#: ../parser_policy.c:279 ../parser_policy.c:359
|
||||
#, 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:362
|
||||
#: ../parser_policy.c:306 ../parser_policy.c:389
|
||||
#, 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:355
|
||||
#: ../parser_policy.c:390 ../parser_policy.c:382
|
||||
#, c-format
|
||||
msgid "ERROR adding hat access rule for profile %s\n"
|
||||
msgstr "FEHLER Hinzufügen von »hat«-Zugriffsregel für Profil %s\n"
|
||||
@@ -641,32 +617,31 @@ msgstr ""
|
||||
"%s: Beim Kombinieren von Regeln in der Nachverarbeitung sind Fehler "
|
||||
"aufgetreten. Der Vorgang wird abgebrochen.\n"
|
||||
|
||||
#: parser_lex.l:180 parser_lex.l:186
|
||||
#: parser_lex.l:180
|
||||
#, 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:523
|
||||
#: ../parser_main.c:660
|
||||
msgid "Feature buffer full."
|
||||
msgstr "Funktionspuffer ist voll."
|
||||
|
||||
#: ../parser_main.c:1115 ../parser_main.c:1132 ../parser_main.c:1024
|
||||
#: ../parser_main.c:1041
|
||||
#: ../parser_main.c:1115 ../parser_main.c:1132
|
||||
msgid "Out of memory"
|
||||
msgstr "Nicht genügend Speicher!"
|
||||
msgstr "Nicht genug Speicher"
|
||||
|
||||
#: ../parser_main.c:1182 ../parser_main.c:1091
|
||||
#: ../parser_main.c:1182
|
||||
#, 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:1094
|
||||
#: ../parser_main.c:1185
|
||||
#, c-format
|
||||
msgid "File in cache directory location: %s\n"
|
||||
msgstr "Datei im Pufferverzeichnisort: %s\n"
|
||||
|
||||
#: ../parser_main.c:1188 ../parser_main.c:1097
|
||||
#: ../parser_main.c:1188
|
||||
#, c-format
|
||||
msgid "Can't update cache directory: %s\n"
|
||||
msgstr "Pufferverzeichnis kann nicht aktualisiert werden: %s\n"
|
||||
@@ -681,11 +656,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:621
|
||||
#: parser_yacc.y:575
|
||||
msgid "deny prefix not allowed"
|
||||
msgstr "Verweigernpräfix nicht erlaubt"
|
||||
|
||||
#: parser_yacc.y:612 parser_yacc.y:658
|
||||
#: parser_yacc.y:612
|
||||
msgid "owner prefix not allowed"
|
||||
msgstr "Eigentümerpräfix nicht erlaubt"
|
||||
|
||||
@@ -701,25 +676,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:1613
|
||||
#: parser_yacc.y:1357
|
||||
#, c-format
|
||||
msgid "invalid mount conditional %s%s"
|
||||
msgstr "Ungültige Einhängebedingung %s%s"
|
||||
|
||||
#: parser_yacc.y:1374 parser_yacc.y:1628
|
||||
#: parser_yacc.y:1374
|
||||
msgid "bad mount rule"
|
||||
msgstr "Ungültige Einhängeregel"
|
||||
|
||||
#: parser_yacc.y:1381 parser_yacc.y:1635
|
||||
#: parser_yacc.y:1381
|
||||
msgid "mount point conditions not currently supported"
|
||||
msgstr "Einhängepunktbedingungen werden derzeit nicht unterstützt"
|
||||
|
||||
#: parser_yacc.y:1398 parser_yacc.y:1650
|
||||
#: parser_yacc.y:1398
|
||||
#, c-format
|
||||
msgid "invalid pivotroot conditional '%s'"
|
||||
msgstr "Ungültige pivotroot-Bedingung »%s«"
|
||||
|
||||
#: ../parser_regex.c:241 ../parser_regex.c:236
|
||||
#: ../parser_regex.c:241
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s: Regex grouping error: Invalid close ], no matching open [ detected\n"
|
||||
@@ -727,20 +702,20 @@ msgstr ""
|
||||
"%s: Regex-Gruppierungsfehler: Ungültiges schließendes Zeichen ], kein "
|
||||
"passendes öffnendes Zeichen [ gefunden\n"
|
||||
|
||||
#: ../parser_regex.c:257 ../parser_regex.c:256
|
||||
#: ../parser_regex.c:257
|
||||
#, 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:339
|
||||
#: ../parser_policy.c:366
|
||||
#, 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:369
|
||||
#: ../parser_policy.c:396
|
||||
#, c-format
|
||||
msgid "ERROR replacing aliases for profile %s, failed to load\n"
|
||||
msgstr ""
|
||||
|
@@ -95,15 +95,13 @@ void update_mru_tstamp(FILE *file, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
char *cache_filename(aa_policy_cache *pc, int dir, const char *basename)
|
||||
char *cache_filename(const char *cachedir, const char *basename)
|
||||
{
|
||||
char *cachename;
|
||||
autofree char *path;
|
||||
|
||||
path = aa_policy_cache_dir_path(pc, dir);
|
||||
if (!path || asprintf(&cachename, "%s/%s", path, basename) < 0) {
|
||||
if (asprintf(&cachename, "%s/%s", cachedir, basename) < 0) {
|
||||
PERROR("Memory allocation error.");
|
||||
return NULL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return cachename;
|
||||
|
@@ -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(aa_policy_cache *pc, int dir, const char *basename);
|
||||
char *cache_filename(const char *cachedir, 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,19 +117,13 @@ skip_profile() {
|
||||
"${profile%\~}" != "${profile}" ] ; then
|
||||
return 1
|
||||
fi
|
||||
# Silently ignore the dpkg, pacman, and xbps files
|
||||
# Silently ignore the dpkg files
|
||||
if [ "${profile%.dpkg-new}" != "${profile}" -o \
|
||||
"${profile%.dpkg-old}" != "${profile}" -o \
|
||||
"${profile%.dpkg-dist}" != "${profile}" -o \
|
||||
"${profile%.dpkg-bak}" != "${profile}" -o \
|
||||
"${profile%.dpkg-remove}" != "${profile}" -o \
|
||||
"${profile%.pacsave}" != "${profile}" -o \
|
||||
"${profile%.pacnew}" != "${profile}" ] ; then
|
||||
"${profile%.dpkg-bak}" != "${profile}" ] ; then
|
||||
return 2
|
||||
fi
|
||||
if echo "${profile}" | egrep -q '^.+\.new-[0-9\.]+_[0-9]+$'; then
|
||||
return 2 ;;
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
149
parser/rc.apparmor.suse
Normal file
149
parser/rc.apparmor.suse
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/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
|
||||
|
@@ -4,8 +4,6 @@ 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)
|
||||
@@ -32,14 +30,14 @@ gen_dbus: $(GEN_TRANS_DIRS)
|
||||
./gen-dbus.pl
|
||||
|
||||
error_output: $(PARSER)
|
||||
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 | \
|
||||
LANG=C $(PARSER) -S -I errors >/dev/null errors/okay.sd
|
||||
LANG=C $(PARSER) -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) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/double.sd | \
|
||||
LANG=C $(PARSER) -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) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/modefail.sd | \
|
||||
LANG=C $(PARSER) -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) $(PARSER_ARGS) -S -I errors 2>&1 >/dev/null errors/multi_include.sd | \
|
||||
LANG=C $(PARSER) -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"
|
||||
|
||||
@@ -50,13 +48,13 @@ caching: $(PARSER)
|
||||
LANG=C ./caching.py -p "$(PARSER)" $(PYTEST_ARG)
|
||||
|
||||
minimize: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./minimize.sh
|
||||
LANG=C APPARMOR_PARSER="$(PARSER)" ./minimize.sh
|
||||
|
||||
equality: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./equality.sh
|
||||
LANG=C APPARMOR_PARSER="$(PARSER)" ./equality.sh
|
||||
|
||||
valgrind: $(PARSER) gen_xtrans gen_dbus
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER) $(PARSER_ARGS)" -v simple_tests
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER)" -v simple_tests
|
||||
|
||||
$(PARSER):
|
||||
$(MAKE) -C $(PARSER_DIR) $(PARSER_BIN)
|
||||
|
@@ -60,6 +60,13 @@ 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)
|
||||
@@ -68,26 +75,11 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
||||
self.do_cleanup = False
|
||||
self.debug = True
|
||||
|
||||
# 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']
|
||||
self.cmd_prefix = [config.parser, '--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'''
|
||||
|
||||
@@ -97,22 +89,6 @@ 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),
|
||||
@@ -202,16 +178,16 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
|
||||
def setUp(self):
|
||||
super(AAParserAltCacheBasicTests, self).setUp()
|
||||
|
||||
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
alt_cache_dir = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_dir, 0o755)
|
||||
|
||||
self.unused_cache_loc = self.cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir()
|
||||
self.unused_cache_dir = self.cache_dir
|
||||
self.cache_dir = alt_cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_dir])
|
||||
|
||||
def tearDown(self):
|
||||
if len(os.listdir(self.unused_cache_loc)) > 0:
|
||||
self.fail('original cache dir \'%s\' not empty' % self.unused_cache_loc)
|
||||
if len(os.listdir(self.unused_cache_dir)) > 0:
|
||||
self.fail('original cache dir \'%s\' not empty' % self.unused_cache_dir)
|
||||
super(AAParserAltCacheBasicTests, self).tearDown()
|
||||
|
||||
|
||||
@@ -338,22 +314,18 @@ 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_collision_of_features(self):
|
||||
'''test cache writing collision of features'''
|
||||
# cache dir with different features causes a collision resulting
|
||||
# in a new cache dir
|
||||
def test_cache_writing_updates_features(self):
|
||||
'''test cache writing updates features'''
|
||||
|
||||
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.assert_path_exists(new_features_file)
|
||||
self.compare_features_file(new_features_file)
|
||||
self.compare_features_file(features_file)
|
||||
|
||||
def test_cache_writing_updates_cache_file(self):
|
||||
'''test cache writing updates cache file'''
|
||||
@@ -522,13 +494,13 @@ class AAParserAltCacheTests(AAParserCachingTests):
|
||||
def setUp(self):
|
||||
super(AAParserAltCacheTests, self).setUp()
|
||||
|
||||
alt_cache_loc = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_loc, 0o755)
|
||||
alt_cache_dir = tempfile.mkdtemp(prefix='aa-alt-cache', dir=self.tmp_dir)
|
||||
os.chmod(alt_cache_dir, 0o755)
|
||||
|
||||
self.orig_cache_dir = self.cache_dir
|
||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_loc])
|
||||
self.cache_dir = self.get_cache_dir(create=True)
|
||||
self.cache_dir = alt_cache_dir
|
||||
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:
|
||||
|
@@ -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'}", "--config-file=./parser.conf", "-M", "features_files/features.all", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
|
||||
exec("$config{'parser'}", "-M", "features_files/features.all", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
|
||||
# noreturn
|
||||
}
|
||||
|
||||
|
@@ -93,7 +93,7 @@ check-parser: local
|
||||
@echo "*** Checking profiles from ${PROFILES_SOURCE} and ${EXTRAS_SOURCE} against apparmor_parser"
|
||||
$(Q)for profile in ${CHECK_PROFILES} ; do \
|
||||
[ -n "${VERBOSE}" ] && echo "Testing $${profile}" ; \
|
||||
${PARSER} --config-file=../parser/tst/parser.conf -S -b ${PWD}/apparmor.d $${profile} > /dev/null || exit 1; \
|
||||
${PARSER} -S -b ${PWD}/apparmor.d $${profile} > /dev/null || exit 1; \
|
||||
done
|
||||
|
||||
.PHONY: check-logprof
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
#include <abstractions/dri-common>
|
||||
|
||||
|
||||
# .ICEauthority files required for X authentication, per user
|
||||
@@ -46,6 +45,14 @@
|
||||
# EGL
|
||||
/usr/lib/@{multiarch}/egl/*.so* mr,
|
||||
|
||||
# DRI
|
||||
/usr/lib{,32,64}/dri/** mr,
|
||||
/usr/lib/@{multiarch}/dri/** mr,
|
||||
/usr/lib/fglrx/dri/** mr,
|
||||
/dev/dri/** rw,
|
||||
/etc/drirc r,
|
||||
owner @{HOME}/.drirc r,
|
||||
|
||||
# Xcompose
|
||||
owner @{HOME}/.XCompose r,
|
||||
|
||||
|
@@ -1,12 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
|
||||
# This file contains common DRI-specific rules useful for GUI applications
|
||||
# (needed by libdrm and similar).
|
||||
|
||||
/usr/lib{,32,64}/dri/** mr,
|
||||
/usr/lib/@{multiarch}/dri/** mr,
|
||||
/usr/lib/fglrx/dri/** mr,
|
||||
/dev/dri/** rw,
|
||||
/etc/drirc r,
|
||||
owner @{HOME}/.drirc r,
|
||||
|
@@ -1,9 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
|
||||
# This file contains common DRI-specific rules useful for GUI applications that
|
||||
# needs to enumerate graphic devices (as with drmParsePciDeviceInfo() from
|
||||
# libdrm).
|
||||
|
||||
# TODO: use @{sys} after it's moved into tunables/kernelvars (LP: #1728551)
|
||||
/sys/devices/pci[0-9]*/**/{device,subsystem_device,subsystem_vendor,uevent,vendor} r,
|
||||
|
@@ -10,12 +10,21 @@
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# system configuration
|
||||
@{system_share_dirs}/applications/{**,} r,
|
||||
@{system_share_dirs}/icons/{**,} r,
|
||||
@{system_share_dirs}/pixmaps/{**,} r,
|
||||
/usr/{,local/}share/applications/{*/,} r,
|
||||
/usr/{,local/}share/applications/{*/,}defaults.list r,
|
||||
/usr/{,local/}share/applications/{*/,}mimeinfo.cache r,
|
||||
/usr/{,local/}share/applications/{*/,}*.desktop r,
|
||||
/usr/share/icons/ r,
|
||||
/usr/share/icons/** r,
|
||||
/usr/share/pixmaps/ r,
|
||||
/usr/share/pixmaps/** r,
|
||||
/usr/local/share/icons/ r,
|
||||
/usr/local/share/icons/** r,
|
||||
/usr/local/share/pixmaps/ r,
|
||||
/usr/local/share/pixmaps/** r,
|
||||
|
||||
# this should probably go elsewhere
|
||||
@{system_share_dirs}/mime/** r,
|
||||
/usr/share/mime/** r,
|
||||
|
||||
# per-user configurations
|
||||
owner @{HOME}/.icons/ r,
|
||||
@@ -23,6 +32,12 @@
|
||||
owner @{HOME}/.local/share/recently-used.xbel* rw,
|
||||
owner @{HOME}/.config/user-dirs.dirs r,
|
||||
owner @{HOME}/.config/mimeapps.list r,
|
||||
owner @{user_share_dirs}/applications/{**,} r,
|
||||
owner @{user_share_dirs}/icons/{**,} r,
|
||||
owner @{user_share_dirs}/mime/{**,} r,
|
||||
owner @{HOME}/.local/share/applications/ r,
|
||||
owner @{HOME}/.local/share/applications/*.desktop r,
|
||||
owner @{HOME}/.local/share/applications/defaults.list r,
|
||||
owner @{HOME}/.local/share/applications/mimeapps.list r,
|
||||
owner @{HOME}/.local/share/applications/mimeinfo.cache r,
|
||||
owner @{HOME}/.local/share/icons/ r,
|
||||
owner @{HOME}/.local/share/icons/** r,
|
||||
owner @{HOME}/.local/share/mime/ r,
|
||||
owner @{HOME}/.local/share/mime/** r,
|
||||
|
@@ -33,6 +33,8 @@ owner @{HOME}/.kde{,4}/share/config/*.lock rwl,
|
||||
owner @{HOME}/.qt/** rw,
|
||||
owner @{HOME}/.config/Trolltech.conf rwk,
|
||||
|
||||
/usr/share/icons/ r,
|
||||
/usr/share/icons/** r,
|
||||
/usr/share/X11/XKeysymDB r,
|
||||
|
||||
# kde3
|
||||
|
@@ -1,10 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# Rules for changing KDE settings (for KFileDialog and other).
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.config/#[0-9]* rw,
|
||||
owner @{HOME}/.config/kdeglobals rw,
|
||||
owner @{HOME}/.config/kdeglobals.?????? rwl -> @{HOME}/.config/#[0-9]*,
|
||||
owner @{HOME}/.config/kdeglobals.lock rwk,
|
||||
|
@@ -1,7 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# Rules for writing KDE icon cache
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.cache/icon-cache.kcache rw, # for KIconLoader
|
||||
|
@@ -1,12 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# Rules for changing per-application language settings on KDE. Some KDE
|
||||
# applications have "Help -> Switch Application Language..." option, that needs
|
||||
# write access to language settings file.
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.config/#[0-9]* rw,
|
||||
owner @{HOME}/.config/klanguageoverridesrc rw,
|
||||
owner @{HOME}/.config/klanguageoverridesrc.?????? rwl -> @{HOME}/.config/#[0-9]*,
|
||||
owner @{HOME}/.config/klanguageoverridesrc.lock rwk,
|
||||
|
@@ -1,13 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# Rules for Mesa implementation of the OpenGL API
|
||||
|
||||
# System files
|
||||
/dev/dri/ r, # libGLX_mesa.so calls drmGetDevice2()
|
||||
|
||||
# User files
|
||||
owner @{HOME}/.cache/ w, # if user clears all caches
|
||||
owner @{HOME}/.cache/mesa_shader_cache/ w,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/index rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/??/ w,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/??/* rwk,
|
||||
|
@@ -17,8 +17,6 @@
|
||||
@{PROC}/driver/nvidia/params r,
|
||||
@{PROC}/modules r,
|
||||
|
||||
/sys/devices/system/memory/block_size_bytes r,
|
||||
|
||||
owner @{HOME}/.nv/ w,
|
||||
owner @{HOME}/.nv/GLCache/ rw,
|
||||
owner @{HOME}/.nv/GLCache/** rwk,
|
||||
|
@@ -1,9 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# OpenCL access requirements
|
||||
|
||||
# TODO: use conditionals to select allowed implementations
|
||||
#include <abstractions/opencl-intel>
|
||||
#include <abstractions/opencl-mesa>
|
||||
#include <abstractions/opencl-nvidia>
|
||||
#include <abstractions/opencl-pocl>
|
||||
|
@@ -1,10 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# implementation-independent OpenCL access requirements
|
||||
|
||||
# System files
|
||||
|
||||
/etc/OpenCL/** r,
|
||||
/sys/bus/pci/devices/ r, # libpocl.so -> libhwlock.so, libnvidia-opencl.so, beignet/libcl.so -> libdrm_intel.so
|
||||
/sys/devices/system/node/ r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
/sys/devices/system/node/node[0-9]*/meminfo r, # for clGetPlatformIDs() from libOpenCL.so
|
||||
|
@@ -1,17 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# OpenCL access requirements for Intel implementation
|
||||
|
||||
#include <abstractions/opencl-common>
|
||||
|
||||
# for libcl.so (libOpenCL.so -> beignet/libcl.so calls XOpenDisplay())
|
||||
#include <abstractions/X>
|
||||
|
||||
# for libOpenCL.so -> beignet/libcl.so -> libpciaccess.so
|
||||
#include <abstractions/dri-enumerate>
|
||||
|
||||
# System files
|
||||
|
||||
/dev/dri/card[0-9]* rw, # beignet/libcl.so
|
||||
/sys/devices/pci[0-9]*/**/{class,config,resource,revision} r, # libcl.so -> libdrm_intel.so -> libpciaccess.so (move to dri-enumerate ?)
|
||||
/usr/lib/@{multiarch}/beignet/** r,
|
||||
|
@@ -1,20 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# OpenCL access requirements for Mesa implementation
|
||||
|
||||
#include <abstractions/opencl-common>
|
||||
|
||||
# Additional libraries
|
||||
|
||||
/usr/lib/@{multiarch}/gallium-pipe/*.so mr, # libMesaOpenCL.so
|
||||
/usr/lib{,64}/gallium-pipe/*.so mr, # libMesaOpenCL.so on openSUSE
|
||||
|
||||
# System files
|
||||
|
||||
/dev/dri/ r, # libMesaOpenCL.so -> libdrm.so
|
||||
/dev/dri/render* rw, # libMesaOpenCL.so
|
||||
/etc/drirc r, # libMesaOpenCL.so
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.cache/mesa_shader_cache/{,**} rw, # libMesaOpenCL.so -> pipe_nouveau.so
|
||||
|
@@ -1,30 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# OpenCL access requirements for NVIDIA implementation
|
||||
|
||||
#include <abstractions/nvidia>
|
||||
#include <abstractions/opencl-common>
|
||||
|
||||
# Executables
|
||||
|
||||
# https://github.com/NVIDIA/nvidia-modprobe
|
||||
# This setuid executable is used to create various device files and load the
|
||||
# the nvidia kernel module.
|
||||
/usr/bin/nvidia-modprobe Px -> nvidia_modprobe,
|
||||
|
||||
# System files
|
||||
|
||||
# libnvidia-opencl.so rules:
|
||||
/dev/nvidia-uvm rw,
|
||||
/dev/nvidia-uvm-tools rw,
|
||||
/sys/devices/pci[0-9]*/**/config r,
|
||||
/sys/devices/system/memory/block_size_bytes r,
|
||||
/usr/share/nvidia/** r,
|
||||
@{PROC}/devices r,
|
||||
@{PROC}/sys/vm/mmap_min_addr r,
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.nv/ComputeCache/ w,
|
||||
owner @{HOME}/.nv/ComputeCache/** rw,
|
||||
owner @{HOME}/.nv/ComputeCache/index rwk,
|
||||
|
@@ -1,76 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# OpenCL access requirements for POCL implementation
|
||||
|
||||
#include <abstractions/opencl-common>
|
||||
|
||||
# Executables
|
||||
|
||||
/usr/bin/{,@{multiarch}-}ld.bfd Cx -> opencl_pocl_ld,
|
||||
/usr/lib/llvm-[0-9]*.[0-9]*/bin/clang Cx -> opencl_pocl_clang,
|
||||
|
||||
# System files
|
||||
|
||||
/ r, # libpocl.so -> libhwloc.so
|
||||
/sys/bus/pci/slots/ r, # libpocl.so -> hwloc_topology_load() from libhwloc.so
|
||||
/sys/bus/{cpu,node}/devices/ r, # libpocl.so -> libhwlock.so
|
||||
/sys/class/net/ r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/ r, # for libpocl -> hwloc_linux_lookup_block_class() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/block/*/dev r, # libpocl.so -> hwloc_linux_lookup_host_block_class() from libhwloc.so
|
||||
/sys/devices/pci[0-9]*/**/{class,local_cpus} r, # libpocl.so -> libhwlock.so
|
||||
/sys/devices/pci[0-9]*/*/net/*/address r, # libpocl.so -> hwloc_pci_traverse_lookuposdevices_cb() from libhwloc.so
|
||||
/sys/devices/system/cpu/ r, # libpocl.so -> libnuma.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/cache/index[0-9]*/* r, # libpocl.so -> libhwloc.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/online r, # libpocl.so -> libhwlock.so
|
||||
/sys/devices/system/cpu/cpu[0-9]*/topology/* r, # *_siblings, physical_package_id and lot's of others, for libpocl.so -> libhwloc.so
|
||||
/sys/devices/system/cpu/cpufreq/policy[0-9]*/* r, # for clGetPlatformIDs() from libpocl.so
|
||||
/sys/devices/system/cpu/possible r, # libpocl.so -> libhwloc.so
|
||||
/sys/devices/virtual/dmi/id/{,*} r, # libpocl.so -> libhwloc.so
|
||||
/sys/fs/cgroup/cpuset/cpuset.{cpus,mems} r, # libpocl.so -> libhwloc.so
|
||||
/sys/kernel/mm/hugepages{/,/**} r, # libpocl.so -> libhwloc.so
|
||||
/usr/share/pocl/** r,
|
||||
/{,var/}run/udev/data/*:* r, # libpocl.so -> hwloc_linux_block_class_fillinfos() from libhwloc.so
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.cache/pocl/ w,
|
||||
owner @{HOME}/.cache/pocl/kcache/ w,
|
||||
owner @{HOME}/.cache/pocl/kcache/** rw,
|
||||
owner @{HOME}/.cache/pocl/kcache/**.so mrw, # dangerous!
|
||||
owner @{PROC}/@{pid}/{cgroup,cpuset,status} r, # libpocl.so -> libhwloc.so, status for libpocl.so -> libnuma.so
|
||||
|
||||
# Child profiles
|
||||
|
||||
profile opencl_pocl_ld {
|
||||
#include <abstractions/base>
|
||||
|
||||
# Main executables
|
||||
|
||||
/usr/bin/{,@{multiarch}-}ld.bfd mr,
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.cache/pocl/kcache/tempfile*.so rw,
|
||||
owner @{HOME}/.cache/pocl/kcache/**.so.o r,
|
||||
}
|
||||
|
||||
profile opencl_pocl_clang {
|
||||
#include <abstractions/base>
|
||||
|
||||
# Main executables
|
||||
|
||||
/usr/lib/llvm-[0-9]*.[0-9]*/bin/clang mr,
|
||||
|
||||
# Additional executables
|
||||
|
||||
/usr/bin/{,@{multiarch}-}ld.bfd ix, # TODO: transfer to opencl_ld child profile?
|
||||
|
||||
# System files
|
||||
|
||||
/etc/debian-version r,
|
||||
/etc/lsb-release r,
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.cache/pocl/kcache/*/*/*/*/*.so{,.o} rw,
|
||||
}
|
||||
|
@@ -1,10 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
# Allow updating recent documents
|
||||
|
||||
# User files
|
||||
|
||||
owner @{HOME}/.local/share/RecentDocuments/ rw,
|
||||
owner @{HOME}/.local/share/RecentDocuments/#[0-9]* rw,
|
||||
owner @{HOME}/.local/share/RecentDocuments/*.desktop rwl -> @{HOME}/.local/share/RecentDocuments/#[0-9]*,
|
||||
owner @{HOME}/.local/share/RecentDocuments/*.lock rwk,
|
||||
|
@@ -1,63 +0,0 @@
|
||||
# vim:syntax=apparmor
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
profile nvidia_modprobe {
|
||||
#include <abstractions/base>
|
||||
|
||||
# Capabilities
|
||||
|
||||
capability chown,
|
||||
capability mknod,
|
||||
capability setuid,
|
||||
capability sys_admin,
|
||||
|
||||
# Main executable
|
||||
|
||||
/usr/bin/nvidia-modprobe mr,
|
||||
|
||||
# Other executables
|
||||
|
||||
/usr/bin/kmod Cx -> kmod,
|
||||
|
||||
# System files
|
||||
|
||||
/dev/nvidia-uvm w,
|
||||
/dev/nvidia-uvm-tools w,
|
||||
/sys/bus/pci/devices/ r,
|
||||
/sys/devices/pci[0-9]*/**/config r,
|
||||
@{PROC}/devices r,
|
||||
@{PROC}/modules r,
|
||||
@{PROC}/sys/kernel/modprobe r,
|
||||
|
||||
# Child profiles
|
||||
|
||||
profile kmod {
|
||||
#include <abstractions/base>
|
||||
|
||||
# Capabilities
|
||||
|
||||
capability sys_module,
|
||||
|
||||
# Main executable
|
||||
|
||||
/usr/bin/kmod mrix,
|
||||
|
||||
# Other executables
|
||||
|
||||
/{,usr/}bin/{,ba,da}sh ix,
|
||||
|
||||
# System files
|
||||
|
||||
/etc/modprobe.d/{,*.conf} r,
|
||||
/etc/nvidia/current/*.conf r,
|
||||
/sys/module/ipmi_devintf/initstate r,
|
||||
/sys/module/ipmi_msghandler/initstate r,
|
||||
/sys/module/nvidia/initstate r,
|
||||
@{PROC}/cmdline r,
|
||||
}
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
#include <local/nvidia_modprobe>
|
||||
}
|
||||
|
@@ -18,4 +18,3 @@
|
||||
#include <tunables/alias>
|
||||
#include <tunables/kernelvars>
|
||||
#include <tunables/xdg-user-dirs>
|
||||
#include <tunables/share>
|
||||
|
@@ -1,15 +0,0 @@
|
||||
@{flatpak_exports_root} = flatpak/exports flatpak/{app,runtime}/*/*/*/*/export
|
||||
|
||||
# System-wide directories with behaviour analogous to /usr/share
|
||||
# in patterns like the freedesktop.org basedir spec. These are
|
||||
# owned by root or a system user, appear in XDG_DATA_DIRS, and
|
||||
# are the parent directory for `applications`, `themes`,
|
||||
# `dbus-1/services`, etc.
|
||||
@{system_share_dirs} = /usr/share /usr/local/share /var/lib/@{flatpak_exports_root}/share
|
||||
|
||||
# Per-user/personal directories with behaviour analogous to
|
||||
# ~/.local/share in patterns like the freedesktop.org basedir spec.
|
||||
# These are owned by the user running an application, appear in
|
||||
# XDG_DATA_DIRS or XDG_DATA_HOME, and are the parent directory
|
||||
# for the same subdirectories as @{system_share_dirs}
|
||||
@{user_share_dirs} = @{HOME}/.local/share @{HOME}/.local/share/@{flatpak_exports_root}/share
|
@@ -31,7 +31,6 @@
|
||||
/usr/lib/dovecot/dovecot-lda mrix,
|
||||
/usr/{bin,sbin}/sendmail Cx,
|
||||
/usr/share/dovecot/protocols.d/ r,
|
||||
/usr/share/dovecot/protocols.d/** r,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
#include <local/usr.lib.dovecot.dovecot-lda>
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include <abstractions/ssl_keys>
|
||||
|
||||
capability dac_override,
|
||||
capability dac_read_search,
|
||||
capability setuid,
|
||||
|
||||
@{DOVECOT_MAILSTORE}/ rw,
|
||||
|
@@ -25,7 +25,6 @@
|
||||
/var/spool/mlmmj/*/subscribers.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/digesters.d/ r,
|
||||
/var/spool/mlmmj/*/digesters.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/moderation/* rwk,
|
||||
|
||||
|
@@ -66,7 +66,7 @@
|
||||
|
||||
capability audit_write,
|
||||
|
||||
/{,usr/}sbin/pam_tally2 mr,
|
||||
/sbin/pam_tally2 mr,
|
||||
/var/log/tallylog rw,
|
||||
|
||||
}
|
||||
|
@@ -247,7 +247,7 @@ sub readconf {
|
||||
s/\s+$//; # no trailing white
|
||||
next unless length; # anything left?
|
||||
my ($var, $value) = split(/\s*=\s*/, $_, 2);
|
||||
if ($var eq "show_notifications" or $var eq "use_group" or $var eq "message_body" or $var eq "message_title" or $var eq "message_footer") {
|
||||
if ($var eq "show_notifications" or $var eq "use_group") {
|
||||
$value =~ s/^"(.*)"$/$1/g;
|
||||
$prefs{$var} = $value;
|
||||
}
|
||||
@@ -298,16 +298,12 @@ sub format_message {
|
||||
my ($profile, $operation, $name, $denied, $family, $sock_type, $date) = @_;
|
||||
|
||||
my $formatted = "";
|
||||
if (defined($prefs{message_body})) {
|
||||
$formatted .= $prefs{message_body};
|
||||
} else {
|
||||
defined($profile) and $formatted .= "Profile: $profile\n";
|
||||
defined($operation) and $formatted .= "Operation: $operation\n";
|
||||
defined($name) and $formatted .= "Name: $name\n";
|
||||
defined($denied) and $formatted .= "Denied: $denied\n";
|
||||
defined($family) and defined ($sock_type) and $formatted .= "Family: $family\nSocket type: $sock_type\n";
|
||||
$formatted .= "Logfile: $logfile\n";
|
||||
}
|
||||
defined($profile) and $formatted .= "Profile: $profile\n";
|
||||
defined($operation) and $formatted .= "Operation: $operation\n";
|
||||
defined($name) and $formatted .= "Name: $name\n";
|
||||
defined($denied) and $formatted .= "Denied: $denied\n";
|
||||
defined($family) and defined ($sock_type) and $formatted .= "Family: $family\nSocket type: $sock_type\n";
|
||||
$formatted .= "Logfile: $logfile\n";
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
@@ -403,7 +399,7 @@ sub do_notify {
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $footer = exists $prefs{message_footer} ? $prefs{message_footer} : "For more information, please see:\n$url";
|
||||
my $footer = "For more information, please see:\n$url";
|
||||
my $first_run = 1;
|
||||
my $since = $now;
|
||||
if ($opt_s and int($opt_s) > 0) {
|
||||
|
@@ -92,12 +92,6 @@ System-wide configuration for B<aa-notify> is done via
|
||||
# only people in use_group can use aa-notify
|
||||
use_group="admin"
|
||||
|
||||
# OPTIONAL - custom notification message body
|
||||
message_body="This is a custom notification message."
|
||||
|
||||
# OPTIONAL - custom notification message footer
|
||||
message_footer="For more information visit https://foo.com"
|
||||
|
||||
Per-user configuration is done via ~/.apparmor/notify.conf:
|
||||
|
||||
# set to 'yes' to enable AppArmor DENIED notifications
|
||||
|
@@ -103,7 +103,7 @@ extras = hasher() # Inactive profiles from extras
|
||||
### end our
|
||||
log_pid = dict() # handed over to ReadLog, gets filled in logparser.py. The only case the previous content of this variable _might_(?) be used is aa-genprof (multiple do_logprof_pass() runs)
|
||||
|
||||
profile_changes = dict()
|
||||
profile_changes = hasher()
|
||||
prelog = hasher()
|
||||
changed = dict()
|
||||
created = []
|
||||
@@ -709,7 +709,7 @@ def sync_profile():
|
||||
repo_profiles = []
|
||||
changed_profiles = []
|
||||
new_profiles = []
|
||||
serialize_opts = dict()
|
||||
serialize_opts = hasher()
|
||||
status_ok, ret = fetch_profiles_by_user(cfg['repository']['url'],
|
||||
cfg['repository']['distro'], user)
|
||||
if not status_ok:
|
||||
@@ -796,7 +796,7 @@ def upload_profile(url, user, passw, distro, p, profile_string, changelog):
|
||||
|
||||
def console_select_and_upload_profiles(title, message, profiles_up):
|
||||
url = cfg['repository']['url']
|
||||
profiles = profiles_up[:]
|
||||
profs = profiles_up[:]
|
||||
q = aaui.PromptQuestion()
|
||||
q.title = title
|
||||
q.headers = ['Repository', url]
|
||||
@@ -804,20 +804,20 @@ def console_select_and_upload_profiles(title, message, profiles_up):
|
||||
q.functions = ['CMD_UPLOAD_CHANGES', 'CMD_VIEW_CHANGES', 'CMD_ASK_LATER',
|
||||
'CMD_ASK_NEVER', 'CMD_ABORT']
|
||||
q.default = 'CMD_VIEW_CHANGES'
|
||||
q.options = [i[0] for i in profiles]
|
||||
q.options = [i[0] for i in profs]
|
||||
q.selected = 0
|
||||
ans = ''
|
||||
while 'CMD_UPLOAD_CHANGES' not in ans and 'CMD_ASK_NEVER' not in ans and 'CMD_ASK_LATER' not in ans:
|
||||
ans, arg = q.promptUser()
|
||||
if ans == 'CMD_VIEW_CHANGES':
|
||||
aaui.UI_Changes(profiles[arg][2], profiles[arg][1])
|
||||
aaui.UI_Changes(profs[arg][2], profs[arg][1])
|
||||
if ans == 'CMD_NEVER_ASK':
|
||||
set_profiles_local_only([i[0] for i in profiles])
|
||||
set_profiles_local_only([i[0] for i in profs])
|
||||
elif ans == 'CMD_UPLOAD_CHANGES':
|
||||
changelog = aaui.UI_GetString(_('Changelog Entry: '), '')
|
||||
user, passw = get_repo_user_pass()
|
||||
if user and passw:
|
||||
for p_data in profiles:
|
||||
for p_data in profs:
|
||||
prof = p_data[0]
|
||||
prof_string = p_data[1]
|
||||
status_ok, ret = upload_profile(url, user, passw,
|
||||
@@ -836,10 +836,10 @@ def console_select_and_upload_profiles(title, message, profiles_up):
|
||||
else:
|
||||
aaui.UI_Important(_('Repository Error\nRegistration or Signin was unsuccessful. User login\ninformation is required to upload profiles to the repository.\nThese changes could not be sent.'))
|
||||
|
||||
def set_profiles_local_only(profiles):
|
||||
for p in profiles:
|
||||
aa[profiles][profiles]['repo']['neversubmit'] = True
|
||||
write_profile_ui_feedback(profiles)
|
||||
def set_profiles_local_only(profs):
|
||||
for p in profs:
|
||||
aa[profs][profs]['repo']['neversubmit'] = True
|
||||
write_profile_ui_feedback(profs)
|
||||
|
||||
|
||||
def build_x_functions(default, options, exec_toggle):
|
||||
@@ -2019,7 +2019,7 @@ def is_skippable_file(path):
|
||||
if not basename or basename[0] == '.' or basename == 'README':
|
||||
return True
|
||||
|
||||
skippable_suffix = ('.dpkg-new', '.dpkg-old', '.dpkg-dist', '.dpkg-bak', '.dpkg-remove', '.pacsave', '.pacnew', '.rpmnew', '.rpmsave', '.orig', '.rej', '~')
|
||||
skippable_suffix = ('.dpkg-new', '.dpkg-old', '.dpkg-dist', '.dpkg-bak', '.rpmnew', '.rpmsave', '.orig', '.rej', '~')
|
||||
if basename.endswith(skippable_suffix):
|
||||
return True
|
||||
|
||||
@@ -2599,6 +2599,26 @@ def write_header(prof_data, depth, name, embedded_hat, write_flags):
|
||||
|
||||
return data
|
||||
|
||||
def write_single(prof_data, depth, allow, name, prefix, tail):
|
||||
pre = ' ' * depth
|
||||
data = []
|
||||
ref, allow = set_ref_allow(prof_data, allow)
|
||||
|
||||
if ref.get(name, False):
|
||||
for key in sorted(ref[name].keys()):
|
||||
if name == 'include':
|
||||
if key.startswith('/'):
|
||||
qkey = '"%s"' % key
|
||||
else:
|
||||
qkey = '<%s>' % quote_if_needed(key)
|
||||
else:
|
||||
qkey = quote_if_needed(key)
|
||||
data.append('%s%s%s%s%s' % (pre, allow, prefix, qkey, tail))
|
||||
if ref[name].keys():
|
||||
data.append('')
|
||||
|
||||
return data
|
||||
|
||||
def set_allow_str(allow):
|
||||
if allow == 'deny':
|
||||
return 'deny '
|
||||
@@ -2631,21 +2651,7 @@ def write_pair(prof_data, depth, allow, name, prefix, sep, tail, fn):
|
||||
return data
|
||||
|
||||
def write_includes(prof_data, depth):
|
||||
pre = ' ' * depth
|
||||
data = []
|
||||
|
||||
for key in sorted(prof_data['include'].keys()):
|
||||
if key.startswith('/'):
|
||||
qkey = '"%s"' % key
|
||||
else:
|
||||
qkey = '<%s>' % quote_if_needed(key)
|
||||
|
||||
data.append('%s#include %s' % (pre, qkey))
|
||||
|
||||
if data:
|
||||
data.append('')
|
||||
|
||||
return data
|
||||
return write_single(prof_data, depth, '', 'include', '#include ', '')
|
||||
|
||||
def write_change_profile(prof_data, depth):
|
||||
data = []
|
||||
|
@@ -12,7 +12,6 @@
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
import ctypes
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
@@ -119,7 +118,7 @@ class ReadLog:
|
||||
ev['protocol'] = event.net_protocol
|
||||
ev['sock_type'] = event.net_sock_type
|
||||
|
||||
if event.ouid != ctypes.c_ulong(-1).value: # ULONG_MAX
|
||||
if event.ouid != 18446744073709551615: # 2^64 - 1
|
||||
ev['fsuid'] = event.fsuid
|
||||
ev['ouid'] = event.ouid
|
||||
|
||||
|
@@ -14,9 +14,3 @@ show_notifications="yes"
|
||||
# OPTIONAL - restrict using aa-notify to users in the given group
|
||||
# (if not set, everybody who has permissions to read the logfile can use it)
|
||||
# use_group="admin"
|
||||
|
||||
# OPTIONAL - custom notification message body
|
||||
# message_body="This is a custom notification message."
|
||||
|
||||
# OPTIONAL - custom notification message footer
|
||||
# message_footer="For more information visit https://foo.com"
|
||||
|
@@ -7,14 +7,14 @@ msgstr ""
|
||||
"Project-Id-Version: apparmor-utils\n"
|
||||
"Report-Msgid-Bugs-To: <apparmor@lists.ubuntu.com>\n"
|
||||
"POT-Creation-Date: 2014-09-14 19:29+0530\n"
|
||||
"PO-Revision-Date: 2018-04-06 21:54+0000\n"
|
||||
"PO-Revision-Date: 2017-12-20 02:04+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: 2018-04-07 05:20+0000\n"
|
||||
"X-Generator: Launchpad (build 18599)\n"
|
||||
"X-Launchpad-Export-Date: 2017-12-21 05:12+0000\n"
|
||||
"X-Generator: Launchpad (build 18511)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#: ../aa-genprof:56
|
||||
@@ -320,15 +320,15 @@ msgstr "vorhandenes Profil überschreiben"
|
||||
|
||||
#: ../aa-audit:24
|
||||
msgid "Switch the given programs to audit mode"
|
||||
msgstr "Das angegebene Programm in den Prüfmodus versetzen"
|
||||
msgstr "Das angegebene Programm in den Audit-Modus versetzen"
|
||||
|
||||
#: ../aa-audit:26
|
||||
msgid "remove audit mode"
|
||||
msgstr "Prüfmodus entfernen"
|
||||
msgstr "Audit-Modus entfernen"
|
||||
|
||||
#: ../aa-audit:28
|
||||
msgid "Show full trace"
|
||||
msgstr "Die vollständige Spur anzeigen"
|
||||
msgstr "Zeige die komplette Spur"
|
||||
|
||||
#: ../aa-complain:23
|
||||
msgid "Switch the given program to complain mode"
|
||||
@@ -662,13 +662,12 @@ msgstr "Profiländerungen"
|
||||
#, python-format
|
||||
msgid "Can't find existing profile %s to compare changes."
|
||||
msgstr ""
|
||||
"Es kann kein vorhandenes Profil %s gefunden werden, um Änderungen zu "
|
||||
"vergleichen."
|
||||
"Kann kein existierendes Profil %s finden um Änderungen zu vergleichen."
|
||||
|
||||
#: ../apparmor/aa.py:2566 ../apparmor/aa.py:2581
|
||||
#, python-format
|
||||
msgid "Can't read AppArmor profiles in %s"
|
||||
msgstr "AppArmor-Profile in %s können nicht gelesen werden"
|
||||
msgstr "Kann AppArmor-Profile in %s nicht lesen"
|
||||
|
||||
#: ../apparmor/aa.py:2677
|
||||
#, python-format
|
||||
@@ -890,7 +889,7 @@ msgstr "Vorhandenes Profil kann nicht zum Verändern gefunden werden"
|
||||
#: ../apparmor/aa.py:4347
|
||||
#, python-format
|
||||
msgid "Writing updated profile for %s."
|
||||
msgstr "Aktualisiertes Profil für %s wird geschrieben."
|
||||
msgstr "Schreibe aktualisiertes Profil für %s."
|
||||
|
||||
#: ../apparmor/aa.py:4481
|
||||
#, python-format
|
||||
@@ -959,12 +958,12 @@ msgstr "%s wird deaktiviert."
|
||||
#: ../apparmor/tools.py:198
|
||||
#, python-format
|
||||
msgid "Setting %s to audit mode."
|
||||
msgstr "%s wird in den Prüfmodus versetzt."
|
||||
msgstr "%s wird in den audit-Modus versetzt."
|
||||
|
||||
#: ../apparmor/tools.py:200
|
||||
#, python-format
|
||||
msgid "Removing audit mode from %s."
|
||||
msgstr "Prüfmodus wird von %s entfernt."
|
||||
msgstr "Audit-Modus wird von %s entfernt."
|
||||
|
||||
#: ../apparmor/tools.py:212
|
||||
#, python-format
|
||||
@@ -1003,7 +1002,7 @@ msgstr "Das Profil für %s existiert nicht. Nichts zu bereinigen."
|
||||
|
||||
#: ../apparmor/ui.py:61
|
||||
msgid "Invalid hotkey for"
|
||||
msgstr "Ungültiges Tastenkürzel für"
|
||||
msgstr "Ungültiger Hotkey für"
|
||||
|
||||
#: ../apparmor/ui.py:77 ../apparmor/ui.py:121 ../apparmor/ui.py:275
|
||||
msgid "(Y)es"
|
||||
@@ -1035,7 +1034,7 @@ msgstr "Audi(t) aus"
|
||||
|
||||
#: ../apparmor/ui.py:227
|
||||
msgid "Audit (A)ll"
|
||||
msgstr "(A)lle überprüfen"
|
||||
msgstr ""
|
||||
|
||||
#: ../apparmor/ui.py:229
|
||||
msgid "(O)wner permissions on"
|
||||
|
@@ -159,4 +159,4 @@ class MinitoolsTest(AATest):
|
||||
setup_aa(apparmor)
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -200,4 +200,4 @@ type=AVC msg=audit(1348982148.195:2933): apparmor="DENIED" operation="file_lock"
|
||||
if __name__ == '__main__':
|
||||
if 'APPARMOR_DECODE' in os.environ:
|
||||
aadecode_bin = os.environ['APPARMOR_DECODE']
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -2684,7 +2684,7 @@ if __name__ == '__main__':
|
||||
# run the tests
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(unittest.TestLoader().loadTestsFromTestCase(T))
|
||||
rc = unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
rc = unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
if not rc.wasSuccessful():
|
||||
sys.exit(1)
|
||||
|
@@ -447,28 +447,22 @@ class AaTest_is_skippable_file(AATest):
|
||||
def test_skippable_04(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping..dpkg-bak'))
|
||||
def test_skippable_05(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.dpkg-remove'))
|
||||
def test_skippable_06(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.pacsave'))
|
||||
def test_skippable_07(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.pacnew'))
|
||||
def test_skippable_08(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.rpmnew'))
|
||||
def test_skippable_09(self):
|
||||
def test_skippable_06(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.rpmsave'))
|
||||
def test_skippable_10(self):
|
||||
def test_skippable_07(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.orig'))
|
||||
def test_skippable_11(self):
|
||||
def test_skippable_08(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping.rej'))
|
||||
def test_skippable_12(self):
|
||||
def test_skippable_09(self):
|
||||
self.assertTrue(is_skippable_file('bin.ping~'))
|
||||
def test_skippable_13(self):
|
||||
def test_skippable_10(self):
|
||||
self.assertTrue(is_skippable_file('.bin.ping'))
|
||||
def test_skippable_14(self):
|
||||
def test_skippable_11(self):
|
||||
self.assertTrue(is_skippable_file('')) # empty filename
|
||||
def test_skippable_15(self):
|
||||
def test_skippable_12(self):
|
||||
self.assertTrue(is_skippable_file('/etc/apparmor.d/')) # directory without filename
|
||||
def test_skippable_16(self):
|
||||
def test_skippable_13(self):
|
||||
self.assertTrue(is_skippable_file('README'))
|
||||
|
||||
|
||||
@@ -936,4 +930,4 @@ class AaTest_nonexistent_includes(AATest):
|
||||
setup_aa(apparmor.aa)
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -111,4 +111,4 @@ class AamodeTest_validate_log_mode(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -420,4 +420,4 @@ class TestAAREglobPathWithExt(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -86,4 +86,4 @@ class TestBaserule(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -989,4 +989,4 @@ class CapabilityDeleteTest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -484,4 +484,4 @@ class ChangeProfileDeleteTestAATest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -29,4 +29,4 @@ class TestIs_str_type(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -870,4 +870,4 @@ class DbusGlobTest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -50,4 +50,4 @@ class TestBaz(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -1123,4 +1123,4 @@ class FileGetExecConflictRules_1(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -272,4 +272,4 @@ TestLogToProfile.tests = find_test_multi('../../libraries/libapparmor/testsuite/
|
||||
setup_aa(apparmor.aa)
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=1) # reduced verbosity due to the big number of tests
|
||||
|
@@ -96,4 +96,4 @@ class TestParseEvent(unittest.TestCase):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -44,4 +44,4 @@ if __name__ == '__main__':
|
||||
setup_regex_tests(AAParseMountTest)
|
||||
setup_regex_tests(AAParseRemountTest)
|
||||
setup_regex_tests(AAParseUmountTest)
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -461,4 +461,4 @@ class NetworkRulesetReprTest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -528,4 +528,4 @@ find_and_setup_test_profiles('../../parser/tst/simple_tests/')
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=1) # reduced verbosity due to the big number of tests
|
||||
|
@@ -27,4 +27,4 @@ class AAParsePivotRootTest(AAParseTest):
|
||||
setup_aa(aa)
|
||||
if __name__ == '__main__':
|
||||
setup_regex_tests(AAParsePivotRootTest)
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -75,4 +75,4 @@ class AaTest_split_flags(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -555,4 +555,4 @@ class PtraceGlobTestAATest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -564,4 +564,4 @@ if __name__ == '__main__':
|
||||
setup_has_comma_testcases()
|
||||
setup_split_comment_testcases()
|
||||
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -490,4 +490,4 @@ class RlimitTime_to_intTest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -174,4 +174,4 @@ class SeverityDBTest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -621,4 +621,4 @@ class SignalGlobTestAATest(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -72,4 +72,4 @@ class TestHotkeyConflicts(AATest):
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
@@ -37,4 +37,4 @@ class AAParseUnixTest(AAParseTest):
|
||||
setup_aa(aa)
|
||||
if __name__ == '__main__':
|
||||
setup_regex_tests(AAParseUnixTest)
|
||||
unittest.main(verbosity=1)
|
||||
unittest.main(verbosity=2)
|
||||
|
Reference in New Issue
Block a user