mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 23:05:11 +00:00
Compare commits
81 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
704c82c574 | ||
|
bcda237953 | ||
|
8485770cdf | ||
|
cc7f549665 | ||
|
d6441c9da8 | ||
|
18813234b9 | ||
|
b9aaa632fb | ||
|
8cf3ec75fc | ||
|
d4e465a0bb | ||
|
8890dbcedc | ||
|
0e7d009164 | ||
|
215b5de131 | ||
|
59c8d43cec | ||
|
ec19c34795 | ||
|
df1bbdbb20 | ||
|
a5586f45fb | ||
|
9099b7ed41 | ||
|
6bb342380c | ||
|
0e26be21df | ||
|
36886b9c45 | ||
|
b0af2c2217 | ||
|
32c87d09c5 | ||
|
dceba9763a | ||
|
f1c6defb4a | ||
|
ecf8abab98 | ||
|
9b72afe9c3 | ||
|
c6324c2a3e | ||
|
cecb8e2855 | ||
|
4f2f7c60a6 | ||
|
da879c0704 | ||
|
9799fbde99 | ||
|
2b6eada019 | ||
|
bc952a5c85 | ||
|
b27a5b0cab | ||
|
74e074a213 | ||
|
8a21472175 | ||
|
1d3193b55c | ||
|
d0a131b70e | ||
|
78baf655b2 | ||
|
5141132c48 | ||
|
de9d56c29e | ||
|
939530b2b8 | ||
|
b4fc4c3c14 | ||
|
59a22c5786 | ||
|
f3ee5a1849 | ||
|
2c25ed160e | ||
|
edf59286e5 | ||
|
1e9e0e40a9 | ||
|
5049cdb45f | ||
|
aa82f874e2 | ||
|
fa98c9aafa | ||
|
033ed7837c | ||
|
5ca5b3879f | ||
|
ab4cfb5e84 | ||
|
d1e2ab6a77 | ||
|
b4cc405b80 | ||
|
c2c2cf005c | ||
|
0e4d3e6b30 | ||
|
af8d5021a5 | ||
|
8c63d75a20 | ||
|
7371119f28 | ||
|
e8041a7f48 | ||
|
b23de50180 | ||
|
9aac5e09d7 | ||
|
cb285b0cdd | ||
|
609a262447 | ||
|
e186512671 | ||
|
ca6f239790 | ||
|
c903b36d05 | ||
|
66ede4ae7a | ||
|
663b9636ed | ||
|
73e2f0cd8c | ||
|
37f5326d0e | ||
|
06dc32a9f3 | ||
|
b1a6f9c86e | ||
|
dc00e28558 | ||
|
6cfc6eeec2 | ||
|
4fbd6468ac | ||
|
e9e9340eff | ||
|
1a6c042ac6 | ||
|
5a5f969a5e |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -14,6 +14,7 @@ parser/po/*.mo
|
||||
parser/af_names.h
|
||||
parser/cap_names.h
|
||||
parser/generated_cap_names.h
|
||||
parser/generated_af_names.h
|
||||
parser/tst_lib
|
||||
parser/tst_misc
|
||||
parser/tst_regex
|
||||
@@ -159,6 +160,7 @@ libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/perl/libapparmor_wrap.o
|
||||
libraries/libapparmor/swig/perl/pm_to_blib
|
||||
libraries/libapparmor/swig/python/LibAppArmor.py
|
||||
libraries/libapparmor/swig/python/LibAppArmor.egg-info/
|
||||
libraries/libapparmor/swig/python/build/
|
||||
libraries/libapparmor/swig/python/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/python/Makefile
|
||||
@@ -175,7 +177,7 @@ libraries/libapparmor/swig/ruby/LibAppArmor_wrap.c
|
||||
libraries/libapparmor/swig/ruby/LibAppArmor_wrap.o
|
||||
libraries/libapparmor/swig/ruby/Makefile
|
||||
libraries/libapparmor/swig/ruby/Makefile.in
|
||||
libraries/libapparmor/swig/ruby/Makefile.new
|
||||
libraries/libapparmor/swig/ruby/Makefile.bak
|
||||
libraries/libapparmor/swig/ruby/Makefile.ruby
|
||||
libraries/libapparmor/swig/ruby/mkmf.log
|
||||
libraries/libapparmor/testsuite/.deps
|
||||
@@ -203,6 +205,8 @@ utils/*.tmp
|
||||
utils/po/*.mo
|
||||
utils/apparmor/*.pyc
|
||||
utils/apparmor/rule/*.pyc
|
||||
utils/apparmor.egg-info/
|
||||
utils/build/
|
||||
utils/htmlcov/
|
||||
utils/test/common_test.pyc
|
||||
utils/test/.coverage
|
||||
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
image: ubuntu:latest
|
||||
before_script:
|
||||
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil zlib1g-dev
|
||||
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil python3-setuptools zlib1g-dev
|
||||
- lsb_release -a
|
||||
- uname -a
|
||||
|
||||
|
@@ -124,7 +124,7 @@ static char **parse_args(int argc, char **argv)
|
||||
{"stdout", no_argument, 0, ARG_STDOUT},
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "+dvhxl:w:", long_opts, NULL)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "+dvhxf:l:w:", long_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
opt_debug = true;
|
||||
@@ -181,7 +181,7 @@ int main(int argc, char **argv)
|
||||
error("failed to extract features abi from the kernel");
|
||||
}
|
||||
if (opt_file) {
|
||||
int in = open(opt_file, O_RDONLY);
|
||||
in = open(opt_file, O_RDONLY);
|
||||
if (in == -1)
|
||||
error("failed to open file '%s'", opt_file);
|
||||
rc = aa_features_new_from_file(&features, in);
|
||||
|
@@ -135,7 +135,16 @@ static int get_profiles(struct profile **profiles, size_t *n) {
|
||||
while (getline(&line, &len, fp) != -1) {
|
||||
struct profile *_profiles;
|
||||
autofree char *status = NULL;
|
||||
autofree char *name = strdup(aa_splitcon(line, &status));
|
||||
autofree char *name = NULL;
|
||||
char *tmpname = aa_splitcon(line, &status);
|
||||
|
||||
if (!tmpname) {
|
||||
dfprintf(stderr, "Error: failed profile name split of '%s'.\n", line);
|
||||
ret = AA_EXIT_INTERNAL_ERROR;
|
||||
// skip this entry and keep processing
|
||||
continue;
|
||||
}
|
||||
name = strdup(tmpname);
|
||||
|
||||
if (status)
|
||||
status = strdup(status);
|
||||
|
@@ -1 +1 @@
|
||||
3.0.2
|
||||
3.0.5
|
||||
|
@@ -66,17 +66,17 @@ variable to configure. See ``configure --help'' for reference.
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
# Check if you have setuptools, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test -z "$ac_distutils_result"; then
|
||||
AC_MSG_CHECKING([for the setuptools Python package])
|
||||
ac_setuptools_result=`$PYTHON -c "import setuptools" 2>&1`
|
||||
if test -z "$ac_setuptools_result"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
AC_MSG_ERROR([cannot import Python module "setuptools".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
$ac_setuptools_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
@@ -88,8 +88,8 @@ $ac_distutils_result])
|
||||
PYTHON_CPPFLAGS=`$PYTHON_CONFIG --includes`
|
||||
fi
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
|
||||
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
|
||||
python_path=`$PYTHON -c "import sys; import sysconfig;\
|
||||
sys.stdout.write('%s\n' % sysconfig.get_path('include'));"`
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
@@ -108,8 +108,8 @@ sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
# (makes two attempts to ensure we've got a version number
|
||||
# from the interpreter)
|
||||
py_version=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
|
||||
sys.stdout.write('%s\n' % ''.join(get_config_vars('VERSION')))"`
|
||||
py_version=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('%s\n' % ''.join(sysconfig.get_config_vars('VERSION')))"`
|
||||
if test "$py_version" == "[None]"; then
|
||||
if test -n "$PYTHON_VERSION"; then
|
||||
py_version=$PYTHON_VERSION
|
||||
@@ -119,8 +119,8 @@ sys.stdout.write("%s\n" % sys.version[[:3]])"`
|
||||
fi
|
||||
fi
|
||||
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
|
||||
sys.stdout.write('-L' + get_python_lib(0,1) + ' -lpython\n')"`$py_version`$PYTHON -c \
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('-L' + sysconfig.get_path('stdlib') + ' -lpython\n')"`$py_version`$PYTHON -c \
|
||||
"import sys; sys.stdout.write('%s' % getattr(sys,'abiflags',''))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LDFLAGS])
|
||||
@@ -131,8 +131,8 @@ sys.stdout.write('-L' + get_python_lib(0,1) + ' -lpython\n')"`$py_version`$PYTHO
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
sys.stdout.write('%s\n' % distutils.sysconfig.get_python_lib(0,0));"`
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import sys; import sysconfig; \
|
||||
sys.stdout.write('%s\n' % sysconfig.get_path('purelib'));"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
@@ -146,8 +146,8 @@ sys.stdout.write('%s\n' % distutils.sysconfig.get_python_lib(0,0));"`
|
||||
PYTHON_EXTRA_LIBS=''
|
||||
fi
|
||||
if test -z "$PYTHON_EXTRA_LIBS"; then
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
conf = sysconfig.get_config_var; \
|
||||
sys.stdout.write('%s %s %s\n' % (conf('BLDLIBRARY'), conf('LOCALMODLIBS'), conf('LIBS')))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
|
||||
@@ -162,8 +162,8 @@ sys.stdout.write('%s %s %s\n' % (conf('BLDLIBRARY'), conf('LOCALMODLIBS'), conf(
|
||||
PYTHON_EXTRA_LDFLAGS=''
|
||||
fi
|
||||
if test -z "$PYTHON_EXTRA_LDFLAGS"; then
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
|
||||
conf = sysconfig.get_config_var; \
|
||||
sys.stdout.write('%s\n' % conf('LINKFORSHARED'))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
|
||||
|
@@ -27,7 +27,7 @@ INCLUDES = $(all_includes)
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
#
|
||||
AA_LIB_CURRENT = 9
|
||||
AA_LIB_REVISION = 1
|
||||
AA_LIB_REVISION = 3
|
||||
AA_LIB_AGE = 8
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
@@ -38,7 +38,7 @@ include $(COMMONDIR)/Make.rules
|
||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||
AM_LFLAGS = -v
|
||||
AM_YFLAGS = -d -p aalogparse_
|
||||
AM_CFLAGS = -Wall $(EXTRA_WARNINGS) -fPIC
|
||||
AM_CFLAGS = -Wall $(EXTRA_WARNINGS) -fPIC -flto-partition=none
|
||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||
scanner.h: scanner.l
|
||||
$(LEX) -v $<
|
||||
|
@@ -194,6 +194,8 @@ static int features_dir_cb(int dirfd, const char *name, struct stat *st,
|
||||
if (features_snprintf(fst, "%s {", name) == -1)
|
||||
return -1;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
ssize_t len;
|
||||
size_t remaining;
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#if (YYDEBUG != 0)
|
||||
#define debug_unused_ /* nothing */
|
||||
#else
|
||||
#define no_debug_unused_ unused_
|
||||
#define debug_unused_ unused_
|
||||
#endif
|
||||
|
||||
aa_log_record *ret_record;
|
||||
@@ -46,7 +46,7 @@ aa_log_record *ret_record;
|
||||
/* Since we're a library, on any errors we don't want to print out any
|
||||
* error messages. We should probably add a debug interface that does
|
||||
* emit messages when asked for. */
|
||||
void aalogparse_error(unused_ void *scanner, no_debug_unused_ char const *s)
|
||||
void aalogparse_error(unused_ void *scanner, debug_unused_ char const *s)
|
||||
{
|
||||
#if (YYDEBUG != 0)
|
||||
printf("ERROR: %s\n", s);
|
||||
@@ -186,6 +186,7 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
||||
%token TOK_KEY_FLAGS
|
||||
%token TOK_KEY_SRCNAME
|
||||
|
||||
%token TOK_SOCKLOGD_KERNEL
|
||||
%token TOK_SYSLOG_KERNEL
|
||||
%token TOK_SYSLOG_USER
|
||||
|
||||
@@ -232,24 +233,28 @@ dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
|
||||
;
|
||||
|
||||
syslog_id: TOK_ID TOK_SYSLOG_KERNEL { free($1); }
|
||||
| TOK_SOCKLOGD_KERNEL { }
|
||||
;
|
||||
|
||||
syslog_type:
|
||||
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
syslog_date syslog_id audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date syslog_id key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
/* needs update: hard newline in handling mutiline log messages */
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); free($4); }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||
| syslog_date syslog_id TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_USER key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
;
|
||||
|
@@ -43,6 +43,7 @@
|
||||
__asm__ (".symver " #real "," #name "@" #version)
|
||||
#define default_symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version)
|
||||
#define DLLEXPORT __attribute__((visibility("default"),externally_visible))
|
||||
|
||||
#define UNCONFINED "unconfined"
|
||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||
@@ -824,7 +825,7 @@ int aa_change_onexec(const char *profile)
|
||||
}
|
||||
|
||||
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
|
||||
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
DLLEXPORT extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
|
||||
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
||||
|
||||
@@ -1222,7 +1223,7 @@ int query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
||||
|
||||
/* export multiple aa_query_label symbols to compensate for downstream
|
||||
* releases with differing symbol versions. */
|
||||
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
DLLEXPORT extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
|
||||
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
||||
|
||||
|
@@ -6,14 +6,14 @@
|
||||
|
||||
IMMUNIX_1.0 {
|
||||
global:
|
||||
change_hat;
|
||||
change_hat; __old_change_hat;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
APPARMOR_1.0 {
|
||||
global:
|
||||
change_hat;
|
||||
change_hat; __change_hat;
|
||||
parse_record;
|
||||
free_record;
|
||||
local:
|
||||
@@ -24,7 +24,7 @@ APPARMOR_1.1 {
|
||||
global:
|
||||
aa_is_enabled;
|
||||
aa_find_mountpoint;
|
||||
aa_change_hat;
|
||||
aa_change_hat; __old_change_hat;
|
||||
aa_change_hatv;
|
||||
aa_change_hat_vargs;
|
||||
aa_change_profile;
|
||||
@@ -37,7 +37,7 @@ APPARMOR_1.1 {
|
||||
free_record;
|
||||
aa_getprocattr_raw;
|
||||
aa_getprocattr;
|
||||
aa_query_label;
|
||||
aa_query_label; __aa_query_label;
|
||||
|
||||
# no more symbols here, please
|
||||
|
||||
@@ -47,7 +47,7 @@ APPARMOR_1.1 {
|
||||
|
||||
APPARMOR_2.9 {
|
||||
global:
|
||||
aa_query_label;
|
||||
aa_query_label; query_label;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_1.1;
|
||||
|
@@ -45,6 +45,8 @@ struct aa_policy_cache {
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
/* remove regular files */
|
||||
return unlinkat(dirfd, path, 0);
|
||||
|
@@ -452,7 +452,8 @@ int _aa_overlaydirat_for_each(int dirfd[], int n, void *data,
|
||||
*
|
||||
* The cb function is called with the DIR in use and the name of the
|
||||
* file in that directory. If the file is to be opened it should
|
||||
* use the openat, fstatat, and related fns.
|
||||
* use the openat, fstatat, and related fns. If the file is a symlink
|
||||
* _aa_dirat_for_each currently tries to traverse it for the caller
|
||||
*
|
||||
* Returns: 0 on success, else -1 and errno is set to the error code
|
||||
*/
|
||||
@@ -485,14 +486,34 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
autofree struct dirent *dir = namelist[i];
|
||||
struct stat my_stat;
|
||||
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, AT_SYMLINK_NOFOLLOW)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
/* currently none of the callers handle symlinks, and this
|
||||
* same basic code was applied to each. So for this patch
|
||||
* just drop it here.
|
||||
*
|
||||
* Going forward we need to start handling symlinks as
|
||||
* they have meaning.
|
||||
* In the case of
|
||||
* cache: they act as a place holder for files that have been
|
||||
* combined into a single binary. This enables the
|
||||
* file based cache lookup time find that relation
|
||||
* and dedup, so multiple loads aren't done.
|
||||
* profiles: just a profile in an alternate location, but
|
||||
* should do dedup detection when doing dir reads
|
||||
* so we don't double process.
|
||||
*/
|
||||
if (S_ISLNK(my_stat.st_mode)) {
|
||||
/* just traverse the symlink */
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
PDEBUG("symlink target stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
|
@@ -172,6 +172,7 @@ audit "audit"
|
||||
ip_addr [a-f[:digit:].:]{3,}
|
||||
|
||||
/* syslog tokens */
|
||||
socklogd_kernel kern.notice{colon}
|
||||
syslog_kernel kernel{colon}
|
||||
syslog_user [[:alnum:]_-]+\[[[:digit:]]+\]{colon}
|
||||
syslog_yyyymmdd {digit}{4}{minus}{digit}{2}{minus}{digit}{2}
|
||||
@@ -351,6 +352,7 @@ yy_flex_debug = 0;
|
||||
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
||||
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
||||
|
||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
|
||||
{syslog_user} { return(TOK_SYSLOG_USER); }
|
||||
{syslog_month} { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
|
||||
@@ -365,6 +367,7 @@ yy_flex_debug = 0;
|
||||
|
||||
<hostname>{
|
||||
{ws}+ { /* eat whitespace */ }
|
||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||
{syslog_hostname} { yylval->t_str = strdup(yytext); BEGIN(INITIAL); return(TOK_ID); }
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,7 @@ install-exec-local:
|
||||
|
||||
clean-local:
|
||||
if test -x "$(PYTHON)"; then $(PYTHON) setup.py clean; fi
|
||||
rm -rf build
|
||||
rm -rf build LibAppArmor.egg-info
|
||||
if test $(top_srcdir) != $(top_builddir) ; then rm -f libapparmor_wrap.c ; fi
|
||||
|
||||
endif
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from distutils.core import setup, Extension
|
||||
from setuptools import setup, Extension
|
||||
import string
|
||||
|
||||
setup(name = 'LibAppArmor',
|
||||
|
@@ -10,8 +10,7 @@ test_python.py: test_python.py.in $(top_builddir)/config.status
|
||||
|
||||
CLEANFILES = test_python.py
|
||||
|
||||
# bah, how brittle is this?
|
||||
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")'
|
||||
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
|
||||
|
||||
TESTS = test_python.py
|
||||
TESTS_ENVIRONMENT = \
|
||||
|
10
libraries/libapparmor/swig/python/test/buildpath.py
Normal file
10
libraries/libapparmor/swig/python/test/buildpath.py
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/python3
|
||||
# the build path has changed in setuptools 61.2
|
||||
import sys
|
||||
import sysconfig
|
||||
import setuptools
|
||||
if tuple(map(int,setuptools.__version__.split("."))) >= (61, 2):
|
||||
identifier = sys.implementation.cache_tag
|
||||
else:
|
||||
identifier = "%d.%d" % sys.version_info[:2]
|
||||
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))
|
@@ -9,7 +9,9 @@ LibAppArmor_wrap.c : $(srcdir)/../SWIG/libapparmor.i
|
||||
MOSTLYCLEANFILES=LibAppArmor_wrap.c
|
||||
|
||||
Makefile.ruby: extconf.rb
|
||||
mv Makefile Makefile.bak
|
||||
PREFIX=$(prefix) $(RUBY) $< --with-LibAppArmor-include=$(top_srcdir)/include
|
||||
mv Makefile.bak Makefile
|
||||
|
||||
LibAppArmor.so: LibAppArmor_wrap.c Makefile.ruby
|
||||
$(MAKE) -fMakefile.ruby
|
||||
@@ -22,7 +24,7 @@ install-exec-local: Makefile.ruby
|
||||
|
||||
clean-local:
|
||||
if test -f Makefile.ruby; then $(MAKE) -fMakefile.ruby clean; fi
|
||||
rm -f Makefile.ruby Makefile.new
|
||||
rm -f Makefile.ruby Makefile.bak
|
||||
rm -f *.o *.so *.log
|
||||
|
||||
endif
|
||||
|
@@ -2,16 +2,8 @@
|
||||
|
||||
require 'mkmf'
|
||||
|
||||
# hack 1: ruby black magic to write a Makefile.new instead of a Makefile
|
||||
alias open_orig open
|
||||
def open(path, mode=nil, perm=nil)
|
||||
path = 'Makefile.new' if path == 'Makefile'
|
||||
if block_given?
|
||||
open_orig(path, mode, perm) { |io| yield(io) }
|
||||
else
|
||||
open_orig(path, mode, perm)
|
||||
end
|
||||
end
|
||||
# hack 1: Before extconf.rb gets called, Makefile gets backed up, and
|
||||
# restored afterwards (see Makefile.am)
|
||||
|
||||
if ENV['PREFIX']
|
||||
prefix = CONFIG['prefix']
|
||||
@@ -27,7 +19,7 @@ if find_library('apparmor', 'parse_record', '../../src/.libs') and
|
||||
|
||||
# hack 2: strip all rpath references
|
||||
open('Makefile.ruby', 'w') do |out|
|
||||
IO.foreach('Makefile.new') do |line|
|
||||
IO.foreach('Makefile') do |line|
|
||||
out.puts line.gsub(/-Wl,-R'[^']*'/, '')
|
||||
end
|
||||
end
|
||||
|
@@ -0,0 +1 @@
|
||||
audit.log:type=AVC msg=audit(1630913351.586:4): apparmor="STATUS" info="AppArmor Filesystem Enabled" pid=1 comm="swapper/0"
|
@@ -0,0 +1,3 @@
|
||||
START
|
||||
File: status-filesystem-enabled.in
|
||||
Event type: AA_RECORD_INVALID
|
@@ -0,0 +1 @@
|
||||
2021-09-11T20:57:41.91645 kern.notice: [ 469.180605] audit: type=1400 audit(1631392703.952:3): apparmor="ALLOWED" operation="mkdir" profile="/usr/sbin/sshd" name="/run/user/1000/kakoune/" pid=2545 comm="sshd" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
|
@@ -0,0 +1,15 @@
|
||||
START
|
||||
File: testcase_socklogd_mkdir.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1631392703.952:3
|
||||
Operation: mkdir
|
||||
Mask: c
|
||||
Denied Mask: c
|
||||
fsuid: 1000
|
||||
ouid: 1000
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /run/user/1000/kakoune/
|
||||
Command: sshd
|
||||
PID: 2545
|
||||
Epoch: 1631392703
|
||||
Audit subid: 3
|
@@ -0,0 +1,4 @@
|
||||
/usr/sbin/sshd {
|
||||
owner /run/user/1000/kakoune/ w,
|
||||
|
||||
}
|
@@ -60,7 +60,7 @@ WARNINGS = -Wall
|
||||
CXX_WARNINGS = ${WARNINGS} ${EXTRA_WARNINGS}
|
||||
CPP_WARNINGS =
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -g -O2 -pipe
|
||||
CFLAGS = -g -O2 -pipe -flto-partition=none
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -pg -D DEBUG
|
||||
@@ -307,10 +307,18 @@ parser_version.h: Makefile
|
||||
# as well as the filtering that occurs for network protocols that
|
||||
# apparmor should not mediate.
|
||||
|
||||
af_names.h: ../common/list_af_names.sh
|
||||
../common/list_af_names.sh | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@
|
||||
../common/list_af_names.sh | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@
|
||||
# cat $@
|
||||
generated_af_names.h: ../common/list_af_names.sh
|
||||
../common/list_af_names.sh > $@
|
||||
|
||||
af_names.h: generated_af_names.h base_af_names.h
|
||||
cat base_af_names.h | diff -u - generated_af_names.h | grep -v '^.AF_MAX' | grep '^\+[^+]' ; \
|
||||
if [ $$? -eq 1 ] ; then \
|
||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@ ; \
|
||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@ ; \
|
||||
else \
|
||||
echo "Error: new AF names detected; please update base_af_names.h with values from generated_af_names.h" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
generated_cap_names.h: /usr/include/linux/capability.h
|
||||
../common/list_capabilities.sh | LC_ALL=C sed -n -e "s/[ \\t]\\?CAP_\\([A-Z0-9_]\\+\\)/\{\"\\L\\1\", \\UCAP_\\1, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE\},\\n/pg" > $@
|
||||
@@ -411,6 +419,7 @@ install-indep: indep
|
||||
install -m 755 -d ${DESTDIR}/var/lib/apparmor
|
||||
install -m 755 -d $(APPARMOR_BIN_PREFIX)
|
||||
install -m 755 rc.apparmor.functions $(APPARMOR_BIN_PREFIX)
|
||||
install -m 755 profile-load $(APPARMOR_BIN_PREFIX)
|
||||
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
|
||||
$(MAKE) install_manpages DESTDIR=${DESTDIR}
|
||||
|
||||
@@ -434,7 +443,7 @@ clean: pod_clean
|
||||
rm -f $(YACC_C_FILES)
|
||||
rm -f parser_version.h
|
||||
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
||||
rm -f af_names.h
|
||||
rm -f af_names.h generated_af_names.h
|
||||
rm -f cap_names.h generated_cap_names.h
|
||||
rm -rf techdoc.aux techdoc.out techdoc.log techdoc.pdf techdoc.toc techdoc.txt techdoc/
|
||||
$(MAKE) -s -C $(AAREDIR) clean
|
||||
|
@@ -148,7 +148,7 @@ capabilities(7))
|
||||
|
||||
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
||||
|
||||
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' ) ','
|
||||
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
|
||||
|
||||
B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
||||
|
||||
@@ -842,7 +842,7 @@ and other operations that are typically reserved for the root user.
|
||||
|
||||
AppArmor supports simple coarse grained network mediation. The network
|
||||
rule restrict all socket(2) based operations. The mediation done is
|
||||
a course grained check on whether a socket of a given type and family
|
||||
a coarse-grained check on whether a socket of a given type and family
|
||||
can be created, read, or written. There is no mediation based of port
|
||||
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
|
||||
only specify type 'dgram' and 'raw'.
|
||||
|
@@ -71,6 +71,13 @@ fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
systemd-detect-virt --quiet --container && \
|
||||
! is_container_with_internal_policy; then
|
||||
aa_log_daemon_msg "Not starting AppArmor in container"
|
||||
aa_log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
apparmor_start
|
||||
rc=$?
|
||||
;;
|
||||
@@ -79,6 +86,13 @@ case "$1" in
|
||||
rc=$?
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
if [ -x /usr/bin/systemd-detect-virt ] && \
|
||||
systemd-detect-virt --quiet --container && \
|
||||
! is_container_with_internal_policy; then
|
||||
aa_log_daemon_msg "Not starting AppArmor in container"
|
||||
aa_log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
apparmor_restart
|
||||
rc=$?
|
||||
;;
|
||||
|
46
parser/base_af_names.h
Normal file
46
parser/base_af_names.h
Normal file
@@ -0,0 +1,46 @@
|
||||
AF_UNSPEC 0,
|
||||
AF_UNIX 1,
|
||||
AF_INET 2,
|
||||
AF_AX25 3,
|
||||
AF_IPX 4,
|
||||
AF_APPLETALK 5,
|
||||
AF_NETROM 6,
|
||||
AF_BRIDGE 7,
|
||||
AF_ATMPVC 8,
|
||||
AF_X25 9,
|
||||
AF_INET6 10,
|
||||
AF_ROSE 11,
|
||||
AF_NETBEUI 13,
|
||||
AF_SECURITY 14,
|
||||
AF_KEY 15,
|
||||
AF_NETLINK 16,
|
||||
AF_PACKET 17,
|
||||
AF_ASH 18,
|
||||
AF_ECONET 19,
|
||||
AF_ATMSVC 20,
|
||||
AF_RDS 21,
|
||||
AF_SNA 22,
|
||||
AF_IRDA 23,
|
||||
AF_PPPOX 24,
|
||||
AF_WANPIPE 25,
|
||||
AF_LLC 26,
|
||||
AF_IB 27,
|
||||
AF_MPLS 28,
|
||||
AF_CAN 29,
|
||||
AF_TIPC 30,
|
||||
AF_BLUETOOTH 31,
|
||||
AF_IUCV 32,
|
||||
AF_RXRPC 33,
|
||||
AF_ISDN 34,
|
||||
AF_PHONET 35,
|
||||
AF_IEEE802154 36,
|
||||
AF_CAIF 37,
|
||||
AF_ALG 38,
|
||||
AF_NFC 39,
|
||||
AF_VSOCK 40,
|
||||
AF_KCM 41,
|
||||
AF_QIPCRTR 42,
|
||||
AF_SMC 43,
|
||||
AF_XDP 44,
|
||||
AF_MCTP 45,
|
||||
AF_MAX 46,
|
@@ -19,8 +19,25 @@
|
||||
#ifndef __AA_CAPABILITY_H
|
||||
#define __AA_CAPABILITY_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <linux/capability.h>
|
||||
|
||||
#define NO_BACKMAP_CAP 0xff
|
||||
|
||||
|
||||
#ifndef CAP_AUDIT_WRITE
|
||||
#define CAP_AUDIT_WRITE 29
|
||||
#endif
|
||||
#ifndef CAP_AUDIT_CONTROL
|
||||
#define CAP_AUDIT_CONTROL 30
|
||||
#endif
|
||||
#ifndef CAP_SETFCAP
|
||||
#define CAP_SETFCAP 31
|
||||
#endif
|
||||
#ifndef CAP_MAC_OVERRIDE
|
||||
#define CAP_MAC_OVERRIDE 32
|
||||
#endif
|
||||
|
||||
#ifndef CAP_PERFMON
|
||||
#define CAP_PERFMON 38
|
||||
#endif
|
||||
|
@@ -543,9 +543,9 @@ public:
|
||||
|
||||
int min_match_len()
|
||||
{
|
||||
if (contains_oob()) {
|
||||
return 0;
|
||||
}
|
||||
/* Inverse match does not match any oob char at this time
|
||||
* so only count characters
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -141,6 +141,8 @@ static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
if (!(yyin = fopen(path,"r")))
|
||||
yyerror(_("Could not open '%s' in '%s'"), path, d->filename);
|
||||
@@ -741,7 +743,7 @@ include/{WS} {
|
||||
}
|
||||
}
|
||||
|
||||
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODEINCLUDE,INCLUDE_EXISTS,ABI_MODE>{
|
||||
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODE,INCLUDE,INCLUDE_EXISTS,ABI_MODE>{
|
||||
(.|\n) {
|
||||
DUMP_PREPROCESS;
|
||||
/* Something we didn't expect */
|
||||
|
@@ -1332,6 +1332,8 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||
autofree char *path = NULL;
|
||||
@@ -1354,6 +1356,8 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||
autofree char *path = NULL;
|
||||
@@ -1546,7 +1550,7 @@ int main(int argc, char *argv[])
|
||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||
&cb_data, cb))) {
|
||||
last_error = errno;
|
||||
PDEBUG("Failed loading profiles from %s\n",
|
||||
PERROR("There was an error while loading profiles from %s\n",
|
||||
profilename);
|
||||
if (abort_on_error)
|
||||
break;
|
||||
|
@@ -44,20 +44,6 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <linux/capability.h>
|
||||
|
||||
#ifndef CAP_AUDIT_WRITE
|
||||
#define CAP_AUDIT_WRITE 29
|
||||
#endif
|
||||
#ifndef CAP_AUDIT_CONTROL
|
||||
#define CAP_AUDIT_CONTROL 30
|
||||
#endif
|
||||
#ifndef CAP_SETFCAP
|
||||
#define CAP_SETFCAP 31
|
||||
#endif
|
||||
#ifndef CAP_MAC_OVERRIDE
|
||||
#define CAP_MAC_OVERRIDE 32
|
||||
#endif
|
||||
|
||||
#define CIDR_32 htonl(0xffffffff)
|
||||
#define CIDR_24 htonl(0xffffff00)
|
||||
|
48
parser/profile-load
Executable file
48
parser/profile-load
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
# profile-load
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2010-2015 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical, Ltd.
|
||||
# ----------------------------------------------------------------------
|
||||
#
|
||||
# Helper for loading an AppArmor profile in pre-start scripts.
|
||||
|
||||
[ -z "$1" ] && exit 1 # require a profile name
|
||||
|
||||
. /lib/apparmor/rc.apparmor.functions
|
||||
|
||||
# do not load in a container
|
||||
[ -x /usr/bin/systemd-detect-virt ] && systemd-detect-virt --quiet --container && ! is_container_with_internal_policy && exit 0 || true
|
||||
|
||||
[ -d /rofs/etc/apparmor.d ] && exit 0 # do not load if running liveCD
|
||||
|
||||
profile=/etc/apparmor.d/"$1"
|
||||
[ -e "$profile" ] || exit 0 # skip when missing profile
|
||||
|
||||
module=/sys/module/apparmor
|
||||
[ -d $module ] || exit 0 # do not load without AppArmor in kernel
|
||||
|
||||
[ -x /sbin/apparmor_parser ] || exit 0 # do not load without parser
|
||||
|
||||
aafs=/sys/kernel/security/apparmor
|
||||
[ -d $aafs ] || exit 0 # do not load if unmounted
|
||||
[ -w $aafs/.load ] || exit 1 # fail if cannot load profiles
|
||||
|
||||
params=$module/parameters
|
||||
[ -r $params/enabled ] || exit 0 # do not load if missing
|
||||
read enabled < $params/enabled || exit 1 # if this fails, something went wrong
|
||||
[ "$enabled" = "Y" ] || exit 0 # do not load if disabled
|
||||
|
||||
/sbin/apparmor_parser -r -W "$profile" || exit 0 # LP: #1058356
|
@@ -181,10 +181,10 @@ __parse_profiles_dir() {
|
||||
if [ ! -f "$profile" ] ; then
|
||||
continue
|
||||
fi
|
||||
echo "$profile"
|
||||
printf "%s\0" "$profile"
|
||||
done | \
|
||||
# Use xargs to parallelize calls to the parser over all CPUs
|
||||
xargs -n1 -d"\n" --max-procs="$(getconf _NPROCESSORS_ONLN)" \
|
||||
xargs -n1 -0r -P "$(getconf _NPROCESSORS_ONLN)" \
|
||||
"$PARSER" $PARSER_OPTS "$parser_cmd" --
|
||||
if [ $? -ne 0 ]; then
|
||||
status=1
|
||||
|
@@ -17,8 +17,8 @@ endif
|
||||
|
||||
all: tests
|
||||
|
||||
.PHONY: tests error_output gen_dbus gen_xtrans parser_sanity caching minimize equality valgrind
|
||||
tests: error_output caching minimize equality parser_sanity
|
||||
.PHONY: tests error_output gen_dbus gen_xtrans parser_sanity caching minimize equality dirtest valgrind
|
||||
tests: error_output caching minimize equality dirtest parser_sanity
|
||||
|
||||
GEN_TRANS_DIRS=simple_tests/generated_x/ simple_tests/generated_perms_leading/ simple_tests/generated_perms_safe/ simple_tests/generated_dbus
|
||||
|
||||
@@ -46,6 +46,9 @@ minimize: $(PARSER)
|
||||
equality: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./equality.sh
|
||||
|
||||
dirtest: $(PARSER)
|
||||
LANG=C APPARMOR_PARSER="$(PARSER) $(PARSER_ARGS)" ./dirtest.sh
|
||||
|
||||
valgrind: $(PARSER) gen_xtrans gen_dbus
|
||||
LANG=C ./valgrind_simple.py -p "$(PARSER) $(PARSER_ARGS)" -v simple_tests
|
||||
|
||||
|
72
parser/tst/dirtest.sh
Executable file
72
parser/tst/dirtest.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2022
|
||||
# Canonical, Ltd. (All rights reserved)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical Ltd.
|
||||
#
|
||||
|
||||
# simple test to ensure dir is being iterated as expected
|
||||
# yes this needs to be improved and reworked
|
||||
|
||||
|
||||
# passed in by Makefile
|
||||
#APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
|
||||
|
||||
|
||||
do_tst() {
|
||||
local msg="$1"
|
||||
local expected="$2"
|
||||
local rc=0
|
||||
shift 2
|
||||
#global tmpdir
|
||||
|
||||
${APPARMOR_PARSER} "$@" > "$tmpdir/out" 2>/dev/null
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ] && [ "$expected" != "fail" ] ; then
|
||||
echo "failed: expected \"$expected\" but parser returned error"
|
||||
return 1
|
||||
fi
|
||||
if [ $rc -eq 0 ] && [ "$expected" = "fail" ] ; then
|
||||
echo "succeeded unexpectedly: expected \"$expected\" but parser returned success"
|
||||
return 1
|
||||
fi
|
||||
if ! diff -q "$tmpdir/out" dirtest/dirtest.out ; then
|
||||
echo "failed: expected \"$expected\" but output comparison failed"
|
||||
diff -u dirtest/dirtest.out "$tmpdir/out"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
tmpdir=$(mktemp -d "$tmpdir.XXXXXXXX")
|
||||
chmod 755 "$tmpdir"
|
||||
export tmpdir
|
||||
|
||||
rc=0
|
||||
|
||||
# pass - no parser errors and output matches
|
||||
# error - parser error and output matches
|
||||
# fail - comparison out parser output failed
|
||||
do_tst "good dir list" pass -N dirtest/gooddir/ || rc=1
|
||||
do_tst "bad link in dir" fail -N dirtest/badlink/ || rc=1
|
||||
do_tst "bad profile in dir" fail -N dirtest/badprofile/ || rc=1
|
||||
|
||||
rm -rf "$tmpdir"
|
||||
|
||||
if [ $rc -eq 0 ] ; then
|
||||
echo "PASS"
|
||||
fi
|
||||
|
||||
exit $rc
|
1
parser/tst/dirtest/badlink/bar
Symbolic link
1
parser/tst/dirtest/badlink/bar
Symbolic link
@@ -0,0 +1 @@
|
||||
foo
|
1
parser/tst/dirtest/badlink/good_link
Symbolic link
1
parser/tst/dirtest/badlink/good_link
Symbolic link
@@ -0,0 +1 @@
|
||||
../goodtarget
|
2
parser/tst/dirtest/badlink/profileA
Normal file
2
parser/tst/dirtest/badlink/profileA
Normal file
@@ -0,0 +1,2 @@
|
||||
profile a_profile {
|
||||
}
|
2
parser/tst/dirtest/badlink/profileB
Normal file
2
parser/tst/dirtest/badlink/profileB
Normal file
@@ -0,0 +1,2 @@
|
||||
profile b_profile {
|
||||
}
|
3
parser/tst/dirtest/badprofile/bad
Normal file
3
parser/tst/dirtest/badprofile/bad
Normal file
@@ -0,0 +1,3 @@
|
||||
profile bad_profile {
|
||||
file
|
||||
}
|
1
parser/tst/dirtest/badprofile/good_link
Symbolic link
1
parser/tst/dirtest/badprofile/good_link
Symbolic link
@@ -0,0 +1 @@
|
||||
../goodtarget
|
2
parser/tst/dirtest/badprofile/profileA
Normal file
2
parser/tst/dirtest/badprofile/profileA
Normal file
@@ -0,0 +1,2 @@
|
||||
profile a_profile {
|
||||
}
|
2
parser/tst/dirtest/badprofile/profileB
Normal file
2
parser/tst/dirtest/badprofile/profileB
Normal file
@@ -0,0 +1,2 @@
|
||||
profile b_profile {
|
||||
}
|
3
parser/tst/dirtest/dirtest.out
Normal file
3
parser/tst/dirtest/dirtest.out
Normal file
@@ -0,0 +1,3 @@
|
||||
good_target
|
||||
a_profile
|
||||
b_profile
|
1
parser/tst/dirtest/gooddir/good_link
Symbolic link
1
parser/tst/dirtest/gooddir/good_link
Symbolic link
@@ -0,0 +1 @@
|
||||
../goodtarget
|
2
parser/tst/dirtest/gooddir/profileA
Normal file
2
parser/tst/dirtest/gooddir/profileA
Normal file
@@ -0,0 +1,2 @@
|
||||
profile a_profile {
|
||||
}
|
2
parser/tst/dirtest/gooddir/profileB
Normal file
2
parser/tst/dirtest/gooddir/profileB
Normal file
@@ -0,0 +1,2 @@
|
||||
profile b_profile {
|
||||
}
|
2
parser/tst/dirtest/goodtarget
Normal file
2
parser/tst/dirtest/goodtarget
Normal file
@@ -0,0 +1,2 @@
|
||||
profile good_target {
|
||||
}
|
@@ -96,7 +96,7 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
|
||||
sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr,
|
||||
close_fds=True, preexec_fn=subprocess_setup, universal_newlines=True)
|
||||
except OSError as e:
|
||||
return [127, str(e)]
|
||||
return [127, str(e), '']
|
||||
|
||||
timeout_communicate = TimeoutFunction(sp.communicate, timeout)
|
||||
out, outerr = (None, None)
|
||||
@@ -180,7 +180,7 @@ def read_features_dir(path):
|
||||
if not os.path.exists(path) or not os.path.isdir(path):
|
||||
return result
|
||||
|
||||
for name in os.listdir(path):
|
||||
for name in sorted(os.listdir(path)):
|
||||
entry = os.path.join(path, name)
|
||||
result += '%s {' % name
|
||||
if os.path.isfile(entry):
|
||||
|
@@ -41,7 +41,7 @@ ifdef USE_SYSTEM
|
||||
LOGPROF?=aa-logprof
|
||||
else
|
||||
# PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
|
||||
PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")
|
||||
PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import sysconfig; print(\"lib.%s-%s\" %(sysconfig.get_platform(), sysconfig.get_python_version()))")
|
||||
LIBAPPARMOR_PATH=../libraries/libapparmor/src/.libs/
|
||||
LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
|
||||
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
|
||||
|
@@ -6,6 +6,10 @@
|
||||
|
||||
include <abstractions/nameservice>
|
||||
|
||||
# Allow other processes to read our /proc entries
|
||||
ptrace (readby),
|
||||
# Allow other processes to trace us by default
|
||||
ptrace (tracedby),
|
||||
# Allow unconfined processes to send us signals by default
|
||||
signal (receive) peer=unconfined,
|
||||
# Allow apache to send us signals by default
|
||||
|
55
profiles/apparmor.d/abstractions/gtk
Normal file
55
profiles/apparmor.d/abstractions/gtk
Normal file
@@ -0,0 +1,55 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
/usr/share/themes/{,**} r,
|
||||
|
||||
/usr/share/gtksourceview-[0-9]*/{,**} r,
|
||||
|
||||
/usr/share/gtk-2.0/ r,
|
||||
/usr/share/gtk-2.0/gtkrc r,
|
||||
|
||||
/usr/share/gtk-{3,4}.0/ r,
|
||||
/usr/share/gtk-{3,4}.0/settings.ini r,
|
||||
|
||||
/etc/gtk-2.0/ r,
|
||||
/etc/gtk-2.0/gtkrc r,
|
||||
|
||||
/etc/gtk-{3,4}.0/ r,
|
||||
/etc/gtk-{3,4}.0/*.conf r,
|
||||
|
||||
/etc/gtk/gtkrc r,
|
||||
|
||||
owner @{HOME}/.themes/{,**} r,
|
||||
owner @{HOME}/.local/share/themes/{,**} r,
|
||||
|
||||
owner @{HOME}/.gtk r,
|
||||
owner @{HOME}/.gtkrc r,
|
||||
owner @{HOME}/.gtkrc-2.0 r,
|
||||
owner @{HOME}/.gtk-bookmarks r,
|
||||
owner @{HOME}/.config/gtkrc r,
|
||||
owner @{HOME}/.config/gtkrc-2.0 r,
|
||||
owner @{HOME}/.config/gtk-{3,4}.0/ rw,
|
||||
owner @{HOME}/.config/gtk-{3,4}.0/settings.ini r,
|
||||
owner @{HOME}/.config/gtk-{3,4}.0/bookmarks r,
|
||||
owner @{HOME}/.config/gtk-{3,4}.0/gtk.css r,
|
||||
|
||||
# for gtk file dialog
|
||||
owner @{HOME}/.config/gtk-2.0/ rw,
|
||||
owner @{HOME}/.config/gtk-2.0/gtkfilechooser.ini* rw,
|
||||
|
||||
# .Xauthority file required for X connections
|
||||
owner @{HOME}/.Xauthority r,
|
||||
|
||||
# Xsession errors file
|
||||
owner @{HOME}/.xsession-errors w,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/gtk.d>
|
@@ -16,5 +16,14 @@
|
||||
owner @{HOME}/.config/ibus/bus/ rw,
|
||||
owner @{HOME}/.config/ibus/bus/* rw,
|
||||
|
||||
# abstract path in ibus >= 1.5.22 uses $XDG_CACHE_HOME (ie, @{HOME}/.cache)
|
||||
# This should use this, but due to LP: #1856738 we cannot
|
||||
#unix (connect, receive, send)
|
||||
# type=stream
|
||||
# peer=(addr="@@{HOME}/.cache/ibus/dbus-*"),
|
||||
unix (connect, receive, send)
|
||||
type=stream
|
||||
peer=(addr="@/home/*/.cache/ibus/dbus-*"),
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/ibus.d>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
# (src/intel/perf/gen_perf.c, load_oa_metrics())
|
||||
@{PROC}/sys/dev/i915/perf_stream_paranoid r,
|
||||
|
||||
@{sys}/devices/pci[0-9]*/**/{revision,config} r,
|
||||
|
||||
# User files
|
||||
owner @{HOME}/.cache/ w, # if user clears all caches
|
||||
owner @{HOME}/.cache/mesa_shader_cache/ rw,
|
||||
|
@@ -24,6 +24,7 @@
|
||||
@{run}/systemd/userdb/io.systemd.DynamicUser rw, # systemd-exec users
|
||||
@{run}/systemd/userdb/io.systemd.Home rw, # systemd-home dirs
|
||||
@{run}/systemd/userdb/io.systemd.NameServiceSwitch rw, # UNIX/glibc NSS
|
||||
@{run}/systemd/userdb/io.systemd.Machine rw, # systemd-machined
|
||||
|
||||
@{PROC}/sys/kernel/random/boot_id r,
|
||||
|
||||
|
@@ -11,6 +11,8 @@
|
||||
abi <abi/3.0>,
|
||||
|
||||
/etc/ssl/openssl.cnf r,
|
||||
/etc/ssl/{engdef,engines}.d/ r,
|
||||
/etc/ssl/{engdef,engines}.d/*.cnf r,
|
||||
/usr/share/ssl/openssl.cnf r,
|
||||
@{PROC}/sys/crypto/fips_enabled r,
|
||||
|
||||
|
@@ -13,8 +13,7 @@
|
||||
abi <abi/3.0>,
|
||||
|
||||
# shared snippets for config files
|
||||
/etc/php{,5,7,8}/**/ r,
|
||||
/etc/php{,5,7,8}/**.ini r,
|
||||
/etc/php{,5,7,8}/** r,
|
||||
|
||||
# Xlibs
|
||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||
|
@@ -12,18 +12,17 @@
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so} mr,
|
||||
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth} r,
|
||||
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
|
||||
/usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
|
||||
|
||||
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{pyc,so} mr,
|
||||
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{egg,py,pth} r,
|
||||
/usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/{site,dist}-packages/ r,
|
||||
/usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{pyc,so,so.*[0-9]} mr,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{egg,py,pth} r,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/**/ r,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/*.dist-info/{METADATA,namespace_packages.txt} r,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/*.VERSION r,
|
||||
/usr/{local/,}lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/*.egg-info/PKG-INFO r,
|
||||
/usr/{local/,}lib{,32,64}/python3.{1,}[0-9]/lib-dynload/*.so mr,
|
||||
|
||||
# Site-wide configuration
|
||||
/etc/python{2.[4-7],3.[0-9]}/** r,
|
||||
/etc/python{2.[4-7],3.[0-9],3.1[0-9]}/** r,
|
||||
|
||||
# shared python paths
|
||||
/usr/share/{pyshared,pycentral,python-support}/** r,
|
||||
@@ -36,7 +35,7 @@
|
||||
/usr/lib/wx/python/*.pth r,
|
||||
|
||||
# python build configuration and headers
|
||||
/usr/include/python{2.[4-7],3.[0-9]}*/pyconfig.h r,
|
||||
/usr/include/python{2.[4-7],3.[0-9],3.1[0-9]}*/pyconfig.h r,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/python.d>
|
||||
|
@@ -13,6 +13,8 @@
|
||||
|
||||
/etc/samba/* r,
|
||||
/usr/lib*/ldb/*.so mr,
|
||||
/usr/lib*/ldb2/*.so mr,
|
||||
/usr/lib*/ldb2/modules/ldb/*.so mr,
|
||||
/usr/lib*/samba/ldb/*.so mr,
|
||||
/usr/share/samba/*.dat r,
|
||||
/usr/share/samba/codepages/{lowcase,upcase,valid}.dat r,
|
||||
@@ -22,15 +24,17 @@
|
||||
/var/log/samba/cores/ rw,
|
||||
/var/log/samba/cores/** rw,
|
||||
/var/log/samba/* w,
|
||||
@{run}/samba/ w,
|
||||
@{run}/samba/*.tdb rw,
|
||||
@{run}/samba/msg.lock/ rwk,
|
||||
@{run}/samba/msg.lock/[0-9]* rwk,
|
||||
@{run}/{,lock/}samba/ w,
|
||||
@{run}/{,lock/}samba/*.tdb rw,
|
||||
@{run}/{,lock/}samba/msg.lock/ rwk,
|
||||
@{run}/{,lock/}samba/msg.lock/[0-9]* rwk,
|
||||
/var/cache/samba/msg.lock/ rwk,
|
||||
/var/cache/samba/msg.lock/[0-9]* rwk,
|
||||
|
||||
# required for clustering
|
||||
/var/lib/ctdb/** rwk,
|
||||
|
||||
deny capability net_admin, # noisy setsockopt() calls from systemd
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/samba.d>
|
||||
|
30
profiles/apparmor.d/abstractions/samba-rpcd
Normal file
30
profiles/apparmor.d/abstractions/samba-rpcd
Normal file
@@ -0,0 +1,30 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2022 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
# This file contains basic permissions for samba rpcd_xyz services
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/samba>
|
||||
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
signal receive set=term peer=smbd,
|
||||
|
||||
@{PROC}/sys/kernel/core_pattern r,
|
||||
owner @{PROC}/@{pid}/fd/ r,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/samba-rpcd.d>
|
||||
|
42
profiles/apparmor.d/abstractions/snap_browsers
Normal file
42
profiles/apparmor.d/abstractions/snap_browsers
Normal file
@@ -0,0 +1,42 @@
|
||||
profile snap_browsers {
|
||||
include if exists <abstractions/snap_browsers.d>
|
||||
include <abstractions/base>
|
||||
include <abstractions/dbus-session-strict>
|
||||
|
||||
/etc/passwd r,
|
||||
/etc/nsswitch.conf r,
|
||||
/etc/fstab r,
|
||||
|
||||
# noisy
|
||||
deny owner /run/user/[0-9]*/gdm/Xauthority r, # not needed on Ubuntu
|
||||
|
||||
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/bin/snap mrix, # re-exec
|
||||
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/info r,
|
||||
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snapd r,
|
||||
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snap-seccomp rPix,
|
||||
/{,snap/core/[0-9]*/,snap/snapd/[0-9]*/}usr/lib/snapd/snap-confine Pix,
|
||||
/var/lib/snapd/system-key r,
|
||||
/run/snapd.socket rw,
|
||||
|
||||
@{PROC}/version r,
|
||||
@{PROC}/cmdline r,
|
||||
@{PROC}/sys/net/core/somaxconn r,
|
||||
@{PROC}/sys/kernel/seccomp/actions_avail r,
|
||||
@{PROC}/sys/kernel/random/uuid r,
|
||||
owner @{PROC}/@{pid}/cgroup r,
|
||||
owner @{PROC}/@{pid}/mountinfo r,
|
||||
owner @{HOME}/.snap/auth.json r, # if exists, required
|
||||
|
||||
dbus send bus="session" path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager" member="StartTransientUnit" peer=(name="org.freedesktop.systemd1"),
|
||||
dbus receive bus="session" path="/org/freedesktop/systemd1" interface="org.freedesktop.systemd1.Manager" member="JobRemoved",
|
||||
|
||||
/sys/kernel/security/apparmor/features/ r,
|
||||
|
||||
# allow launching official browser snaps.
|
||||
/snap/chromium/[0-9]*/meta/{snap.yaml,hooks/} r,
|
||||
/snap/firefox/[0-9]*/meta/{snap.yaml,hooks/} r,
|
||||
/snap/opera/[0-9]*/meta/{snap.yaml,hooks/} r,
|
||||
|
||||
/var/lib/snapd/sequence/{chromium,firefox,opera}.json r,
|
||||
# add other browsers here
|
||||
}
|
@@ -15,8 +15,9 @@
|
||||
/etc/{,libre}ssl/ r,
|
||||
/etc/{,libre}ssl/cert.pem r,
|
||||
/etc/{,libre}ssl/certs/{,**} r,
|
||||
/etc/pki/trust/{,*} r,
|
||||
/etc/pki/trust/anchors/{,**} r,
|
||||
/{etc,usr/share}/pki/bl[ao]cklist/{,*} r,
|
||||
/{etc,usr/share}/pki/trust/{,*} r,
|
||||
/{etc,usr/share}/pki/trust/anchors/{,**} r,
|
||||
/usr/share/ca-certificates/{,**} r,
|
||||
/usr/share/ssl/certs/ca-bundle.crt r,
|
||||
/usr/local/share/ca-certificates/{,**} r,
|
||||
|
@@ -72,6 +72,7 @@ profile sanitized_helper {
|
||||
/opt/google/chrome{,-beta,-unstable}/chrome-sandbox PUxr,
|
||||
/opt/google/chrome{,-beta,-unstable}/google-chrome Pixr,
|
||||
/opt/google/chrome{,-beta,-unstable}/chrome Pixr,
|
||||
/opt/google/chrome{,-beta,-unstable}/chrome_crashpad_handler Pixr,
|
||||
/opt/google/chrome{,-beta,-unstable}/{,**/}lib*.so{,.*} m,
|
||||
|
||||
# The same is needed for Brave
|
||||
|
@@ -4,7 +4,7 @@
|
||||
abi <abi/3.0>,
|
||||
|
||||
# System devices
|
||||
@{sys}/class/video4linux r,
|
||||
@{sys}/class/video4linux/ r,
|
||||
@{sys}/class/video4linux/** r,
|
||||
|
||||
# Include additions to the abstraction
|
||||
|
@@ -18,7 +18,7 @@ profile lsb_release {
|
||||
/dev/tty rw,
|
||||
|
||||
/usr/bin/lsb_release r,
|
||||
/usr/bin/python3.[0-9] mr,
|
||||
/usr/bin/python3.{1,}[0-9] mr,
|
||||
|
||||
/etc/debian_version r,
|
||||
/etc/default/apport r,
|
||||
|
@@ -16,8 +16,6 @@ profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
|
||||
# read the system certificates
|
||||
include <abstractions/ssl_certs>
|
||||
|
||||
/etc/php{,5,7}/** r,
|
||||
|
||||
capability net_admin,
|
||||
# change user/group of a pool
|
||||
capability setuid,
|
||||
|
23
profiles/apparmor.d/samba-bgqd
Normal file
23
profiles/apparmor.d/samba-bgqd
Normal file
@@ -0,0 +1,23 @@
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile samba-bgqd /usr/lib*/samba/{,samba/}samba-bgqd {
|
||||
include <abstractions/base>
|
||||
include <abstractions/cups-client>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/openssl>
|
||||
include <abstractions/samba>
|
||||
|
||||
signal receive set=term peer=smbd,
|
||||
|
||||
@{PROC}/sys/kernel/core_pattern r,
|
||||
owner @{PROC}/@{pid}/fd/ r,
|
||||
|
||||
@{run}/samba/samba-bgqd.pid wk,
|
||||
|
||||
/usr/lib*/samba/{,samba/}samba-bgqd m,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/samba-bgqd>
|
||||
}
|
31
profiles/apparmor.d/samba-dcerpcd
Normal file
31
profiles/apparmor.d/samba-dcerpcd
Normal file
@@ -0,0 +1,31 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2022 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile samba-dcerpcd /usr/lib*/samba/{,samba/}samba-dcerpcd {
|
||||
include <abstractions/samba-rpcd>
|
||||
|
||||
@{run}/samba/samba-dcerpcd.pid wk,
|
||||
|
||||
/usr/lib*/samba/{,samba/}samba-dcerpcd m,
|
||||
|
||||
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} Px -> samba-rpcd,
|
||||
/usr/lib*/samba/{,samba/}rpcd_classic Px -> samba-rpcd-classic,
|
||||
/usr/lib*/samba/{,samba/}rpcd_spoolss Px -> samba-rpcd-spoolss,
|
||||
|
||||
@{run}/samba/ncalrpc/ rw,
|
||||
@{run}/samba/ncalrpc/** rw,
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/samba-dcerpcd>
|
||||
}
|
21
profiles/apparmor.d/samba-rpcd
Normal file
21
profiles/apparmor.d/samba-rpcd
Normal file
@@ -0,0 +1,21 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2022 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile samba-rpcd /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} {
|
||||
include <abstractions/samba-rpcd>
|
||||
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} m,
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/samba-rpcd>
|
||||
}
|
24
profiles/apparmor.d/samba-rpcd-classic
Normal file
24
profiles/apparmor.d/samba-rpcd-classic
Normal file
@@ -0,0 +1,24 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2022 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile samba-rpcd-classic /usr/lib*/samba/{,samba/}rpcd_classic {
|
||||
include <abstractions/samba-rpcd>
|
||||
include <abstractions/wutmp>
|
||||
|
||||
/usr/lib*/samba/{,samba/}rpcd_classic m,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/samba-rpcd-classic>
|
||||
}
|
24
profiles/apparmor.d/samba-rpcd-spoolss
Normal file
24
profiles/apparmor.d/samba-rpcd-spoolss
Normal file
@@ -0,0 +1,24 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2022 SUSE LLC
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
abi <abi/3.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile samba-rpcd-spoolss /usr/lib*/samba/{,samba/}rpcd_spoolss {
|
||||
include <abstractions/samba-rpcd>
|
||||
|
||||
/usr/lib*/samba/{,samba/}rpcd_spoolss m,
|
||||
/usr/lib*/samba/{,samba/}samba-bgqd Px -> samba-bgqd,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/samba-rpcd-spoolss>
|
||||
}
|
@@ -30,12 +30,16 @@ profile syslogd /{usr/,}{bin,sbin}/syslogd {
|
||||
|
||||
/dev/log wl,
|
||||
/var/lib/*/dev/log wl,
|
||||
/proc/kmsg r,
|
||||
|
||||
/dev/tty* w,
|
||||
/dev/xconsole rw,
|
||||
/etc/syslog.conf r,
|
||||
/etc/syslog.d/ r,
|
||||
/etc/syslog.d/* r,
|
||||
/{usr/,}{bin,sbin}/syslogd rmix,
|
||||
/var/log/** rw,
|
||||
@{run}/syslog.pid krwl,
|
||||
@{run}/syslogd.pid krwl,
|
||||
@{run}/utmp rw,
|
||||
/var/spool/compaq/nic/messages_fifo rw,
|
||||
|
@@ -36,6 +36,7 @@ profile dovecot-imap /usr/lib/dovecot/imap {
|
||||
|
||||
owner /tmp/dovecot.imap.* rw,
|
||||
@{PROC}/@{pid}/attr/{apparmor/,}current rw,
|
||||
@{PROC}/@{pid}/stat r,
|
||||
/usr/bin/doveconf rix,
|
||||
/usr/lib/dovecot/imap mrix,
|
||||
/usr/share/dovecot/** r,
|
||||
|
@@ -31,6 +31,8 @@ profile dovecot-lmtp /usr/lib/dovecot/lmtp {
|
||||
|
||||
@{HOME}/.dovecot.svbin r,
|
||||
@{PROC}/@{pid}/attr/{apparmor/,}current rw,
|
||||
owner @{PROC}/@{pid}/io r,
|
||||
owner @{PROC}/@{pid}/stat r,
|
||||
@{PROC}/*/mounts r,
|
||||
/tmp/dovecot.lmtp.* rw,
|
||||
/usr/lib/dovecot/lmtp mr,
|
||||
|
@@ -26,6 +26,7 @@ profile dovecot-pop3 /usr/lib/dovecot/pop3 {
|
||||
@{DOVECOT_MAILSTORE}/** rwkl,
|
||||
|
||||
@{HOME} r, # ???
|
||||
@{PROC}/@{pid}/stat r,
|
||||
/usr/lib/dovecot/pop3 mr,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
|
@@ -22,6 +22,9 @@ profile avahi-daemon /usr/{bin,sbin}/avahi-daemon {
|
||||
/etc/avahi/services/ r,
|
||||
/etc/avahi/services/*.service r,
|
||||
@{PROC}/@{pid}/fd/ r,
|
||||
@{PROC}/1/environ r,
|
||||
@{PROC}/cmdline r,
|
||||
@{PROC}/sys/kernel/osrelease r,
|
||||
/usr/{bin,sbin}/avahi-daemon mr,
|
||||
/usr/share/avahi/introspection/*.introspect r,
|
||||
/usr/share/dbus-1/interfaces/org.freedesktop.Avahi.*.xml r,
|
||||
|
@@ -107,6 +107,11 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
||||
@{run}/NetworkManager/dnsmasq.pid w,
|
||||
@{run}/NetworkManager/NetworkManager.pid w,
|
||||
|
||||
# dnsname plugin in podman
|
||||
@{run}/containers/cni/dnsname/*/dnsmasq.conf r,
|
||||
@{run}/containers/cni/dnsname/*/addnhosts r,
|
||||
@{run}/containers/cni/dnsname/*/pidfile rw,
|
||||
|
||||
profile libvirt_leaseshelper {
|
||||
include <abstractions/base>
|
||||
|
||||
|
@@ -33,8 +33,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
capability sys_chroot,
|
||||
capability sys_resource,
|
||||
|
||||
signal send set=(int,quit,term,kill) peer=/usr/lib/dovecot/*,
|
||||
signal send set=(int,quit,term,kill) peer=dovecot-*,
|
||||
signal send peer=/usr/lib/dovecot/*,
|
||||
signal send peer=dovecot-*,
|
||||
|
||||
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
|
||||
unix (receive, send) type=stream peer=(label=dovecot-anvil),
|
||||
|
@@ -8,6 +8,7 @@ profile smbd /usr/{bin,sbin}/smbd {
|
||||
include <abstractions/consoles>
|
||||
include <abstractions/cups-client>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/openssl>
|
||||
include <abstractions/samba>
|
||||
include <abstractions/user-tmp>
|
||||
include <abstractions/wutmp>
|
||||
@@ -24,6 +25,8 @@ profile smbd /usr/{bin,sbin}/smbd {
|
||||
capability sys_resource,
|
||||
capability sys_tty_config,
|
||||
|
||||
signal send set=term peer=samba-bgqd,
|
||||
|
||||
/etc/mtab r,
|
||||
/etc/netgroup r,
|
||||
/etc/printcap r,
|
||||
@@ -35,10 +38,13 @@ profile smbd /usr/{bin,sbin}/smbd {
|
||||
/usr/lib*/samba/charset/*.so mr,
|
||||
/usr/lib*/samba/gensec/*.so mr,
|
||||
/usr/lib*/samba/pdb/*.so mr,
|
||||
/usr/lib*/samba/{,samba/}samba-bgqd Px -> samba-bgqd,
|
||||
/usr/lib*/samba/{,samba/}samba-dcerpcd Px -> samba-dcerpcd,
|
||||
/usr/lib*/samba/{lowcase,upcase,valid}.dat r,
|
||||
/usr/lib/@{multiarch}/samba/*.so{,.[0-9]*} mr,
|
||||
/usr/lib/@{multiarch}/samba/**/ r,
|
||||
/usr/lib/@{multiarch}/samba/**/*.so{,.[0-9]*} mr,
|
||||
/usr/share/samba/** r,
|
||||
/usr/{bin,sbin}/smbd mr,
|
||||
/usr/{bin,sbin}/smbldap-useradd Px,
|
||||
/var/cache/samba/** rwk,
|
||||
@@ -56,6 +62,11 @@ profile smbd /usr/{bin,sbin}/smbd {
|
||||
@{HOMEDIRS}/** lrwk,
|
||||
/var/lib/samba/usershares/{,**} lrwk,
|
||||
|
||||
# Permissions for all configured shares (file autogenerated by
|
||||
# update-apparmor-samba-profile on service startup on Debian and openSUSE)
|
||||
include if exists <samba/smbd-shares>
|
||||
include if exists <local/usr.sbin.smbd-shares>
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/usr.sbin.smbd>
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ profile winbindd /usr/{bin,sbin}/winbindd {
|
||||
/usr/lib*/samba/idmap/*.so mr,
|
||||
/usr/lib*/samba/nss_info/*.so mr,
|
||||
/usr/lib*/samba/pdb/*.so mr,
|
||||
/usr/lib*/samba/{,samba/}samba-dcerpcd Px -> samba-dcerpcd,
|
||||
/usr/{bin,sbin}/winbindd mr,
|
||||
/var/cache/krb5rcache/* rwk,
|
||||
/var/cache/samba/*.tdb rwk,
|
||||
|
@@ -14,6 +14,7 @@ include <tunables/global>
|
||||
|
||||
profile rpc.statd /{usr/,}sbin/rpc.statd {
|
||||
include <abstractions/base>
|
||||
include <abstractions/hosts_access>
|
||||
include <abstractions/nameservice>
|
||||
|
||||
# needed to sanely drop privileges
|
||||
@@ -32,6 +33,9 @@ profile rpc.statd /{usr/,}sbin/rpc.statd {
|
||||
@{PROC}/sys/fs/nfs/nsm_local_state w,
|
||||
|
||||
/etc/netconfig r,
|
||||
/etc/nfs.conf rk,
|
||||
/etc/nfs.conf.d/ r,
|
||||
/etc/nfs.conf.d/* rk,
|
||||
/etc/rpc r,
|
||||
/{usr/,}sbin/rpc.statd mrix,
|
||||
/{usr/,}sbin/sm-notify mrix,
|
||||
@@ -46,7 +50,7 @@ profile rpc.statd /{usr/,}sbin/rpc.statd {
|
||||
/var/lib/nfs/statd/sm.bak/* rwl,
|
||||
/var/lib/nfs/state rwk,
|
||||
/var/lib/nfs/state.new rwl,
|
||||
/{,var/}run/rpc.statd.pid w,
|
||||
/{,var/}run/rpcbind.sock rw,
|
||||
/{,var/}run/sm-notify.pid w,
|
||||
@{run}/rpc.statd.pid w,
|
||||
@{run}/rpcbind.sock rw,
|
||||
@{run}/sm-notify.pid w,
|
||||
}
|
||||
|
@@ -267,9 +267,9 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
||||
/usr/share/distro-info/** r,
|
||||
/var/lib/dpkg/** r,
|
||||
|
||||
/usr/local/lib/python3.[0-9]/dist-packages/ r,
|
||||
/usr/local/lib/python3.{1,}[0-9]/dist-packages/ r,
|
||||
/usr/bin/ r,
|
||||
/usr/bin/python3.[0-9] mr,
|
||||
/usr/bin/python3.{1,}[0-9] mr,
|
||||
}
|
||||
|
||||
profile sandbox {
|
||||
|
@@ -72,6 +72,7 @@ clean: pod_clean
|
||||
rm -rf staging/ build/
|
||||
rm -f apparmor/*.pyc apparmor/rule/*.pyc
|
||||
rm -rf apparmor/__pycache__/ apparmor/rule/__pycache__/
|
||||
rm -rf apparmor.egg-info/
|
||||
|
||||
# ${CAPABILITIES} is defined in common/Make.rules
|
||||
.PHONY: check_severity_db
|
||||
|
@@ -34,7 +34,6 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
import notify2
|
||||
import psutil
|
||||
import pwd
|
||||
@@ -45,6 +44,7 @@ import apparmor.ui as aaui
|
||||
import apparmor.config as aaconfig
|
||||
from apparmor.common import DebugLogger, open_file_read
|
||||
from apparmor.fail import enable_aa_exception_handler
|
||||
from apparmor.notify import get_last_login_timestamp
|
||||
from apparmor.translations import init_translation
|
||||
|
||||
import LibAppArmor # C-library to parse one log line
|
||||
@@ -61,48 +61,6 @@ def get_user_login():
|
||||
return username
|
||||
|
||||
|
||||
def get_last_login_timestamp(username):
|
||||
'''Directly read wtmp and get last login for user as epoch timestamp'''
|
||||
timestamp = 0
|
||||
filename = '/var/log/wtmp'
|
||||
last_login = 0
|
||||
|
||||
debug_logger.debug('Username: {}'.format(username))
|
||||
|
||||
with open(filename, "rb") as wtmp_file:
|
||||
offset = 0
|
||||
wtmp_filesize = os.path.getsize(filename)
|
||||
debug_logger.debug('WTMP filesize: {}'.format(wtmp_filesize))
|
||||
while offset < wtmp_filesize:
|
||||
wtmp_file.seek(offset)
|
||||
offset += 384 # Increment for next entry
|
||||
|
||||
type = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
debug_logger.debug('WTMP entry type: {}'.format(type))
|
||||
|
||||
# Only parse USER lines
|
||||
if type == 7:
|
||||
# Read each item and move pointer forward
|
||||
pid = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
line = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
id = wtmp_file.read(4).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
user = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
host = wtmp_file.read(256).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
term = struct.unpack("<H", wtmp_file.read(2))[0]
|
||||
exit = struct.unpack("<H", wtmp_file.read(2))[0]
|
||||
session = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
timestamp = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
usec = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
entry = (pid, line, id, user, host, term, exit, session, timestamp, usec)
|
||||
debug_logger.debug('WTMP entry: {}'.format(entry))
|
||||
|
||||
# Store login timestamp for requested user
|
||||
if user == username:
|
||||
last_login = timestamp
|
||||
|
||||
# When loop is done, last value should be the latest login timestamp
|
||||
return last_login
|
||||
|
||||
|
||||
def format_event(event, logsource):
|
||||
output = []
|
||||
@@ -324,7 +282,7 @@ def parse_logdata(logsource):
|
||||
event = LibAppArmor.parse_record(entry)
|
||||
# Only show actual events of contained programs and ignore among
|
||||
# others AppArmor profile reloads
|
||||
if event.operation[0:8] != 'profile_':
|
||||
if event.operation and event.operation[0:8] != 'profile_':
|
||||
yield event
|
||||
|
||||
|
||||
|
9
utils/aa-notify.desktop
Normal file
9
utils/aa-notify.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=AppArmor Notify
|
||||
Comment=Receive on screen notifications of AppArmor denials
|
||||
TryExec=/usr/bin/aa-notify
|
||||
Exec=/usr/bin/aa-notify -p -s 1 -w 60
|
||||
StartupNotify=false
|
||||
NoDisplay=true
|
||||
X-Ubuntu-Gettext-Domain=aa-notify
|
@@ -78,7 +78,14 @@ fi
|
||||
# parent. We *do* need to remove the child profile and not rely
|
||||
# on removing the parent profile when the profile has had its
|
||||
# child profile names changed.
|
||||
profiles_names_list | awk '
|
||||
|
||||
LOADED_PROFILES=$("$PARSER" -N $PROFILE_DIRS) || {
|
||||
ret=$?
|
||||
echo 'apparmor_parser exited with failure, aborting.' >&2
|
||||
exit $ret
|
||||
}
|
||||
|
||||
echo "$LOADED_PROFILES" | awk '
|
||||
BEGIN {
|
||||
while (getline < "'${PROFILES}'" ) {
|
||||
str = sub(/ \((enforce|complain)\)$/, "", $0);
|
||||
|
@@ -127,8 +127,10 @@ for pid in sorted(map(int, pids)):
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
attr = read_proc_current("/proc/%s/attr/apparmor/current" % pid)
|
||||
if not attr:
|
||||
if os.path.exists("/proc/%s/attr/apparmor/current" % pid):
|
||||
attr = read_proc_current("/proc/%s/attr/apparmor/current" % pid)
|
||||
else:
|
||||
# fallback to shared attr/current if attr/apparmor/current doesn't exist
|
||||
attr = read_proc_current("/proc/%s/attr/current" % pid)
|
||||
|
||||
pname = None
|
||||
|
104
utils/apparmor/notify.py
Normal file
104
utils/apparmor/notify.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2018–2019 Otto Kekäläinen <otto@kekalainen.net>
|
||||
# Copyright (C) 2021 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as 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.
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import struct
|
||||
|
||||
from apparmor.common import AppArmorBug, DebugLogger
|
||||
|
||||
debug_logger = DebugLogger('apparmor.notify')
|
||||
|
||||
|
||||
def sane_timestamp(timestamp):
|
||||
''' Check if the given timestamp is in a date range that makes sense for a wtmp file '''
|
||||
|
||||
if timestamp < 946681200: # 2000-01-01
|
||||
return False
|
||||
elif timestamp > 2524604400: # 2050-01-01
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_last_login_timestamp(username, filename='/var/log/wtmp'):
|
||||
'''Directly read wtmp and get last login for user as epoch timestamp'''
|
||||
timestamp = 0
|
||||
last_login = 0
|
||||
|
||||
debug_logger.debug('Username: {}'.format(username))
|
||||
|
||||
with open(filename, "rb") as wtmp_file:
|
||||
offset = 0
|
||||
wtmp_filesize = os.path.getsize(filename)
|
||||
debug_logger.debug('WTMP filesize: {}'.format(wtmp_filesize))
|
||||
|
||||
if wtmp_filesize < 356:
|
||||
return 0 # (nearly) empty wtmp file, no entries
|
||||
|
||||
# detect architecture based on utmp format differences
|
||||
wtmp_file.seek(340) # first possible timestamp position
|
||||
timestamp_x86_64 = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
timestamp_aarch64 = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
timestamp_s390x = struct.unpack(">L", wtmp_file.read(4))[0]
|
||||
debug_logger.debug('WTMP timestamps: x86_64 %s, aarch64 %s, s390x %s' % (timestamp_x86_64, timestamp_aarch64, timestamp_s390x))
|
||||
|
||||
if sane_timestamp(timestamp_x86_64):
|
||||
endianness = '<' # little endian
|
||||
extra_offset_before = 0
|
||||
extra_offset_after = 0
|
||||
elif sane_timestamp(timestamp_aarch64):
|
||||
endianness = '<' # little endian
|
||||
extra_offset_before = 4
|
||||
extra_offset_after = 12
|
||||
elif sane_timestamp(timestamp_s390x):
|
||||
endianness = '>' # big endian
|
||||
extra_offset_before = 8
|
||||
extra_offset_after = 8
|
||||
else:
|
||||
raise AppArmorBug('Your /var/log/wtmp is broken or has an unknown format. Please open a bugreport with /var/log/wtmp and the output of "last" attached!')
|
||||
|
||||
while offset < wtmp_filesize:
|
||||
wtmp_file.seek(offset)
|
||||
offset += 384 + extra_offset_before + extra_offset_after # Increment for next entry
|
||||
|
||||
type = struct.unpack('%sH' % endianness, wtmp_file.read(2))[0]
|
||||
debug_logger.debug('WTMP entry type: {}'.format(type))
|
||||
wtmp_file.read(2) # skip padding
|
||||
|
||||
# Only parse USER lines
|
||||
if type == 7:
|
||||
# Read each item and move pointer forward
|
||||
pid = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
line = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
id = wtmp_file.read(4).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
user = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
host = wtmp_file.read(256).decode("utf-8", "replace").split('\0', 1)[0]
|
||||
term = struct.unpack("<H", wtmp_file.read(2))[0]
|
||||
exit = struct.unpack("<H", wtmp_file.read(2))[0]
|
||||
session = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
if extra_offset_before:
|
||||
wtmp_file.read(extra_offset_before)
|
||||
timestamp = struct.unpack('%sL' % endianness, wtmp_file.read(4))[0]
|
||||
if extra_offset_after:
|
||||
wtmp_file.read(extra_offset_after)
|
||||
usec = struct.unpack("<L", wtmp_file.read(4))[0]
|
||||
entry = (pid, line, id, user, host, term, exit, session, timestamp, usec)
|
||||
debug_logger.debug('WTMP entry: {}'.format(entry))
|
||||
|
||||
# Store login timestamp for requested user
|
||||
if user == username:
|
||||
last_login = timestamp
|
||||
|
||||
# When loop is done, last value should be the latest login timestamp
|
||||
return last_login
|
@@ -27,7 +27,7 @@ _ = init_translation()
|
||||
network_domain_keywords = [ 'unspec', 'unix', 'inet', 'ax25', 'ipx', 'appletalk', 'netrom', 'bridge', 'atmpvc', 'x25', 'inet6',
|
||||
'rose', 'netbeui', 'security', 'key', 'netlink', 'packet', 'ash', 'econet', 'atmsvc', 'rds', 'sna',
|
||||
'irda', 'pppox', 'wanpipe', 'llc', 'ib', 'mpls', 'can', 'tipc', 'bluetooth', 'iucv', 'rxrpc', 'isdn',
|
||||
'phonet', 'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'kcm', 'qipcrtr', 'smc', 'xdp' ]
|
||||
'phonet', 'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'kcm', 'qipcrtr', 'smc', 'xdp', 'mctp' ]
|
||||
|
||||
network_type_keywords = ['stream', 'dgram', 'seqpacket', 'rdm', 'raw', 'packet']
|
||||
network_protocol_keywords = ['tcp', 'udp', 'icmp']
|
||||
|
@@ -112,6 +112,18 @@
|
||||
/usr/bin/python3.5 = icn
|
||||
/usr/bin/python3.6 = icn
|
||||
/usr/bin/python3.7 = icn
|
||||
/usr/bin/python3.8 = icn
|
||||
/usr/bin/python3.9 = icn
|
||||
/usr/bin/python3.10 = icn
|
||||
/usr/bin/python3.11 = icn
|
||||
/usr/bin/python3.12 = icn
|
||||
/usr/bin/python3.13 = icn
|
||||
/usr/bin/python3.14 = icn
|
||||
/usr/bin/python3.15 = icn
|
||||
/usr/bin/python3.16 = icn
|
||||
/usr/bin/python3.17 = icn
|
||||
/usr/bin/python3.18 = icn
|
||||
/usr/bin/python3.19 = icn
|
||||
/usr/bin/tr = icn
|
||||
|
||||
[required_hats]
|
||||
|
@@ -20,14 +20,14 @@
|
||||
# Note: --version=... must be the last argument to this script
|
||||
#
|
||||
|
||||
from distutils.command.install import install as _install
|
||||
from distutils.core import setup
|
||||
from setuptools.command.install import install as _install
|
||||
from setuptools import setup
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
class Install(_install, object):
|
||||
'''Override distutils to install the files where we want them.'''
|
||||
'''Override setuptools to install the files where we want them.'''
|
||||
def run(self):
|
||||
# Now byte-compile everything
|
||||
super(Install, self).run()
|
||||
|
@@ -27,8 +27,7 @@ ifdef USE_SYSTEM
|
||||
BASEDIR=
|
||||
PARSER=
|
||||
else
|
||||
# PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
|
||||
PYTHON_DIST_BUILD_PATH = ../../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")
|
||||
PYTHON_DIST_BUILD_PATH = ../../libraries/libapparmor/swig/python/build/$$($(PYTHON) ../../libraries/libapparmor/swig/python/test/buildpath.py)
|
||||
LIBAPPARMOR_PATH=../../libraries/libapparmor/src/.libs/
|
||||
LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
|
||||
PYTHONPATH=..:$(PYTHON_DIST_BUILD_PATH)
|
||||
|
18
utils/test/README.md
Normal file
18
utils/test/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Running individual tests
|
||||
|
||||
Python's unittest allows individual tests to be executed by specifying the class name and the test on the command line.
|
||||
When running tests individually, the unittest framework executes the "setUp" and "tearDown" methods automatically.
|
||||
For more information, refer to the [unittest documentation](https://docs.python.org/3/library/unittest.html).
|
||||
|
||||
Make sure to set the environment variables pointing to the in-tree apparmor modules, and the in-tree libapparmor and its python wrapper:
|
||||
|
||||
```bash
|
||||
$ export PYTHONPATH=..:../../libraries/libapparmor/swig/python/build/$(/usr/bin/python3 ../../libraries/libapparmor/swig/python/test/buildpath.py)
|
||||
$ export __AA_CONFDIR=.
|
||||
```
|
||||
|
||||
To execute the test individually, run:
|
||||
|
||||
```bash
|
||||
$ python3 ./test-tile.py ClassFoo.test_bar
|
||||
```
|
@@ -148,13 +148,15 @@ Feb 4 13:40:38 XPS-13-9370 kernel: [128552.880347] audit: type=1400 audit({epoc
|
||||
'''Test output of help text'''
|
||||
|
||||
expected_return_code = 0
|
||||
expected_output_is = \
|
||||
expected_output_1 = \
|
||||
'''usage: aa-notify [-h] [-p] [--display DISPLAY] [-f FILE] [-l] [-s NUM] [-v]
|
||||
[-u USER] [-w NUM] [--debug]
|
||||
|
||||
Display AppArmor notifications or messages for DENIED entries.
|
||||
'''
|
||||
|
||||
optional arguments:
|
||||
expected_output_2 = \
|
||||
'''
|
||||
-h, --help show this help message and exit
|
||||
-p, --poll poll AppArmor logs and display notifications
|
||||
--display DISPLAY set the DISPLAY environment variable (might be needed if
|
||||
@@ -174,8 +176,9 @@ optional arguments:
|
||||
return_code, output = cmd([aanotify_bin, '--help'])
|
||||
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code)
|
||||
self.assertEqual(expected_return_code, return_code, result + output)
|
||||
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_is)
|
||||
self.assertEqual(expected_output_is, output, result + output)
|
||||
|
||||
self.assertIn(expected_output_1, output)
|
||||
self.assertIn(expected_output_2, output)
|
||||
|
||||
def test_entries_since_100_days(self):
|
||||
'''Test showing log entries since 100 days'''
|
||||
|
54
utils/test/test-notify.py
Normal file
54
utils/test/test-notify.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2021 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
import unittest
|
||||
from common_test import AATest, setup_all_loops
|
||||
|
||||
from apparmor.common import AppArmorBug
|
||||
from apparmor.notify import get_last_login_timestamp, sane_timestamp
|
||||
|
||||
class TestSane_timestamp(AATest):
|
||||
tests = [
|
||||
(2524704400, False), # Sun Jan 2 03:46:40 CET 2050
|
||||
( 944780400, False), # Fri Dec 10 00:00:00 CET 1999
|
||||
(1635026400, True ), # Sun Oct 24 00:00:00 CEST 2021
|
||||
]
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(sane_timestamp(params), expected)
|
||||
|
||||
class TestGet_last_login_timestamp(AATest):
|
||||
tests = [
|
||||
(['wtmp-x86_64', 'root' ], 1635070346), # Sun Oct 24 12:12:26 CEST 2021
|
||||
(['wtmp-x86_64', 'whoever' ], 0),
|
||||
(['wtmp-s390x', 'root' ], 1626368763), # Thu Jul 15 19:06:03 CEST 2021
|
||||
(['wtmp-s390x', 'linux1' ], 1626368772), # Thu Jul 15 19:06:12 CEST 2021
|
||||
(['wtmp-s390x', 'whoever' ], 0),
|
||||
(['wtmp-aarch64', 'guillaume' ], 1611562789), # Mon Jan 25 09:19:49 CET 2021
|
||||
(['wtmp-aarch64', 'whoever' ], 0),
|
||||
(['wtmp-truncated', 'root' ], 0),
|
||||
(['wtmp-truncated', 'whoever' ], 0),
|
||||
]
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
filename, user = params
|
||||
filename = 'wtmp-examples/%s' % filename
|
||||
self.assertEqual(get_last_login_timestamp(user, filename), expected)
|
||||
|
||||
def test_date_1999(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
# wtmp-x86_64-past is hand-edited to Thu Dec 30 00:00:00 CET 1999, which is outside the expected data range
|
||||
get_last_login_timestamp('root', 'wtmp-examples/wtmp-x86_64-past')
|
||||
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user