mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 07:15:18 +00:00
Compare commits
108 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
027faf20dd | ||
|
b41d34e638 | ||
|
a0df142852 | ||
|
70b764590b | ||
|
6e7a4bac5e | ||
|
e6cfce0309 | ||
|
534185b4ca | ||
|
561a60a3c9 | ||
|
a1fa0ec51d | ||
|
f22e41f8c1 | ||
|
83b7bf3431 | ||
|
dd0d6d3802 | ||
|
b81ad9bb0f | ||
|
48673696a6 | ||
|
8409d7cd61 | ||
|
536959d714 | ||
|
1d17d5399c | ||
|
5642b9b36e | ||
|
ea401061c4 | ||
|
bd315a7039 | ||
|
0e35af4663 | ||
|
d11d2b4922 | ||
|
14f1641ab9 | ||
|
e5c71fd1bf | ||
|
248edc1e88 | ||
|
9cd55ff4a5 | ||
|
4a8223a547 | ||
|
b42e033770 | ||
|
e9f69bca3f | ||
|
6da000f4e4 | ||
|
0f0e268b38 | ||
|
911a4ded2e | ||
|
569423b8e8 | ||
|
d93539fa11 | ||
|
16dc572886 | ||
|
a19951a19f | ||
|
284cfd891c | ||
|
1cf262a026 | ||
|
97bf8be391 | ||
|
b0ace37606 | ||
|
7efbb659a8 | ||
|
8bb8f56f4c | ||
|
7d5e5bfdb8 | ||
|
e220954f5d | ||
|
fe2970ebb6 | ||
|
9139dfd309 | ||
|
ef5da8cecc | ||
|
b51a2d271d | ||
|
f8286feada | ||
|
5700ff9e40 | ||
|
ee0ae96566 | ||
|
67e7b302a4 | ||
|
157c8ee36a | ||
|
d62b5a9a7d | ||
|
3c047517a4 | ||
|
9fff1c5c6a | ||
|
d415e48646 | ||
|
63751d20e2 | ||
|
411249b3b5 | ||
|
8921644ab4 | ||
|
fd1b463643 | ||
|
ca3e5be507 | ||
|
37d938b815 | ||
|
3f4e97e228 | ||
|
7e6df95729 | ||
|
1a3b81857a | ||
|
e3371f871f | ||
|
2d6380c26a | ||
|
5f3f4ba087 | ||
|
4540cb2f50 | ||
|
3cdfe944ac | ||
|
15e5b5c459 | ||
|
3da24e0116 | ||
|
be8ab7d538 | ||
|
b469e1f3e8 | ||
|
2993533d61 | ||
|
5d7b35d30d | ||
|
2686a0af6c | ||
|
9de934c3e7 | ||
|
701943948c | ||
|
47bb1a31b0 | ||
|
898c2cda7a | ||
|
14ed051657 | ||
|
8e04e39b7c | ||
|
552ee5d621 | ||
|
c8e57213f9 | ||
|
44e6f90f23 | ||
|
dd03484866 | ||
|
00396b8f13 | ||
|
3d85e1234a | ||
|
4c8ac78605 | ||
|
17032f2254 | ||
|
de784f55d3 | ||
|
ad0a6ac6bf | ||
|
95aa5b5895 | ||
|
c16fff8cb4 | ||
|
2db3d94ce2 | ||
|
b174705a31 | ||
|
56cc87aace | ||
|
ca0d9f758b | ||
|
a606a59d96 | ||
|
6a8a5de637 | ||
|
1bcf85737b | ||
|
ea55ef22e7 | ||
|
dc3e2c39fb | ||
|
1335b80ff4 | ||
|
1808d14e35 | ||
|
145136f604 |
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
image: ubuntu:latest
|
image: ubuntu:latest
|
||||||
before_script:
|
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
|
- lsb_release -a
|
||||||
- uname -a
|
- uname -a
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
2.13.5
|
2.13.8
|
||||||
|
@@ -58,7 +58,7 @@ if test "$with_perl" = "yes"; then
|
|||||||
AC_PATH_PROG(PERL, perl)
|
AC_PATH_PROG(PERL, perl)
|
||||||
test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings])
|
test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings])
|
||||||
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
|
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
|
||||||
AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no)
|
AS_IF([test -e "$perl_includedir/perl.h"], enable_perl=yes, enable_perl=no)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ variable to configure. See ``configure --help'' for reference.
|
|||||||
# Check if you have distutils, else fail
|
# Check if you have distutils, else fail
|
||||||
#
|
#
|
||||||
AC_MSG_CHECKING([for the distutils Python package])
|
AC_MSG_CHECKING([for the distutils Python package])
|
||||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1 | grep -v DeprecationWarning`
|
||||||
if test -z "$ac_distutils_result"; then
|
if test -z "$ac_distutils_result"; then
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
else
|
else
|
||||||
@@ -75,12 +75,14 @@ $ac_distutils_result])
|
|||||||
PYTHON_VERSION=""
|
PYTHON_VERSION=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_PATH_TOOL([PYTHON_CONFIG],[`basename $PYTHON`-config])
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check for Python include path
|
# Check for Python include path
|
||||||
#
|
#
|
||||||
AC_MSG_CHECKING([for Python include path])
|
AC_MSG_CHECKING([for Python include path])
|
||||||
if type $PYTHON-config; then
|
if test -n "$PYTHON_CONFIG"; then
|
||||||
PYTHON_CPPFLAGS=`$PYTHON-config --includes`
|
PYTHON_CPPFLAGS=`$PYTHON_CONFIG --includes`
|
||||||
fi
|
fi
|
||||||
if test -z "$PYTHON_CPPFLAGS"; then
|
if test -z "$PYTHON_CPPFLAGS"; then
|
||||||
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
|
python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
|
||||||
@@ -97,8 +99,8 @@ sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
|
|||||||
# Check for Python library path
|
# Check for Python library path
|
||||||
#
|
#
|
||||||
AC_MSG_CHECKING([for Python library path])
|
AC_MSG_CHECKING([for Python library path])
|
||||||
if type $PYTHON-config; then
|
if test -n "$PYTHON_CONFIG"; then
|
||||||
PYTHON_LDFLAGS=`$PYTHON-config --ldflags`
|
PYTHON_LDFLAGS=`$PYTHON_CONFIG --ldflags`
|
||||||
fi
|
fi
|
||||||
if test -z "$PYTHON_LDFLAGS"; then
|
if test -z "$PYTHON_LDFLAGS"; then
|
||||||
# (makes two attempts to ensure we've got a version number
|
# (makes two attempts to ensure we've got a version number
|
||||||
|
@@ -27,15 +27,15 @@ INCLUDES = $(all_includes)
|
|||||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||||
#
|
#
|
||||||
AA_LIB_CURRENT = 7
|
AA_LIB_CURRENT = 7
|
||||||
AA_LIB_REVISION = 3
|
AA_LIB_REVISION = 4
|
||||||
AA_LIB_AGE = 7
|
AA_LIB_AGE = 6
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||||
AM_LFLAGS = -v
|
AM_LFLAGS = -v
|
||||||
AM_YFLAGS = -d -p aalogparse_
|
AM_YFLAGS = -d -p aalogparse_
|
||||||
AM_CFLAGS = -Wall
|
AM_CFLAGS = -Wall -flto-partition=none
|
||||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||||
scanner.h: scanner.l
|
scanner.h: scanner.l
|
||||||
$(LEX) -v $<
|
$(LEX) -v $<
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
__asm__ (".symver " #real "," #name "@" #version)
|
__asm__ (".symver " #real "," #name "@" #version)
|
||||||
#define default_symbol_version(real, name, version) \
|
#define default_symbol_version(real, name, version) \
|
||||||
__asm__ (".symver " #real "," #name "@@" #version)
|
__asm__ (".symver " #real "," #name "@@" #version)
|
||||||
|
#define DLLEXPORT __attribute__((visibility("default"),externally_visible))
|
||||||
|
|
||||||
#define UNCONFINED "unconfined"
|
#define UNCONFINED "unconfined"
|
||||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||||
@@ -500,7 +501,7 @@ int aa_change_onexec(const char *profile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
|
/* 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);
|
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
|
||||||
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
||||||
|
|
||||||
@@ -889,7 +890,7 @@ int query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
|||||||
|
|
||||||
/* export multiple aa_query_label symbols to compensate for downstream
|
/* export multiple aa_query_label symbols to compensate for downstream
|
||||||
* releases with differing symbol versions. */
|
* 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);
|
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
|
||||||
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
||||||
|
|
||||||
|
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
IMMUNIX_1.0 {
|
IMMUNIX_1.0 {
|
||||||
global:
|
global:
|
||||||
change_hat;
|
change_hat; __old_change_hat;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
||||||
APPARMOR_1.0 {
|
APPARMOR_1.0 {
|
||||||
global:
|
global:
|
||||||
change_hat;
|
change_hat; __change_hat;
|
||||||
parse_record;
|
parse_record;
|
||||||
free_record;
|
free_record;
|
||||||
local:
|
local:
|
||||||
@@ -24,7 +24,7 @@ APPARMOR_1.1 {
|
|||||||
global:
|
global:
|
||||||
aa_is_enabled;
|
aa_is_enabled;
|
||||||
aa_find_mountpoint;
|
aa_find_mountpoint;
|
||||||
aa_change_hat;
|
aa_change_hat; __old_change_hat;
|
||||||
aa_change_hatv;
|
aa_change_hatv;
|
||||||
aa_change_hat_vargs;
|
aa_change_hat_vargs;
|
||||||
aa_change_profile;
|
aa_change_profile;
|
||||||
@@ -37,7 +37,7 @@ APPARMOR_1.1 {
|
|||||||
free_record;
|
free_record;
|
||||||
aa_getprocattr_raw;
|
aa_getprocattr_raw;
|
||||||
aa_getprocattr;
|
aa_getprocattr;
|
||||||
aa_query_label;
|
aa_query_label; __aa_query_label;
|
||||||
|
|
||||||
# no more symbols here, please
|
# no more symbols here, please
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ APPARMOR_1.1 {
|
|||||||
|
|
||||||
APPARMOR_2.9 {
|
APPARMOR_2.9 {
|
||||||
global:
|
global:
|
||||||
aa_query_label;
|
aa_query_label; query_label;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
} APPARMOR_1.1;
|
} APPARMOR_1.1;
|
||||||
|
@@ -161,6 +161,7 @@ key_dest "dest"
|
|||||||
key_path "path"
|
key_path "path"
|
||||||
key_interface "interface"
|
key_interface "interface"
|
||||||
key_member "member"
|
key_member "member"
|
||||||
|
key_method "method"
|
||||||
key_signal "signal"
|
key_signal "signal"
|
||||||
key_peer "peer"
|
key_peer "peer"
|
||||||
key_fstype "fstype"
|
key_fstype "fstype"
|
||||||
@@ -345,6 +346,7 @@ yy_flex_debug = 0;
|
|||||||
{key_path} { return(TOK_KEY_PATH); }
|
{key_path} { return(TOK_KEY_PATH); }
|
||||||
{key_interface} { return(TOK_KEY_INTERFACE); }
|
{key_interface} { return(TOK_KEY_INTERFACE); }
|
||||||
{key_member} { return(TOK_KEY_MEMBER); }
|
{key_member} { return(TOK_KEY_MEMBER); }
|
||||||
|
{key_method} { return(TOK_KEY_MEMBER); }
|
||||||
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
|
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
|
||||||
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
|
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
|
||||||
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
||||||
|
@@ -10,8 +10,7 @@ test_python.py: test_python.py.in $(top_builddir)/config.status
|
|||||||
|
|
||||||
CLEANFILES = test_python.py
|
CLEANFILES = test_python.py
|
||||||
|
|
||||||
# bah, how brittle is this?
|
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
|
||||||
PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")'
|
|
||||||
|
|
||||||
TESTS = test_python.py
|
TESTS = test_python.py
|
||||||
TESTS_ENVIRONMENT = \
|
TESTS_ENVIRONMENT = \
|
||||||
|
13
libraries/libapparmor/swig/python/test/buildpath.py
Normal file
13
libraries/libapparmor/swig/python/test/buildpath.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# the build path has changed in setuptools 62.1:
|
||||||
|
# https://github.com/pypa/setuptools/commit/1c23f5e1e4b18b50081cbabb2dea22bf345f5894
|
||||||
|
import sys
|
||||||
|
import sysconfig
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
|
||||||
|
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
||||||
|
identifier = sys.implementation.cache_tag
|
||||||
|
else:
|
||||||
|
identifier = "%d.%d" % sys.version_info[:2]
|
||||||
|
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))
|
@@ -0,0 +1 @@
|
|||||||
|
Dec 15 17:32:17 kinetic kernel: [4835959.046111] audit: type=1107 audit(1671125537.724:209): pid=7308 uid=0 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call" bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" method="Hello" mask="send" label="/tmp/apparmor/tests/regression/apparmor/dbus_message" peer_label="unconfined" exe="/usr/local/bin/dbus-broker" sauid=0 hostname=? addr=? terminal=?'
|
@@ -0,0 +1,15 @@
|
|||||||
|
START
|
||||||
|
File: testcase_dbus_11.in
|
||||||
|
Event type: AA_RECORD_DENIED
|
||||||
|
Audit ID: 1671125537.724:209
|
||||||
|
Operation: dbus_method_call
|
||||||
|
Denied Mask: send
|
||||||
|
Profile: /tmp/apparmor/tests/regression/apparmor/dbus_message
|
||||||
|
Peer profile: unconfined
|
||||||
|
Command: /usr/local/bin/dbus-broker
|
||||||
|
DBus bus: session
|
||||||
|
DBus path: /org/freedesktop/DBus
|
||||||
|
DBus interface: org.freedesktop.DBus
|
||||||
|
DBus member: Hello
|
||||||
|
Epoch: 1671125537
|
||||||
|
Audit subid: 209
|
@@ -0,0 +1,4 @@
|
|||||||
|
/tmp/apparmor/tests/regression/apparmor/dbus_message {
|
||||||
|
dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello peer=(label=unconfined),
|
||||||
|
|
||||||
|
}
|
@@ -105,8 +105,7 @@ unix_rule::unix_rule(unsigned int type_p, bool audit_p, bool denied):
|
|||||||
|
|
||||||
unix_rule::unix_rule(int mode_p, struct cond_entry *conds,
|
unix_rule::unix_rule(int mode_p, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds):
|
struct cond_entry *peer_conds):
|
||||||
af_rule("unix"), addr(NULL), peer_addr(NULL),
|
af_rule("unix"), addr(NULL), peer_addr(NULL)
|
||||||
audit(0), deny(0)
|
|
||||||
{
|
{
|
||||||
move_conditionals(conds);
|
move_conditionals(conds);
|
||||||
move_peer_conditionals(peer_conds);
|
move_peer_conditionals(peer_conds);
|
||||||
@@ -130,7 +129,7 @@ ostream &unix_rule::dump_local(ostream &os)
|
|||||||
{
|
{
|
||||||
af_rule::dump_local(os);
|
af_rule::dump_local(os);
|
||||||
if (addr)
|
if (addr)
|
||||||
os << "addr='" << addr << "'";
|
os << " addr='" << addr << "'";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +137,7 @@ ostream &unix_rule::dump_peer(ostream &os)
|
|||||||
{
|
{
|
||||||
af_rule::dump_peer(os);
|
af_rule::dump_peer(os);
|
||||||
if (peer_addr)
|
if (peer_addr)
|
||||||
os << "addr='" << peer_addr << "'";
|
os << " addr='" << peer_addr << "'";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,14 +203,18 @@ void unix_rule::downgrade_rule(Profile &prof) {
|
|||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
if (sock_type_n != -1)
|
if (sock_type_n != -1)
|
||||||
mask = 1 << sock_type_n;
|
mask = 1 << sock_type_n;
|
||||||
if (deny) {
|
if (!deny) {
|
||||||
prof.net.deny[AF_UNIX] |= mask;
|
|
||||||
if (!audit)
|
|
||||||
prof.net.quiet[AF_UNIX] |= mask;
|
|
||||||
} else {
|
|
||||||
prof.net.allow[AF_UNIX] |= mask;
|
prof.net.allow[AF_UNIX] |= mask;
|
||||||
if (audit)
|
if (audit)
|
||||||
prof.net.audit[AF_UNIX] |= mask;
|
prof.net.audit[AF_UNIX] |= mask;
|
||||||
|
} else {
|
||||||
|
/* deny rules have to be dropped because the downgrade makes
|
||||||
|
* the rule less specific meaning it will make the profile more
|
||||||
|
* restrictive and may end up denying accesses that might be
|
||||||
|
* allowed by the profile.
|
||||||
|
*/
|
||||||
|
if (warnflags & WARN_RULE_NOT_ENFORCED)
|
||||||
|
warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,9 +36,6 @@ class unix_rule: public af_rule {
|
|||||||
public:
|
public:
|
||||||
char *addr;
|
char *addr;
|
||||||
char *peer_addr;
|
char *peer_addr;
|
||||||
int mode;
|
|
||||||
int audit;
|
|
||||||
bool deny;
|
|
||||||
|
|
||||||
unix_rule(unsigned int type_p, bool audit_p, bool denied);
|
unix_rule(unsigned int type_p, bool audit_p, bool denied);
|
||||||
unix_rule(int mode, struct cond_entry *conds,
|
unix_rule(int mode, struct cond_entry *conds,
|
||||||
|
@@ -135,7 +135,7 @@ B<MOUNT FLAGS EXPRESSION> = ( I<MOUNT FLAGS LIST> | I<MOUNT EXPRESSION> )
|
|||||||
|
|
||||||
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
|
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
|
||||||
|
|
||||||
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nouser' | 'user' )
|
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nostrictatime' | 'lazytime' | 'nolazytime' | 'nouser' | 'user' | 'symfollow' | 'nosymfollow' )
|
||||||
|
|
||||||
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
||||||
|
|
||||||
@@ -664,7 +664,7 @@ and other operations that are typically reserved for the root user.
|
|||||||
|
|
||||||
AppArmor supports simple coarse grained network mediation. The network
|
AppArmor supports simple coarse grained network mediation. The network
|
||||||
rule restrict all socket(2) based operations. The mediation done is
|
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
|
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
|
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
|
||||||
only specify type 'dgram' and 'raw'.
|
only specify type 'dgram' and 'raw'.
|
||||||
|
@@ -314,12 +314,15 @@ Eg.
|
|||||||
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
|
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
|
||||||
-jx1 is equivalent to -jauto
|
-jx1 is equivalent to -jauto
|
||||||
|
|
||||||
The default value is the number of cpus in the system.
|
The default value is the number of cpus in the system. Note that if jobs
|
||||||
|
is a positive integer number the --jobs-max parameter is automatically
|
||||||
|
set to the same value.
|
||||||
|
|
||||||
=item --max-jobs n
|
=item --max-jobs n
|
||||||
|
|
||||||
Set a hard cap on the value that can be specified by the --jobs flag.
|
When --jobs is set to a scaling value (ie. auto or xN) the specify a
|
||||||
It takes the same set of options available to the --jobs option, and
|
hard cap on the value that can be specified by the --jobs flag. It
|
||||||
|
takes the same set of options available to the --jobs option, and
|
||||||
defaults to 8*cpus
|
defaults to 8*cpus
|
||||||
|
|
||||||
=item -O n, --optimize=n
|
=item -O n, --optimize=n
|
||||||
|
723
parser/mount.cc
723
parser/mount.cc
@@ -98,6 +98,9 @@
|
|||||||
* nomand
|
* nomand
|
||||||
* #define MS_DIRSYNC 128 Directory modifications are synchronous
|
* #define MS_DIRSYNC 128 Directory modifications are synchronous
|
||||||
* dirsync
|
* dirsync
|
||||||
|
* #define MS_NOSYMFOLLOW 256 Do not follow symlinks
|
||||||
|
* symfollow
|
||||||
|
* nosymfollow
|
||||||
* #define MS_NOATIME 1024 Do not update access times
|
* #define MS_NOATIME 1024 Do not update access times
|
||||||
* noatime
|
* noatime
|
||||||
* atime
|
* atime
|
||||||
@@ -139,6 +142,9 @@
|
|||||||
* #define MS_STRICTATIME (1<<24) Always perform atime updates
|
* #define MS_STRICTATIME (1<<24) Always perform atime updates
|
||||||
* strictatime
|
* strictatime
|
||||||
* nostrictatime
|
* nostrictatime
|
||||||
|
* #define MS_LAZYTIME (1<<25) Update the on-disk [acm]times lazily
|
||||||
|
* lazytime
|
||||||
|
* nolazytime
|
||||||
* #define MS_NOSEC (1<<28)
|
* #define MS_NOSEC (1<<28)
|
||||||
* #define MS_BORN (1<<29)
|
* #define MS_BORN (1<<29)
|
||||||
* #define MS_ACTIVE (1<<30)
|
* #define MS_ACTIVE (1<<30)
|
||||||
@@ -247,6 +253,8 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
|||||||
{"mand", MS_MAND, 0},
|
{"mand", MS_MAND, 0},
|
||||||
{"nomand", 0, MS_MAND},
|
{"nomand", 0, MS_MAND},
|
||||||
{"dirsync", MS_DIRSYNC, 0},
|
{"dirsync", MS_DIRSYNC, 0},
|
||||||
|
{"symfollow", 0, MS_NOSYMFOLLOW},
|
||||||
|
{"nosymfollow", MS_NOSYMFOLLOW, 0},
|
||||||
{"atime", 0, MS_NOATIME},
|
{"atime", 0, MS_NOATIME},
|
||||||
{"noatime", MS_NOATIME, 0},
|
{"noatime", MS_NOATIME, 0},
|
||||||
{"diratime", 0, MS_NODIRATIME},
|
{"diratime", 0, MS_NODIRATIME},
|
||||||
@@ -284,6 +292,9 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
|||||||
{"iversion", MS_IVERSION, 0},
|
{"iversion", MS_IVERSION, 0},
|
||||||
{"noiversion", 0, MS_IVERSION},
|
{"noiversion", 0, MS_IVERSION},
|
||||||
{"strictatime", MS_STRICTATIME, 0},
|
{"strictatime", MS_STRICTATIME, 0},
|
||||||
|
{"nostrictatime", 0, MS_STRICTATIME},
|
||||||
|
{"lazytime", MS_LAZYTIME, 0},
|
||||||
|
{"nolazytime", 0, MS_LAZYTIME},
|
||||||
{"user", 0, (unsigned int) MS_NOUSER},
|
{"user", 0, (unsigned int) MS_NOUSER},
|
||||||
{"nouser", (unsigned int) MS_NOUSER, 0},
|
{"nouser", (unsigned int) MS_NOUSER, 0},
|
||||||
|
|
||||||
@@ -299,6 +310,22 @@ static struct mnt_keyword_table mnt_conds_table[] = {
|
|||||||
{NULL, 0, 0}
|
{NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ostream &dump_flags(ostream &os,
|
||||||
|
pair <unsigned int, unsigned int> flags)
|
||||||
|
{
|
||||||
|
for (int i = 0; mnt_opts_table[i].keyword; i++) {
|
||||||
|
if ((flags.first & mnt_opts_table[i].set) ||
|
||||||
|
(flags.second & mnt_opts_table[i].clear))
|
||||||
|
os << mnt_opts_table[i].keyword;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream &operator<<(ostream &os, pair<unsigned int, unsigned int> flags)
|
||||||
|
{
|
||||||
|
return dump_flags(os, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int find_mnt_keyword(struct mnt_keyword_table *table, const char *name)
|
static int find_mnt_keyword(struct mnt_keyword_table *table, const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -321,7 +348,7 @@ int is_valid_mnt_cond(const char *name, int src)
|
|||||||
|
|
||||||
static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
||||||
{
|
{
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0, invflags = 0;
|
||||||
*inv = 0;
|
*inv = 0;
|
||||||
|
|
||||||
struct value_list *entry, *tmp, *prev = NULL;
|
struct value_list *entry, *tmp, *prev = NULL;
|
||||||
@@ -330,11 +357,11 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
|||||||
i = find_mnt_keyword(mnt_opts_table, entry->value);
|
i = find_mnt_keyword(mnt_opts_table, entry->value);
|
||||||
if (i != -1) {
|
if (i != -1) {
|
||||||
flags |= mnt_opts_table[i].set;
|
flags |= mnt_opts_table[i].set;
|
||||||
*inv |= mnt_opts_table[i].clear;
|
invflags |= mnt_opts_table[i].clear;
|
||||||
PDEBUG(" extracting mount flag %s req: 0x%x inv: 0x%x"
|
PDEBUG(" extracting mount flag %s req: 0x%x inv: 0x%x"
|
||||||
" => req: 0x%x inv: 0x%x\n",
|
" => req: 0x%x inv: 0x%x\n",
|
||||||
entry->value, mnt_opts_table[i].set,
|
entry->value, mnt_opts_table[i].set,
|
||||||
mnt_opts_table[i].clear, flags, *inv);
|
mnt_opts_table[i].clear, flags, invflags);
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next = tmp;
|
prev->next = tmp;
|
||||||
if (entry == *list)
|
if (entry == *list)
|
||||||
@@ -345,9 +372,27 @@ static unsigned int extract_flags(struct value_list **list, unsigned int *inv)
|
|||||||
prev = entry;
|
prev = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inv)
|
||||||
|
*inv = invflags;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool conflicting_flags(unsigned int flags, unsigned int inv)
|
||||||
|
{
|
||||||
|
if (flags & inv) {
|
||||||
|
for (int i = 0; i < 31; i++) {
|
||||||
|
unsigned int mask = 1 << i;
|
||||||
|
if ((flags & inv) & mask) {
|
||||||
|
cerr << "conflicting flag values = "
|
||||||
|
<< flags << ", " << inv << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static struct value_list *extract_fstype(struct cond_entry **conds)
|
static struct value_list *extract_fstype(struct cond_entry **conds)
|
||||||
{
|
{
|
||||||
struct value_list *list = NULL;
|
struct value_list *list = NULL;
|
||||||
@@ -370,22 +415,19 @@ static struct value_list *extract_fstype(struct cond_entry **conds)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct value_list *extract_options(struct cond_entry **conds, int eq)
|
static struct cond_entry *extract_options(struct cond_entry **conds, int eq)
|
||||||
{
|
{
|
||||||
struct value_list *list = NULL;
|
struct cond_entry *list = NULL, *entry, *tmp, *prev = NULL;
|
||||||
|
|
||||||
struct cond_entry *entry, *tmp, *prev = NULL;
|
|
||||||
|
|
||||||
list_for_each_safe(*conds, entry, tmp) {
|
list_for_each_safe(*conds, entry, tmp) {
|
||||||
if ((strcmp(entry->name, "options") == 0 ||
|
if ((strcmp(entry->name, "options") == 0 ||
|
||||||
strcmp(entry->name, "option") == 0) &&
|
strcmp(entry->name, "option") == 0) &&
|
||||||
entry->eq == eq) {
|
entry->eq == eq) {
|
||||||
list_remove_at(*conds, prev, entry);
|
list_remove_at(*conds, prev, entry);
|
||||||
PDEBUG(" extracting option %s\n", entry->name);
|
PDEBUG(" extracting %s %s\n", entry->name, entry->eq ?
|
||||||
list_append(entry->vals, list);
|
"=" : "in");
|
||||||
list = entry->vals;
|
list_append(entry, list);
|
||||||
entry->vals = NULL;
|
list = entry;
|
||||||
free_cond_entry(entry);
|
|
||||||
} else
|
} else
|
||||||
prev = entry;
|
prev = entry;
|
||||||
}
|
}
|
||||||
@@ -393,60 +435,129 @@ static struct value_list *extract_options(struct cond_entry **conds, int eq)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void perror_conds(const char *rule, struct cond_entry *conds)
|
||||||
|
{
|
||||||
|
struct cond_entry *entry;
|
||||||
|
|
||||||
|
list_for_each(conds, entry) {
|
||||||
|
PERROR( "unsupported %s condition '%s%s(...)'\n", rule, entry->name, entry->eq ? "=" : " in ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perror_vals(const char *rule, struct value_list *vals)
|
||||||
|
{
|
||||||
|
struct value_list *entry;
|
||||||
|
|
||||||
|
list_for_each(vals, entry) {
|
||||||
|
PERROR( "unsupported %s value '%s'\n", rule, entry->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_one_option(struct cond_entry *&opts, unsigned int &flags,
|
||||||
|
unsigned int &inv_flags)
|
||||||
|
{
|
||||||
|
struct cond_entry *entry;
|
||||||
|
struct value_list *vals;
|
||||||
|
|
||||||
|
entry = list_pop(opts);
|
||||||
|
vals = entry->vals;
|
||||||
|
entry->vals = NULL;
|
||||||
|
/* fail if there are any unknown optional flags */
|
||||||
|
if (opts) {
|
||||||
|
PERROR(" unsupported multiple 'mount options %s(...)'\n", entry->eq ? "=" : " in ");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free_cond_entry(entry);
|
||||||
|
|
||||||
|
flags = extract_flags(&vals, &inv_flags);
|
||||||
|
if (vals) {
|
||||||
|
perror_vals("mount option", vals);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
|
mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
|
||||||
struct cond_entry *dst_conds unused, char *mnt_point_p,
|
struct cond_entry *dst_conds unused, char *mnt_point_p,
|
||||||
int allow_p):
|
int allow_p):
|
||||||
mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
|
mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
|
||||||
flags(0), inv_flags(0), audit(0), deny(0)
|
flagsv(0), opt_flagsv(0), audit(0), deny(0)
|
||||||
{
|
{
|
||||||
/* FIXME: dst_conds are ignored atm */
|
/* FIXME: dst_conds are ignored atm */
|
||||||
dev_type = extract_fstype(&src_conds);
|
dev_type = extract_fstype(&src_conds);
|
||||||
|
|
||||||
if (src_conds) {
|
if (src_conds) {
|
||||||
struct value_list *list = extract_options(&src_conds, 0);
|
/* move options in () to local list */
|
||||||
|
struct cond_entry *opts_in = extract_options(&src_conds, 0);
|
||||||
|
|
||||||
opts = extract_options(&src_conds, 1);
|
if (opts_in) {
|
||||||
if (opts)
|
unsigned int tmpflags = 0, tmpinv_flags = 0;
|
||||||
flags = extract_flags(&opts, &inv_flags);
|
struct cond_entry *entry;
|
||||||
|
|
||||||
if (list) {
|
while ((entry = list_pop(opts_in))) {
|
||||||
unsigned int tmpflags, tmpinv_flags = 0;
|
process_one_option(entry, tmpflags,
|
||||||
|
tmpinv_flags);
|
||||||
tmpflags = extract_flags(&list, &tmpinv_flags);
|
/* optional flags if set/clear mean the same
|
||||||
/* these flags are optional so set both */
|
* thing and can be represented by a single
|
||||||
tmpflags |= tmpinv_flags;
|
* bitset, also there is no need to check for
|
||||||
tmpinv_flags |= tmpflags;
|
* conflicting flags when they are optional
|
||||||
|
*/
|
||||||
flags |= tmpflags;
|
opt_flagsv.push_back(tmpflags | tmpinv_flags);
|
||||||
inv_flags |= tmpinv_flags;
|
}
|
||||||
|
|
||||||
if (opts)
|
|
||||||
list_append(opts, list);
|
|
||||||
else if (list)
|
|
||||||
opts = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* move options=() to opts list */
|
||||||
|
struct cond_entry *opts_eq = extract_options(&src_conds, 1);
|
||||||
|
if (opts_eq) {
|
||||||
|
unsigned int tmpflags = 0, tmpinv_flags = 0;
|
||||||
|
struct cond_entry *entry;
|
||||||
|
|
||||||
|
while ((entry = list_pop(opts_eq))) {
|
||||||
|
process_one_option(entry, tmpflags,
|
||||||
|
tmpinv_flags);
|
||||||
|
/* throw away tmpinv_flags, only needed in
|
||||||
|
* consistancy check
|
||||||
|
*/
|
||||||
|
if (allow_p & AA_DUMMY_REMOUNT)
|
||||||
|
tmpflags |= MS_REMOUNT;
|
||||||
|
|
||||||
|
if (conflicting_flags(tmpflags, tmpinv_flags)) {
|
||||||
|
PERROR("conflicting flags in the rule\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
flagsv.push_back(tmpflags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_conds) {
|
||||||
|
perror_conds("mount", src_conds);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flagsv.size() + opt_flagsv.size())) {
|
||||||
|
/* no flag options, and not remount, allow everything */
|
||||||
|
if (allow_p & AA_DUMMY_REMOUNT) {
|
||||||
|
flagsv.push_back(MS_REMOUNT);
|
||||||
|
opt_flagsv.push_back(MS_REMOUNT_FLAGS & ~MS_REMOUNT);
|
||||||
|
} else {
|
||||||
|
flagsv.push_back(MS_ALL_FLAGS);
|
||||||
|
opt_flagsv.push_back(MS_ALL_FLAGS);
|
||||||
|
}
|
||||||
|
} else if (!(flagsv.size())) {
|
||||||
|
/* no flags but opts set */
|
||||||
|
if (allow_p & AA_DUMMY_REMOUNT)
|
||||||
|
flagsv.push_back(MS_REMOUNT);
|
||||||
|
else
|
||||||
|
flagsv.push_back(0);
|
||||||
|
} else if (!(opt_flagsv.size())) {
|
||||||
|
opt_flagsv.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allow_p & AA_DUMMY_REMOUNT) {
|
if (allow_p & AA_DUMMY_REMOUNT) {
|
||||||
allow_p = AA_MAY_MOUNT;
|
allow_p = AA_MAY_MOUNT;
|
||||||
flags |= MS_REMOUNT;
|
|
||||||
inv_flags = 0;
|
|
||||||
} else if (!(flags | inv_flags)) {
|
|
||||||
/* no flag options, and not remount, allow everything */
|
|
||||||
flags = MS_ALL_FLAGS;
|
|
||||||
inv_flags = MS_ALL_FLAGS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allow = allow_p;
|
allow = allow_p;
|
||||||
|
|
||||||
if (src_conds) {
|
|
||||||
PERROR(" unsupported mount conditions\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (opts) {
|
|
||||||
PERROR(" unsupported mount options\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream &mnt_rule::dump(ostream &os)
|
ostream &mnt_rule::dump(ostream &os)
|
||||||
@@ -460,7 +571,11 @@ ostream &mnt_rule::dump(ostream &os)
|
|||||||
else
|
else
|
||||||
os << "error: unknonwn mount perm";
|
os << "error: unknonwn mount perm";
|
||||||
|
|
||||||
os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
|
for (unsigned int i = 0; i < flagsv.size(); i++)
|
||||||
|
os << " flags=(0x" << hex << flagsv[i] << ")";
|
||||||
|
for (unsigned int i = 0; i < opt_flagsv.size(); i++)
|
||||||
|
os << " flags in (0x" << hex << opt_flagsv[i] << ")";
|
||||||
|
|
||||||
if (dev_type) {
|
if (dev_type) {
|
||||||
os << " type=";
|
os << " type=";
|
||||||
print_value_list(dev_type);
|
print_value_list(dev_type);
|
||||||
@@ -516,7 +631,7 @@ int mnt_rule::expand_variables(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||||
unsigned int inv_flags)
|
unsigned int opt_flags)
|
||||||
{
|
{
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
int i, len = 0;
|
int i, len = 0;
|
||||||
@@ -529,7 +644,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
for (i = 0; i <= 31; ++i) {
|
for (i = 0; i <= 31; ++i) {
|
||||||
if ((flags & inv_flags) & (1 << i))
|
if ((opt_flags) & (1 << i))
|
||||||
len = snprintf(p, size, "(\\x%02x|)", i + 1);
|
len = snprintf(p, size, "(\\x%02x|)", i + 1);
|
||||||
else if (flags & (1 << i))
|
else if (flags & (1 << i))
|
||||||
len = snprintf(p, size, "\\x%02x", i + 1);
|
len = snprintf(p, size, "\\x%02x", i + 1);
|
||||||
@@ -595,7 +710,9 @@ static void warn_once(const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mnt_rule::gen_policy_re(Profile &prof)
|
|
||||||
|
int mnt_rule::gen_policy_remount(Profile &prof, int &count,
|
||||||
|
unsigned int flags, unsigned int opt_flags)
|
||||||
{
|
{
|
||||||
std::string mntbuf;
|
std::string mntbuf;
|
||||||
std::string devbuf;
|
std::string devbuf;
|
||||||
@@ -604,215 +721,317 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||||||
std::string optsbuf;
|
std::string optsbuf;
|
||||||
char class_mount_hdr[64];
|
char class_mount_hdr[64];
|
||||||
const char *vec[5];
|
const char *vec[5];
|
||||||
int count = 0;
|
int tmpallow;
|
||||||
unsigned int tmpflags, tmpinv_flags;
|
|
||||||
|
|
||||||
if (!kernel_supports_mount) {
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
warn_once(prof.name);
|
|
||||||
return RULE_NOT_SUPPORTED;
|
/* remount can't be conditional on device and type */
|
||||||
|
/* rule class single byte header */
|
||||||
|
mntbuf.assign(class_mount_hdr);
|
||||||
|
if (mnt_point) {
|
||||||
|
/* both device && mnt_point or just mnt_point */
|
||||||
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
|
} else {
|
||||||
|
if (!convert_entry(mntbuf, device))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
}
|
}
|
||||||
|
/* skip device */
|
||||||
|
vec[1] = default_match_pattern;
|
||||||
|
/* skip type */
|
||||||
|
vec[2] = default_match_pattern;
|
||||||
|
|
||||||
|
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_REMOUNT_FLAGS,
|
||||||
|
opt_flags & MS_REMOUNT_FLAGS))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
vec[3] = flagsbuf;
|
||||||
|
|
||||||
|
if (opts)
|
||||||
|
tmpallow = AA_MATCH_CONT;
|
||||||
|
else
|
||||||
|
tmpallow = allow;
|
||||||
|
|
||||||
|
/* rule for match without required data || data MATCH_CONT */
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||||
|
audit | AA_AUDIT_MNT_DATA, 4,
|
||||||
|
vec, dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (opts) {
|
||||||
|
/* rule with data match required */
|
||||||
|
optsbuf.clear();
|
||||||
|
if (!build_mnt_opts(optsbuf, opts))
|
||||||
|
goto fail;
|
||||||
|
vec[4] = optsbuf.c_str();
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||||
|
audit | AA_AUDIT_MNT_DATA,
|
||||||
|
5, vec, dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return RULE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
|
||||||
|
unsigned int flags, unsigned int opt_flags)
|
||||||
|
{
|
||||||
|
std::string mntbuf;
|
||||||
|
std::string devbuf;
|
||||||
|
std::string typebuf;
|
||||||
|
char flagsbuf[PATH_MAX + 3];
|
||||||
|
std::string optsbuf;
|
||||||
|
char class_mount_hdr[64];
|
||||||
|
const char *vec[5];
|
||||||
|
|
||||||
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
|
|
||||||
|
/* bind mount rules can't be conditional on dev_type or data */
|
||||||
|
/* rule class single byte header */
|
||||||
|
mntbuf.assign(class_mount_hdr);
|
||||||
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
|
if (!clear_and_convert_entry(devbuf, device))
|
||||||
|
goto fail;
|
||||||
|
vec[1] = devbuf.c_str();
|
||||||
|
/* skip type */
|
||||||
|
vec[2] = default_match_pattern;
|
||||||
|
|
||||||
|
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_BIND_FLAGS,
|
||||||
|
opt_flags & MS_BIND_FLAGS))
|
||||||
|
goto fail;
|
||||||
|
vec[3] = flagsbuf;
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||||
|
dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return RULE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
|
||||||
|
unsigned int flags,
|
||||||
|
unsigned int opt_flags)
|
||||||
|
{
|
||||||
|
std::string mntbuf;
|
||||||
|
std::string devbuf;
|
||||||
|
std::string typebuf;
|
||||||
|
char flagsbuf[PATH_MAX + 3];
|
||||||
|
std::string optsbuf;
|
||||||
|
char class_mount_hdr[64];
|
||||||
|
const char *vec[5];
|
||||||
|
|
||||||
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
|
|
||||||
|
/* change type base rules can not be conditional on device,
|
||||||
|
* device type or data
|
||||||
|
*/
|
||||||
|
/* rule class single byte header */
|
||||||
|
mntbuf.assign(class_mount_hdr);
|
||||||
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
|
/* skip device and type */
|
||||||
|
vec[1] = default_match_pattern;
|
||||||
|
vec[2] = default_match_pattern;
|
||||||
|
|
||||||
|
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MAKE_FLAGS,
|
||||||
|
opt_flags & MS_MAKE_FLAGS))
|
||||||
|
goto fail;
|
||||||
|
vec[3] = flagsbuf;
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||||
|
dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return RULE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
|
||||||
|
unsigned int flags, unsigned int opt_flags)
|
||||||
|
{
|
||||||
|
std::string mntbuf;
|
||||||
|
std::string devbuf;
|
||||||
|
std::string typebuf;
|
||||||
|
char flagsbuf[PATH_MAX + 3];
|
||||||
|
std::string optsbuf;
|
||||||
|
char class_mount_hdr[64];
|
||||||
|
const char *vec[5];
|
||||||
|
|
||||||
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
|
|
||||||
|
/* mount move rules can not be conditional on dev_type,
|
||||||
|
* or data
|
||||||
|
*/
|
||||||
|
/* rule class single byte header */
|
||||||
|
mntbuf.assign(class_mount_hdr);
|
||||||
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
|
if (!clear_and_convert_entry(devbuf, device))
|
||||||
|
goto fail;
|
||||||
|
vec[1] = devbuf.c_str();
|
||||||
|
/* skip type */
|
||||||
|
vec[2] = default_match_pattern;
|
||||||
|
|
||||||
|
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_MOVE_FLAGS,
|
||||||
|
opt_flags & MS_MOVE_FLAGS))
|
||||||
|
goto fail;
|
||||||
|
vec[3] = flagsbuf;
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||||
|
dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return RULE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
||||||
|
unsigned int flags, unsigned int opt_flags)
|
||||||
|
{
|
||||||
|
std::string mntbuf;
|
||||||
|
std::string devbuf;
|
||||||
|
std::string typebuf;
|
||||||
|
char flagsbuf[PATH_MAX + 3];
|
||||||
|
std::string optsbuf;
|
||||||
|
char class_mount_hdr[64];
|
||||||
|
const char *vec[5];
|
||||||
|
int tmpallow;
|
||||||
|
|
||||||
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
|
|
||||||
|
/* rule class single byte header */
|
||||||
|
mntbuf.assign(class_mount_hdr);
|
||||||
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
|
goto fail;
|
||||||
|
vec[0] = mntbuf.c_str();
|
||||||
|
if (!clear_and_convert_entry(devbuf, device))
|
||||||
|
goto fail;
|
||||||
|
vec[1] = devbuf.c_str();
|
||||||
|
typebuf.clear();
|
||||||
|
if (!build_list_val_expr(typebuf, dev_type))
|
||||||
|
goto fail;
|
||||||
|
vec[2] = typebuf.c_str();
|
||||||
|
|
||||||
|
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags & MS_NEW_FLAGS,
|
||||||
|
opt_flags & MS_NEW_FLAGS))
|
||||||
|
goto fail;
|
||||||
|
vec[3] = flagsbuf;
|
||||||
|
|
||||||
|
if (opts)
|
||||||
|
tmpallow = AA_MATCH_CONT;
|
||||||
|
else
|
||||||
|
tmpallow = allow;
|
||||||
|
|
||||||
|
/* rule for match without required data || data MATCH_CONT */
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||||
|
audit | AA_AUDIT_MNT_DATA, 4,
|
||||||
|
vec, dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (opts) {
|
||||||
|
/* rule with data match required */
|
||||||
|
optsbuf.clear();
|
||||||
|
if (!build_mnt_opts(optsbuf, opts))
|
||||||
|
goto fail;
|
||||||
|
vec[4] = optsbuf.c_str();
|
||||||
|
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||||
|
audit | AA_AUDIT_MNT_DATA,
|
||||||
|
5, vec, dfaflags))
|
||||||
|
goto fail;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return RULE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_flag_rules(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* XXX: added !flags to cover cases like:
|
||||||
|
* mount options in (bind) /d -> /4,
|
||||||
|
*/
|
||||||
|
if ((allow & AA_MAY_MOUNT) && (!flags || flags == MS_ALL_FLAGS)) {
|
||||||
|
/* no mount flags specified, generate multiple rules */
|
||||||
|
if (!device && !dev_type &&
|
||||||
|
gen_policy_remount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||||
|
return RULE_ERROR;
|
||||||
|
if (!dev_type && !opts &&
|
||||||
|
gen_policy_bind_mount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||||
|
return RULE_ERROR;
|
||||||
|
if (!device && !dev_type && !opts &&
|
||||||
|
gen_policy_change_mount_type(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||||
|
return RULE_ERROR;
|
||||||
|
if (!dev_type && !opts &&
|
||||||
|
gen_policy_move_mount(prof, count, flags, opt_flags) == RULE_ERROR)
|
||||||
|
return RULE_ERROR;
|
||||||
|
|
||||||
|
return gen_policy_new_mount(prof, count, flags, opt_flags);
|
||||||
|
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
|
||||||
|
&& !device && !dev_type) {
|
||||||
|
return gen_policy_remount(prof, count, flags, opt_flags);
|
||||||
|
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
|
||||||
|
&& !dev_type && !opts) {
|
||||||
|
return gen_policy_bind_mount(prof, count, flags, opt_flags);
|
||||||
|
} else if ((allow & AA_MAY_MOUNT) &&
|
||||||
|
(flags & (MS_MAKE_CMDS))
|
||||||
|
&& !device && !dev_type && !opts) {
|
||||||
|
return gen_policy_change_mount_type(prof, count, flags, opt_flags);
|
||||||
|
} else if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
|
||||||
|
&& !dev_type && !opts) {
|
||||||
|
return gen_policy_move_mount(prof, count, flags, opt_flags);
|
||||||
|
} else if ((allow & AA_MAY_MOUNT) &&
|
||||||
|
((flags | opt_flags) & ~MS_CMDS)) {
|
||||||
|
/* generic mount if flags are set that are not covered by
|
||||||
|
* above commands
|
||||||
|
*/
|
||||||
|
return gen_policy_new_mount(prof, count, flags, opt_flags);
|
||||||
|
} /* else must be RULE_OK for some rules */
|
||||||
|
|
||||||
|
return RULE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_rule::gen_policy_re(Profile &prof)
|
||||||
|
{
|
||||||
|
std::string mntbuf;
|
||||||
|
std::string devbuf;
|
||||||
|
std::string typebuf;
|
||||||
|
std::string optsbuf;
|
||||||
|
char class_mount_hdr[64];
|
||||||
|
const char *vec[5];
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
|
||||||
|
|
||||||
/* a single mount rule may result in multiple matching rules being
|
/* a single mount rule may result in multiple matching rules being
|
||||||
* created in the backend to cover all the possible choices
|
* created in the backend to cover all the possible choices
|
||||||
*/
|
*/
|
||||||
|
for (size_t i = 0; i < flagsv.size(); i++) {
|
||||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
|
for (size_t j = 0; j < opt_flagsv.size(); j++) {
|
||||||
&& !device && !dev_type) {
|
if (gen_flag_rules(prof, count, flagsv[i], opt_flagsv[j]) == RULE_ERROR)
|
||||||
int tmpallow;
|
|
||||||
/* remount can't be conditional on device and type */
|
|
||||||
/* rule class single byte header */
|
|
||||||
mntbuf.assign(class_mount_hdr);
|
|
||||||
if (mnt_point) {
|
|
||||||
/* both device && mnt_point or just mnt_point */
|
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
} else {
|
|
||||||
if (!convert_entry(mntbuf, device))
|
|
||||||
goto fail;
|
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
}
|
|
||||||
/* skip device */
|
|
||||||
vec[1] = default_match_pattern;
|
|
||||||
/* skip type */
|
|
||||||
vec[2] = default_match_pattern;
|
|
||||||
|
|
||||||
tmpflags = flags;
|
|
||||||
tmpinv_flags = inv_flags;
|
|
||||||
if (tmpflags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_REMOUNT_FLAGS;
|
|
||||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_REMOUNT_FLAGS;
|
|
||||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
|
||||||
goto fail;
|
|
||||||
vec[3] = flagsbuf;
|
|
||||||
|
|
||||||
if (opts)
|
|
||||||
tmpallow = AA_MATCH_CONT;
|
|
||||||
else
|
|
||||||
tmpallow = allow;
|
|
||||||
|
|
||||||
/* rule for match without required data || data MATCH_CONT */
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
|
||||||
audit | AA_AUDIT_MNT_DATA, 4,
|
|
||||||
vec, dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (opts) {
|
|
||||||
/* rule with data match required */
|
|
||||||
optsbuf.clear();
|
|
||||||
if (!build_mnt_opts(optsbuf, opts))
|
|
||||||
goto fail;
|
|
||||||
vec[4] = optsbuf.c_str();
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
|
||||||
audit | AA_AUDIT_MNT_DATA,
|
|
||||||
5, vec, dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
|
|
||||||
&& !dev_type && !opts) {
|
|
||||||
/* bind mount rules can't be conditional on dev_type or data */
|
|
||||||
/* rule class single byte header */
|
|
||||||
mntbuf.assign(class_mount_hdr);
|
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
|
||||||
goto fail;
|
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
if (!clear_and_convert_entry(devbuf, device))
|
|
||||||
goto fail;
|
|
||||||
vec[1] = devbuf.c_str();
|
|
||||||
/* skip type */
|
|
||||||
vec[2] = default_match_pattern;
|
|
||||||
|
|
||||||
tmpflags = flags;
|
|
||||||
tmpinv_flags = inv_flags;
|
|
||||||
if (tmpflags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_BIND_FLAGS;
|
|
||||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_BIND_FLAGS;
|
|
||||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
|
||||||
goto fail;
|
|
||||||
vec[3] = flagsbuf;
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
|
||||||
dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if ((allow & AA_MAY_MOUNT) &&
|
|
||||||
(flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
|
|
||||||
&& !device && !dev_type && !opts) {
|
|
||||||
/* change type base rules can not be conditional on device,
|
|
||||||
* device type or data
|
|
||||||
*/
|
|
||||||
/* rule class single byte header */
|
|
||||||
mntbuf.assign(class_mount_hdr);
|
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
|
||||||
goto fail;
|
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
/* skip device and type */
|
|
||||||
vec[1] = default_match_pattern;
|
|
||||||
vec[2] = default_match_pattern;
|
|
||||||
|
|
||||||
tmpflags = flags;
|
|
||||||
tmpinv_flags = inv_flags;
|
|
||||||
if (tmpflags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_MAKE_FLAGS;
|
|
||||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_MAKE_FLAGS;
|
|
||||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
|
||||||
goto fail;
|
|
||||||
vec[3] = flagsbuf;
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
|
||||||
dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
|
|
||||||
&& !dev_type && !opts) {
|
|
||||||
/* mount move rules can not be conditional on dev_type,
|
|
||||||
* or data
|
|
||||||
*/
|
|
||||||
/* rule class single byte header */
|
|
||||||
mntbuf.assign(class_mount_hdr);
|
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
|
||||||
goto fail;
|
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
if (!clear_and_convert_entry(devbuf, device))
|
|
||||||
goto fail;
|
|
||||||
vec[1] = devbuf.c_str();
|
|
||||||
/* skip type */
|
|
||||||
vec[2] = default_match_pattern;
|
|
||||||
|
|
||||||
tmpflags = flags;
|
|
||||||
tmpinv_flags = inv_flags;
|
|
||||||
if (tmpflags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_MOVE_FLAGS;
|
|
||||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= MS_MOVE_FLAGS;
|
|
||||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
|
||||||
goto fail;
|
|
||||||
vec[3] = flagsbuf;
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
|
||||||
dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if ((allow & AA_MAY_MOUNT) &&
|
|
||||||
(flags | inv_flags) & ~MS_CMDS) {
|
|
||||||
int tmpallow;
|
|
||||||
/* generic mount if flags are set that are not covered by
|
|
||||||
* above commands
|
|
||||||
*/
|
|
||||||
/* rule class single byte header */
|
|
||||||
mntbuf.assign(class_mount_hdr);
|
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
|
||||||
goto fail;
|
|
||||||
vec[0] = mntbuf.c_str();
|
|
||||||
if (!clear_and_convert_entry(devbuf, device))
|
|
||||||
goto fail;
|
|
||||||
vec[1] = devbuf.c_str();
|
|
||||||
typebuf.clear();
|
|
||||||
if (!build_list_val_expr(typebuf, dev_type))
|
|
||||||
goto fail;
|
|
||||||
vec[2] = typebuf.c_str();
|
|
||||||
|
|
||||||
tmpflags = flags;
|
|
||||||
tmpinv_flags = inv_flags;
|
|
||||||
if (tmpflags != MS_ALL_FLAGS)
|
|
||||||
tmpflags &= ~MS_CMDS;
|
|
||||||
if (tmpinv_flags != MS_ALL_FLAGS)
|
|
||||||
tmpinv_flags &= ~MS_CMDS;
|
|
||||||
if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
|
|
||||||
goto fail;
|
|
||||||
vec[3] = flagsbuf;
|
|
||||||
|
|
||||||
if (opts)
|
|
||||||
tmpallow = AA_MATCH_CONT;
|
|
||||||
else
|
|
||||||
tmpallow = allow;
|
|
||||||
|
|
||||||
/* rule for match without required data || data MATCH_CONT */
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
|
||||||
audit | AA_AUDIT_MNT_DATA, 4,
|
|
||||||
vec, dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (opts) {
|
|
||||||
/* rule with data match required */
|
|
||||||
optsbuf.clear();
|
|
||||||
if (!build_mnt_opts(optsbuf, opts))
|
|
||||||
goto fail;
|
|
||||||
vec[4] = optsbuf.c_str();
|
|
||||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
|
||||||
audit | AA_AUDIT_MNT_DATA,
|
|
||||||
5, vec, dfaflags))
|
|
||||||
goto fail;
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allow & AA_MAY_UMOUNT) {
|
if (allow & AA_MAY_UMOUNT) {
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#define __AA_MOUNT_H
|
#define __AA_MOUNT_H
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
@@ -39,6 +40,8 @@
|
|||||||
#define MS_MAND (1 << 6)
|
#define MS_MAND (1 << 6)
|
||||||
#define MS_NOMAND 0
|
#define MS_NOMAND 0
|
||||||
#define MS_DIRSYNC (1 << 7)
|
#define MS_DIRSYNC (1 << 7)
|
||||||
|
#define MS_SYMFOLLOW 0
|
||||||
|
#define MS_NOSYMFOLLOW (1 << 8)
|
||||||
#define MS_NODIRSYNC 0
|
#define MS_NODIRSYNC 0
|
||||||
#define MS_NOATIME (1 << 10)
|
#define MS_NOATIME (1 << 10)
|
||||||
#define MS_ATIME 0
|
#define MS_ATIME 0
|
||||||
@@ -61,6 +64,7 @@
|
|||||||
#define MS_IVERSION (1 << 23)
|
#define MS_IVERSION (1 << 23)
|
||||||
#define MS_NOIVERSION 0
|
#define MS_NOIVERSION 0
|
||||||
#define MS_STRICTATIME (1 << 24)
|
#define MS_STRICTATIME (1 << 24)
|
||||||
|
#define MS_LAZYTIME (1 << 25)
|
||||||
#define MS_NOUSER (1 << 31)
|
#define MS_NOUSER (1 << 31)
|
||||||
#define MS_USER 0
|
#define MS_USER 0
|
||||||
|
|
||||||
@@ -74,12 +78,14 @@
|
|||||||
|
|
||||||
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
|
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
|
||||||
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
|
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
|
||||||
|
MS_NOSYMFOLLOW | \
|
||||||
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
|
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
|
||||||
MS_MOVE | MS_VERBOSE | MS_ACL | \
|
MS_MOVE | MS_VERBOSE | MS_ACL | \
|
||||||
MS_UNBINDABLE | MS_RUNBINDABLE | \
|
MS_UNBINDABLE | MS_RUNBINDABLE | \
|
||||||
MS_PRIVATE | MS_RPRIVATE | \
|
MS_PRIVATE | MS_RPRIVATE | \
|
||||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED | \
|
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED | \
|
||||||
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | MS_USER)
|
MS_RELATIME | MS_IVERSION | MS_STRICTATIME | \
|
||||||
|
MS_LAZYTIME | MS_USER)
|
||||||
|
|
||||||
/* set of flags we don't use but define (but not with the kernel values)
|
/* set of flags we don't use but define (but not with the kernel values)
|
||||||
* for MNT_FLAGS
|
* for MNT_FLAGS
|
||||||
@@ -94,16 +100,15 @@
|
|||||||
MS_KERNMOUNT | MS_STRICTATIME)
|
MS_KERNMOUNT | MS_STRICTATIME)
|
||||||
|
|
||||||
#define MS_BIND_FLAGS (MS_BIND | MS_RBIND)
|
#define MS_BIND_FLAGS (MS_BIND | MS_RBIND)
|
||||||
#define MS_MAKE_FLAGS ((MS_UNBINDABLE | MS_RUNBINDABLE | \
|
#define MS_MAKE_CMDS (MS_UNBINDABLE | MS_RUNBINDABLE | \
|
||||||
MS_PRIVATE | MS_RPRIVATE | \
|
MS_PRIVATE | MS_RPRIVATE | \
|
||||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED) | \
|
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
||||||
(MS_ALL_FLAGS & ~(MNT_FLAGS)))
|
#define MS_MAKE_FLAGS (MS_ALL_FLAGS & ~(MNT_FLAGS))
|
||||||
#define MS_MOVE_FLAGS (MS_MOVE)
|
#define MS_MOVE_FLAGS (MS_MOVE)
|
||||||
|
|
||||||
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | \
|
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | MS_MAKE_CMDS)
|
||||||
MS_UNBINDABLE | MS_RUNBINDABLE | MS_PRIVATE | MS_RPRIVATE | \
|
|
||||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
|
||||||
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
|
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
|
||||||
|
#define MS_NEW_FLAGS (MS_ALL_FLAGS & ~MS_CMDS)
|
||||||
|
|
||||||
#define MNT_SRC_OPT 1
|
#define MNT_SRC_OPT 1
|
||||||
#define MNT_DST_OPT 2
|
#define MNT_DST_OPT 2
|
||||||
@@ -121,6 +126,19 @@
|
|||||||
|
|
||||||
|
|
||||||
class mnt_rule: public rule_t {
|
class mnt_rule: public rule_t {
|
||||||
|
int gen_policy_remount(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
|
int gen_policy_bind_mount(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
|
int gen_policy_change_mount_type(Profile &prof, int &count,
|
||||||
|
unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
|
int gen_policy_move_mount(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
|
int gen_policy_new_mount(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
|
int gen_flag_rules(Profile &prof, int &count, unsigned int flags,
|
||||||
|
unsigned int opt_flags);
|
||||||
public:
|
public:
|
||||||
char *mnt_point;
|
char *mnt_point;
|
||||||
char *device;
|
char *device;
|
||||||
@@ -128,7 +146,7 @@ public:
|
|||||||
struct value_list *dev_type;
|
struct value_list *dev_type;
|
||||||
struct value_list *opts;
|
struct value_list *opts;
|
||||||
|
|
||||||
unsigned int flags, inv_flags;
|
std::vector<unsigned int> flagsv, opt_flagsv;
|
||||||
|
|
||||||
int allow, audit;
|
int allow, audit;
|
||||||
int deny;
|
int deny;
|
||||||
|
@@ -204,6 +204,7 @@ do { \
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define list_first(LIST) (LIST)
|
||||||
#define list_for_each(LIST, ENTRY) \
|
#define list_for_each(LIST, ENTRY) \
|
||||||
for ((ENTRY) = (LIST); (ENTRY); (ENTRY) = (ENTRY)->next)
|
for ((ENTRY) = (LIST); (ENTRY); (ENTRY) = (ENTRY)->next)
|
||||||
#define list_for_each_safe(LIST, ENTRY, TMP) \
|
#define list_for_each_safe(LIST, ENTRY, TMP) \
|
||||||
@@ -237,6 +238,16 @@ do { \
|
|||||||
prev; \
|
prev; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define list_pop(LIST) \
|
||||||
|
({ \
|
||||||
|
typeof(LIST) _entry = (LIST); \
|
||||||
|
if (LIST) { \
|
||||||
|
(LIST) = (LIST)->next; \
|
||||||
|
_entry->next = NULL; \
|
||||||
|
} \
|
||||||
|
_entry; \
|
||||||
|
})
|
||||||
|
|
||||||
#define list_remove_at(LIST, PREV, ENTRY) \
|
#define list_remove_at(LIST, PREV, ENTRY) \
|
||||||
if (PREV) \
|
if (PREV) \
|
||||||
(PREV)->next = (ENTRY)->next; \
|
(PREV)->next = (ENTRY)->next; \
|
||||||
|
@@ -180,6 +180,7 @@ void include_filename(char *filename, int search, bool if_exists)
|
|||||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||||
} else if (S_ISDIR(my_stat.st_mode)) {
|
} else if (S_ISDIR(my_stat.st_mode)) {
|
||||||
struct cb_struct data = { fullpath, filename };
|
struct cb_struct data = { fullpath, filename };
|
||||||
|
update_mru_tstamp(include_file, fullpath);
|
||||||
fclose(include_file);
|
fclose(include_file);
|
||||||
include_file = NULL;
|
include_file = NULL;
|
||||||
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
|
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
|
||||||
@@ -715,7 +716,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) {
|
(.|\n) {
|
||||||
DUMP_PREPROCESS;
|
DUMP_PREPROCESS;
|
||||||
/* Something we didn't expect */
|
/* Something we didn't expect */
|
||||||
|
@@ -638,6 +638,8 @@ static int process_arg(int c, char *optarg)
|
|||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
jobs = process_jobs_arg("-j", optarg);
|
jobs = process_jobs_arg("-j", optarg);
|
||||||
|
if (jobs != JOBS_AUTO && jobs < LONG_MAX)
|
||||||
|
jobs_max = jobs;
|
||||||
break;
|
break;
|
||||||
case 136:
|
case 136:
|
||||||
jobs_max = process_jobs_arg("max-jobs", optarg);
|
jobs_max = process_jobs_arg("max-jobs", optarg);
|
||||||
@@ -1183,6 +1185,8 @@ static void setup_parallel_compile(void)
|
|||||||
if (maxn == -1)
|
if (maxn == -1)
|
||||||
/* unable to determine number of processors, default to 1 */
|
/* unable to determine number of processors, default to 1 */
|
||||||
maxn = 1;
|
maxn = 1;
|
||||||
|
if (jobs < 0 || jobs == JOBS_AUTO)
|
||||||
|
jobs_scale = 1;
|
||||||
jobs = compute_jobs(n, jobs);
|
jobs = compute_jobs(n, jobs);
|
||||||
jobs_max = compute_jobs(maxn, jobs_max);
|
jobs_max = compute_jobs(maxn, jobs_max);
|
||||||
|
|
||||||
@@ -1190,7 +1194,7 @@ static void setup_parallel_compile(void)
|
|||||||
pwarn("%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
pwarn("%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
||||||
progname, jobs_max, jobs);
|
progname, jobs_max, jobs);
|
||||||
jobs = jobs_max;
|
jobs = jobs_max;
|
||||||
} else if (jobs < jobs_max)
|
} else if (jobs_scale && jobs < jobs_max)
|
||||||
/* the bigger the difference the more sample chances given */
|
/* the bigger the difference the more sample chances given */
|
||||||
jobs_scale = jobs_max + 1 - n;
|
jobs_scale = jobs_max + 1 - n;
|
||||||
|
|
||||||
|
@@ -564,6 +564,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||||||
int pos;
|
int pos;
|
||||||
vec[0] = tbuf.c_str();
|
vec[0] = tbuf.c_str();
|
||||||
if (entry->link_name) {
|
if (entry->link_name) {
|
||||||
|
filter_slashes(entry->link_name);
|
||||||
ptype = convert_aaregex_to_pcre(entry->link_name, 0, glob_default, lbuf, &pos);
|
ptype = convert_aaregex_to_pcre(entry->link_name, 0, glob_default, lbuf, &pos);
|
||||||
if (ptype == ePatternInvalid)
|
if (ptype == ePatternInvalid)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@@ -547,7 +547,21 @@ verify_binary_equality "set rlimit memlock <= 2GB" \
|
|||||||
"/t { set rlimit memlock <= 2GB, }" \
|
"/t { set rlimit memlock <= 2GB, }" \
|
||||||
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
||||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
||||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }" \
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
|
||||||
|
|
||||||
|
# verify slash filtering for link rules
|
||||||
|
verify_binary_equality "link rules slash filtering" \
|
||||||
|
"/t { link /dev/foo -> /mnt/bar, }" \
|
||||||
|
"/t { link ///dev/foo -> /mnt/bar, }" \
|
||||||
|
"/t { link /dev/foo -> /mnt//bar, }" \
|
||||||
|
"/t { link /dev///foo -> ////mnt/bar, }" \
|
||||||
|
"@{BAR}=/mnt/
|
||||||
|
/t { link /dev///foo -> @{BAR}/bar, }" \
|
||||||
|
"@{FOO}=/dev/
|
||||||
|
/t { link @{FOO}//foo -> /mnt/bar, }" \
|
||||||
|
"@{FOO}=/dev/
|
||||||
|
@{BAR}=/mnt/
|
||||||
|
/t { link @{FOO}/foo -> @{BAR}/bar, }" \
|
||||||
|
|
||||||
if [ $fails -ne 0 -o $errors -ne 0 ]
|
if [ $fails -ne 0 -o $errors -ne 0 ]
|
||||||
then
|
then
|
||||||
|
7
parser/tst/simple_tests/mount/bad_1.sd
Normal file
7
parser/tst/simple_tests/mount/bad_1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule with incompatible options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw, ro) -> /foo,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/bad_2.sd
Normal file
7
parser/tst/simple_tests/mount/bad_2.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule with incompatible options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw ro) -> /foo,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/bad_3.sd
Normal file
7
parser/tst/simple_tests/mount/bad_3.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule with incompatible options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw ro) fstype=procfs -> /foo,
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
#=Description basic mount rule
|
#=Description basic mount rule with incompatible options
|
||||||
#=EXRESULT PASS
|
#=EXRESULT FAIL
|
||||||
#
|
#
|
||||||
/usr/bin/foo {
|
/usr/bin/foo {
|
||||||
mount options=(rw ro) fstype=(procfs) none -> /foo,
|
mount options=(rw ro) fstype=(procfs) none -> /foo,
|
7
parser/tst/simple_tests/mount/bad_opt_29.sd
Normal file
7
parser/tst/simple_tests/mount/bad_opt_29.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting = options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(strictatime, nostrictatime) -> /foo,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/bad_opt_30.sd
Normal file
7
parser/tst/simple_tests/mount/bad_opt_30.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting = options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(lazytime, nolazytime) -> /foo,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/bad_opt_31.sd
Normal file
7
parser/tst/simple_tests/mount/bad_opt_31.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting = options
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(symfollow, nosymfollow) -> /foo,
|
||||||
|
}
|
@@ -3,5 +3,5 @@
|
|||||||
#=EXRESULT PASS
|
#=EXRESULT PASS
|
||||||
#
|
#
|
||||||
/usr/bin/foo {
|
/usr/bin/foo {
|
||||||
mount options=(rw, ro) -> /foo,
|
mount options=(rw nosuid) -> /foo,
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
#
|
|
||||||
#=Description basic mount rule
|
|
||||||
#=EXRESULT PASS
|
|
||||||
#
|
|
||||||
/usr/bin/foo {
|
|
||||||
mount options=(rw ro) -> /foo,
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
#
|
|
||||||
#=Description basic mount rule
|
|
||||||
#=EXRESULT PASS
|
|
||||||
#
|
|
||||||
/usr/bin/foo {
|
|
||||||
mount options=(rw ro) fstype=procfs -> /foo,
|
|
||||||
}
|
|
8
parser/tst/simple_tests/mount/ok_opt_56.sd
Normal file
8
parser/tst/simple_tests/mount/ok_opt_56.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "nostrictatime" mount option
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=nostrictatime /a -> /1,
|
||||||
|
mount options=(nostrictatime) /b -> /2,
|
||||||
|
mount options in (nostrictatime) /d -> /4,
|
||||||
|
}
|
8
parser/tst/simple_tests/mount/ok_opt_57.sd
Normal file
8
parser/tst/simple_tests/mount/ok_opt_57.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "lazytime" mount option
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=lazytime /a -> /1,
|
||||||
|
mount options=(lazytime) /b -> /2,
|
||||||
|
mount options in (lazytime) /d -> /4,
|
||||||
|
}
|
8
parser/tst/simple_tests/mount/ok_opt_58.sd
Normal file
8
parser/tst/simple_tests/mount/ok_opt_58.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "nolazytime" mount option
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=nolazytime /a -> /1,
|
||||||
|
mount options=(nolazytime) /b -> /2,
|
||||||
|
mount options in (nolazytime) /d -> /4,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_59.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_59.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "strictatime" mount option in combination
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw,strictatime) /c -> /3,
|
||||||
|
mount options in (ro,strictatime) /e -> /5,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_60.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_60.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "nostrictatime" mount option in combination
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw,nostrictatime) /c -> /3,
|
||||||
|
mount options in (ro,nostrictatime) /e -> /5,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_61.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_61.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "lazytime" mount option in combination
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw,lazytime) /c -> /3,
|
||||||
|
mount options in (ro,lazytime) /e -> /5,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_62.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_62.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "nolazytime" mount option in combination
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw,nolazytime) /c -> /3,
|
||||||
|
mount options in (ro,nolazytime) /e -> /5,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_63.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_63.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting options with in
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options in (strictatime, nostrictatime) -> /foo,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_64.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_64.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting options with in
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options in (lazytime, nolazytime) -> /foo,
|
||||||
|
}
|
8
parser/tst/simple_tests/mount/ok_opt_65.sd
Normal file
8
parser/tst/simple_tests/mount/ok_opt_65.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "nosymfollow" mount option
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=nosymfollow /a -> /1,
|
||||||
|
mount options=(nosymfollow) /b -> /2,
|
||||||
|
mount options in (nosymfollow) /d -> /4,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_66.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_66.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic rules to test the "symfollow" mount option in combination
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw,symfollow) /c -> /3,
|
||||||
|
mount options in (ro,symfollow) /e -> /5,
|
||||||
|
}
|
7
parser/tst/simple_tests/mount/ok_opt_67.sd
Normal file
7
parser/tst/simple_tests/mount/ok_opt_67.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rule conflicting options with in
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options in (symfollow, nosymfollow) -> /foo,
|
||||||
|
}
|
@@ -41,7 +41,7 @@ ifdef USE_SYSTEM
|
|||||||
LOGPROF?=aa-logprof
|
LOGPROF?=aa-logprof
|
||||||
else
|
else
|
||||||
# PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
|
# 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/
|
LIBAPPARMOR_PATH=../libraries/libapparmor/src/.libs/
|
||||||
LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
|
LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
|
||||||
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
|
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
|
||||||
|
@@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
# Xcompose
|
# Xcompose
|
||||||
owner @{HOME}/.XCompose r,
|
owner @{HOME}/.XCompose r,
|
||||||
|
/var/cache/libx11/compose/* r,
|
||||||
|
deny /var/cache/libx11/compose/* wlk,
|
||||||
|
|
||||||
# mouse themes
|
# mouse themes
|
||||||
/etc/X11/cursors/ r,
|
/etc/X11/cursors/ r,
|
||||||
|
@@ -34,8 +34,8 @@
|
|||||||
/usr/share/locale-langpack/** r,
|
/usr/share/locale-langpack/** r,
|
||||||
/usr/share/locale/** r,
|
/usr/share/locale/** r,
|
||||||
/usr/share/**/locale/** r,
|
/usr/share/**/locale/** r,
|
||||||
/usr/share/zoneinfo/ r,
|
/usr/share/zoneinfo{,-icu}/ r,
|
||||||
/usr/share/zoneinfo/** r,
|
/usr/share/zoneinfo{,-icu}/** r,
|
||||||
/usr/share/X11/locale/** r,
|
/usr/share/X11/locale/** r,
|
||||||
/run/systemd/journal/dev-log w,
|
/run/systemd/journal/dev-log w,
|
||||||
# systemd native journal API (see sd_journal_print(4))
|
# systemd native journal API (see sd_journal_print(4))
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
@{PROC}/cpuinfo r,
|
@{PROC}/cpuinfo r,
|
||||||
@{sys}/devices/system/cpu/ r,
|
@{sys}/devices/system/cpu/ r,
|
||||||
@{sys}/devices/system/cpu/online r,
|
@{sys}/devices/system/cpu/online r,
|
||||||
|
@{sys}/devices/system/cpu/possible r,
|
||||||
|
|
||||||
# glibc's *printf protections read the maps file
|
# glibc's *printf protections read the maps file
|
||||||
@{PROC}/@{pid}/{maps,auxv,status} r,
|
@{PROC}/@{pid}/{maps,auxv,status} r,
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
@{system_share_dirs}/mime/** r,
|
@{system_share_dirs}/mime/** r,
|
||||||
|
|
||||||
# per-user configurations
|
# per-user configurations
|
||||||
owner @{HOME}/.icons/ r,
|
owner @{HOME}/.icons/{,**} r,
|
||||||
owner @{HOME}/.recently-used.xbel* rw,
|
owner @{HOME}/.recently-used.xbel* rw,
|
||||||
owner @{HOME}/.local/share/recently-used.xbel* rw,
|
owner @{HOME}/.local/share/recently-used.xbel* rw,
|
||||||
owner @{HOME}/.config/user-dirs.dirs r,
|
owner @{HOME}/.config/user-dirs.dirs r,
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
# (src/intel/perf/gen_perf.c, load_oa_metrics())
|
# (src/intel/perf/gen_perf.c, load_oa_metrics())
|
||||||
@{PROC}/sys/dev/i915/perf_stream_paranoid r,
|
@{PROC}/sys/dev/i915/perf_stream_paranoid r,
|
||||||
|
|
||||||
|
@{sys}/devices/pci[0-9]*/**/{revision,config} r,
|
||||||
|
|
||||||
# User files
|
# User files
|
||||||
owner @{HOME}/.cache/ w, # if user clears all caches
|
owner @{HOME}/.cache/ w, # if user clears all caches
|
||||||
owner @{HOME}/.cache/mesa_shader_cache/ w,
|
owner @{HOME}/.cache/mesa_shader_cache/ w,
|
||||||
|
@@ -21,8 +21,12 @@
|
|||||||
|
|
||||||
@{sys}/devices/system/memory/block_size_bytes r,
|
@{sys}/devices/system/memory/block_size_bytes r,
|
||||||
|
|
||||||
|
owner @{HOME}/.cache/nvidia/ w,
|
||||||
|
owner @{HOME}/.cache/nvidia/GLCache/ rw,
|
||||||
|
owner @{HOME}/.cache/nvidia/GLCache/** rwk,
|
||||||
owner @{HOME}/.nv/ w,
|
owner @{HOME}/.nv/ w,
|
||||||
owner @{HOME}/.nv/GLCache/ rw,
|
owner @{HOME}/.nv/GLCache/ rw,
|
||||||
owner @{HOME}/.nv/GLCache/** rwk,
|
owner @{HOME}/.nv/GLCache/** rwk,
|
||||||
|
owner @{PROC}/@{pid}/comm r, # somehwere in libnvidia-glcore.so
|
||||||
|
|
||||||
unix (send, receive) type=dgram peer=(addr="@nvidia[0-9a-f]*"),
|
unix (send, receive) type=dgram peer=(addr="@nvidia[0-9a-f]*"),
|
||||||
|
@@ -9,6 +9,9 @@
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
/etc/ssl/openssl.cnf r,
|
/etc/ssl/openssl.cnf r,
|
||||||
|
/etc/ssl/openssl-*.cnf r,
|
||||||
|
/etc/ssl/{engdef,engines}.d/ r,
|
||||||
|
/etc/ssl/{engdef,engines}.d/*.cnf r,
|
||||||
/usr/share/ssl/openssl.cnf r,
|
/usr/share/ssl/openssl.cnf r,
|
||||||
@{PROC}/sys/crypto/fips_enabled r,
|
@{PROC}/sys/crypto/fips_enabled r,
|
||||||
|
|
||||||
|
@@ -11,26 +11,26 @@
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
# shared snippets for config files
|
# shared snippets for config files
|
||||||
/etc/php{,5,7}/**/ r,
|
/etc/php{,5,7,8}/**/ r,
|
||||||
/etc/php{,5,7}/**.ini r,
|
/etc/php{,5,7,8}/**.ini r,
|
||||||
|
|
||||||
# Xlibs
|
# Xlibs
|
||||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||||
# php extensions
|
# php extensions
|
||||||
/usr/lib{64,}/php{,5,7}/*/*.so mr,
|
/usr/lib{64,}/php{,5,7,8}/*/*.so mr,
|
||||||
|
|
||||||
# ICU (unicode support) data tables
|
# ICU (unicode support) data tables
|
||||||
/usr/share/icu/*/*.dat r,
|
/usr/share/icu/*/*.dat r,
|
||||||
|
|
||||||
# php session mmap socket
|
# php session mmap socket
|
||||||
/var/lib/php{,5,7}/session_mm_* rwlk,
|
/var/lib/php{,5,7,8}/session_mm_* rwlk,
|
||||||
# file based session handler
|
# file based session handler
|
||||||
/var/lib/php{,5,7}/sess_* rwlk,
|
/var/lib/php{,5,7,8}/sess_* rwlk,
|
||||||
/var/lib/php{,5,7}/sessions/* rwlk,
|
/var/lib/php{,5,7,8}/sessions/* rwlk,
|
||||||
|
|
||||||
# php libraries
|
# php libraries
|
||||||
/usr/share/php{,5,7}/ r,
|
/usr/share/php{,5,7,8}/ r,
|
||||||
/usr/share/php{,5,7}/** mr,
|
/usr/share/php{,5,7,8}/** mr,
|
||||||
|
|
||||||
# MySQL extension
|
# MySQL extension
|
||||||
/usr/share/mysql/** r,
|
/usr/share/mysql/** r,
|
||||||
|
@@ -22,4 +22,4 @@
|
|||||||
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
||||||
audit deny @{HOME}/.kde{,4}/share/apps/kmail{,2}/{,**} mrwkl,
|
audit deny @{HOME}/.kde{,4}/share/apps/kmail{,2}/{,**} mrwkl,
|
||||||
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
||||||
|
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
|
||||||
|
@@ -10,18 +10,19 @@
|
|||||||
#
|
#
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
/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],3.1[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],3.1[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}/python{2.[4-7],3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
|
||||||
|
|
||||||
/usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
|
/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],3.1[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],3.1[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}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
|
||||||
/usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
|
/usr/local/lib{,32,64}/python3.{1,}[0-9]/lib-dynload/*.so mr,
|
||||||
|
|
||||||
# Site-wide configuration
|
# 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
|
# shared python paths
|
||||||
/usr/share/{pyshared,pycentral,python-support}/** r,
|
/usr/share/{pyshared,pycentral,python-support}/** r,
|
||||||
@@ -34,4 +35,4 @@
|
|||||||
/usr/lib/wx/python/*.pth r,
|
/usr/lib/wx/python/*.pth r,
|
||||||
|
|
||||||
# python build configuration and headers
|
# 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,
|
||||||
|
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
|
||||||
|
}
|
@@ -12,6 +12,7 @@
|
|||||||
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
|
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
|
||||||
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
|
||||||
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
|
||||||
|
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
|
||||||
|
|
||||||
# Comment this out if using gpg plugin/addons
|
# Comment this out if using gpg plugin/addons
|
||||||
audit deny @{HOME}/.gnupg/{,**} mrwkl,
|
audit deny @{HOME}/.gnupg/{,**} mrwkl,
|
||||||
|
@@ -70,6 +70,7 @@ profile sanitized_helper {
|
|||||||
/opt/google/chrome{,-beta,-unstable}/chrome-sandbox PUxr,
|
/opt/google/chrome{,-beta,-unstable}/chrome-sandbox PUxr,
|
||||||
/opt/google/chrome{,-beta,-unstable}/google-chrome Pixr,
|
/opt/google/chrome{,-beta,-unstable}/google-chrome Pixr,
|
||||||
/opt/google/chrome{,-beta,-unstable}/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,
|
/opt/google/chrome{,-beta,-unstable}/{,**/}lib*.so{,.*} m,
|
||||||
|
|
||||||
# Full access
|
# Full access
|
||||||
|
@@ -2,5 +2,5 @@
|
|||||||
# video device access
|
# video device access
|
||||||
|
|
||||||
# System devices
|
# System devices
|
||||||
@{sys}/class/video4linux r,
|
@{sys}/class/video4linux/ r,
|
||||||
@{sys}/class/video4linux/** r,
|
@{sys}/class/video4linux/** r,
|
||||||
|
@@ -12,5 +12,6 @@
|
|||||||
# some services update wtmp, utmp, and lastlog with per-user
|
# some services update wtmp, utmp, and lastlog with per-user
|
||||||
# connection information
|
# connection information
|
||||||
/var/log/lastlog rwk,
|
/var/log/lastlog rwk,
|
||||||
/var/log/wtmp wk,
|
/var/log/wtmp rwk,
|
||||||
|
/var/log/btmp rwk,
|
||||||
/{,var/}run/utmp rwk,
|
/{,var/}run/utmp rwk,
|
||||||
|
@@ -16,7 +16,7 @@ profile lsb_release {
|
|||||||
/dev/tty rw,
|
/dev/tty rw,
|
||||||
|
|
||||||
/usr/bin/lsb_release r,
|
/usr/bin/lsb_release r,
|
||||||
/usr/bin/python3.[0-9] mr,
|
/usr/bin/python3.{1,}[0-9] mr,
|
||||||
|
|
||||||
/etc/debian_version r,
|
/etc/debian_version r,
|
||||||
/etc/default/apport r,
|
/etc/default/apport r,
|
||||||
@@ -28,6 +28,8 @@ profile lsb_release {
|
|||||||
/{usr/,}bin/dash ixr,
|
/{usr/,}bin/dash ixr,
|
||||||
/usr/bin/basename ixr,
|
/usr/bin/basename ixr,
|
||||||
/usr/bin/dpkg-query ixr,
|
/usr/bin/dpkg-query ixr,
|
||||||
|
/usr/bin/cat ixr,
|
||||||
|
/usr/bin/cut ixr,
|
||||||
/usr/bin/getopt ixr,
|
/usr/bin/getopt ixr,
|
||||||
/usr/bin/sed ixr,
|
/usr/bin/sed ixr,
|
||||||
/usr/bin/tr ixr,
|
/usr/bin/tr ixr,
|
||||||
|
@@ -52,10 +52,10 @@ profile nvidia_modprobe {
|
|||||||
# System files
|
# System files
|
||||||
|
|
||||||
/etc/modprobe.d/{,*.conf} r,
|
/etc/modprobe.d/{,*.conf} r,
|
||||||
/etc/nvidia/current/*.conf r,
|
/etc/nvidia/{current,legacy*,tesla*}/*.conf r,
|
||||||
@{sys}/module/ipmi_devintf/initstate r,
|
@{sys}/module/ipmi_devintf/initstate r,
|
||||||
@{sys}/module/ipmi_msghandler/initstate r,
|
@{sys}/module/ipmi_msghandler/initstate r,
|
||||||
@{sys}/module/nvidia/initstate r,
|
@{sys}/module/{drm,nvidia}/initstate r,
|
||||||
@{PROC}/cmdline r,
|
@{PROC}/cmdline r,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
|
|||||||
/{var,var/run,run}/log/journal/*/*.journal r,
|
/{var,var/run,run}/log/journal/*/*.journal r,
|
||||||
/{var/,}run/syslog-ng.ctl a,
|
/{var/,}run/syslog-ng.ctl a,
|
||||||
/{var/,}run/syslog-ng/additional-log-sockets.conf r,
|
/{var/,}run/syslog-ng/additional-log-sockets.conf r,
|
||||||
|
/{var,var/run,run}/log/journal/*.journal r,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
#include <local/sbin.syslog-ng>
|
#include <local/sbin.syslog-ng>
|
||||||
|
@@ -29,6 +29,8 @@ profile syslogd /{usr/,}{bin,sbin}/syslogd {
|
|||||||
/dev/log wl,
|
/dev/log wl,
|
||||||
/var/lib/*/dev/log wl,
|
/var/lib/*/dev/log wl,
|
||||||
|
|
||||||
|
/dev/kmsg r,
|
||||||
|
/proc/kmsg r,
|
||||||
/dev/tty* w,
|
/dev/tty* w,
|
||||||
/dev/xconsole rw,
|
/dev/xconsole rw,
|
||||||
/etc/syslog.conf r,
|
/etc/syslog.conf r,
|
||||||
|
33
profiles/apparmor.d/usr.lib.dovecot.script-login
Normal file
33
profiles/apparmor.d/usr.lib.dovecot.script-login
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# ------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 Michael Hirmke
|
||||||
|
# Copyright (C) 2020 Christian Boltz
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
|
# License published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# vim: ft=apparmor
|
||||||
|
|
||||||
|
#include <tunables/global>
|
||||||
|
|
||||||
|
profile dovecot-script-login /usr/lib/dovecot/script-login {
|
||||||
|
#include <abstractions/base>
|
||||||
|
#include <abstractions/dovecot-common>
|
||||||
|
#include <abstractions/nameservice>
|
||||||
|
|
||||||
|
capability setuid,
|
||||||
|
|
||||||
|
/usr/lib/dovecot/script-login mrPx,
|
||||||
|
|
||||||
|
# NOTE: You'll need to allow execution of your actual login script.
|
||||||
|
# The recommended way is to add a rule for it in local/usr.lib.dovecot.script-login
|
||||||
|
# for example
|
||||||
|
# /home/vmail/bin/postlogin.sh Px,
|
||||||
|
# and then to create the profile for the script.
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
#include <local/usr.lib.dovecot.script-login>
|
||||||
|
}
|
||||||
|
|
@@ -18,6 +18,10 @@
|
|||||||
capability setuid,
|
capability setuid,
|
||||||
capability sys_chroot,
|
capability sys_chroot,
|
||||||
|
|
||||||
|
# for metrics end-point (Prometheus)
|
||||||
|
network inet stream,
|
||||||
|
network inet6 stream,
|
||||||
|
|
||||||
/usr/lib/dovecot/stats mr,
|
/usr/lib/dovecot/stats mr,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
@@ -20,6 +20,9 @@ profile avahi-daemon /usr/{bin,sbin}/avahi-daemon {
|
|||||||
/etc/avahi/services/ r,
|
/etc/avahi/services/ r,
|
||||||
/etc/avahi/services/*.service r,
|
/etc/avahi/services/*.service r,
|
||||||
@{PROC}/@{pid}/fd/ r,
|
@{PROC}/@{pid}/fd/ r,
|
||||||
|
@{PROC}/1/environ r,
|
||||||
|
@{PROC}/cmdline r,
|
||||||
|
@{PROC}/sys/kernel/osrelease r,
|
||||||
/usr/{bin,sbin}/avahi-daemon mr,
|
/usr/{bin,sbin}/avahi-daemon mr,
|
||||||
/usr/share/avahi/introspection/*.introspect r,
|
/usr/share/avahi/introspection/*.introspect r,
|
||||||
/usr/share/dbus-1/interfaces/org.freedesktop.Avahi.*.xml r,
|
/usr/share/dbus-1/interfaces/org.freedesktop.Avahi.*.xml r,
|
||||||
|
@@ -116,8 +116,8 @@ profile /usr/sbin/dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
|
|||||||
|
|
||||||
/etc/libnl-3/classid r,
|
/etc/libnl-3/classid r,
|
||||||
|
|
||||||
/usr/lib{,64}/libvirt/libvirt_leaseshelper m,
|
/usr/lib{,64}/libvirt/libvirt_leaseshelper mr,
|
||||||
/usr/libexec/libvirt_leaseshelper m,
|
/usr/libexec/libvirt_leaseshelper mr,
|
||||||
|
|
||||||
owner @{PROC}/@{pid}/net/psched r,
|
owner @{PROC}/@{pid}/net/psched r,
|
||||||
owner @{PROC}/@{pid}/status r,
|
owner @{PROC}/@{pid}/status r,
|
||||||
|
@@ -31,7 +31,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
|||||||
capability sys_chroot,
|
capability sys_chroot,
|
||||||
capability sys_resource,
|
capability sys_resource,
|
||||||
|
|
||||||
signal send set=(int,quit,term) peer=/usr/lib/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=/usr/lib/dovecot/anvil),
|
||||||
|
|
||||||
@@ -55,10 +56,12 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
|||||||
/usr/lib/dovecot/managesieve-login Pxmr,
|
/usr/lib/dovecot/managesieve-login Pxmr,
|
||||||
/usr/lib/dovecot/pop3 mrPx,
|
/usr/lib/dovecot/pop3 mrPx,
|
||||||
/usr/lib/dovecot/pop3-login Pxmr,
|
/usr/lib/dovecot/pop3-login Pxmr,
|
||||||
|
/usr/lib/dovecot/script-login Px,
|
||||||
/usr/lib/dovecot/ssl-build-param rix,
|
/usr/lib/dovecot/ssl-build-param rix,
|
||||||
/usr/lib/dovecot/ssl-params mrPx,
|
/usr/lib/dovecot/ssl-params mrPx,
|
||||||
/usr/lib/dovecot/stats Px,
|
/usr/lib/dovecot/stats Px,
|
||||||
/usr/{bin,sbin}/dovecot mrix,
|
/usr/{bin,sbin}/dovecot mrix,
|
||||||
|
/usr/share/dovecot/dh.pem r,
|
||||||
/usr/share/dovecot/protocols.d/ r,
|
/usr/share/dovecot/protocols.d/ r,
|
||||||
/usr/share/dovecot/protocols.d/** r,
|
/usr/share/dovecot/protocols.d/** r,
|
||||||
/var/lib/dovecot/ w,
|
/var/lib/dovecot/ w,
|
||||||
|
@@ -21,6 +21,7 @@ profile nscd /usr/{bin,sbin}/nscd {
|
|||||||
capability setgid,
|
capability setgid,
|
||||||
capability setuid,
|
capability setuid,
|
||||||
|
|
||||||
|
/etc/machine-id r,
|
||||||
/etc/netgroup r,
|
/etc/netgroup r,
|
||||||
/etc/nscd.conf r,
|
/etc/nscd.conf r,
|
||||||
/usr/{bin,sbin}/nscd rmix,
|
/usr/{bin,sbin}/nscd rmix,
|
||||||
@@ -38,6 +39,13 @@ profile nscd /usr/{bin,sbin}/nscd {
|
|||||||
@{PROC}/@{pid}/fd/* r,
|
@{PROC}/@{pid}/fd/* r,
|
||||||
@{PROC}/@{pid}/mounts r,
|
@{PROC}/@{pid}/mounts r,
|
||||||
|
|
||||||
|
# systemd-userdb
|
||||||
|
/{etc,run,run/host,/usr/lib}/userdb/ r,
|
||||||
|
/{etc,run,run/host,/usr/lib}/userdb/*.{user,user-privileged,group,group-privileged} r,
|
||||||
|
|
||||||
|
# needed by unscd
|
||||||
|
@{run}/systemd/notify w,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
#include <local/usr.sbin.nscd>
|
#include <local/usr.sbin.nscd>
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
#include <abstractions/consoles>
|
#include <abstractions/consoles>
|
||||||
#include <abstractions/cups-client>
|
#include <abstractions/cups-client>
|
||||||
#include <abstractions/nameservice>
|
#include <abstractions/nameservice>
|
||||||
|
#include <abstractions/openssl>
|
||||||
#include <abstractions/samba>
|
#include <abstractions/samba>
|
||||||
#include <abstractions/user-tmp>
|
#include <abstractions/user-tmp>
|
||||||
#include <abstractions/wutmp>
|
#include <abstractions/wutmp>
|
||||||
@@ -41,6 +42,7 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
/usr/{bin,sbin}/smbldap-useradd Px,
|
/usr/{bin,sbin}/smbldap-useradd Px,
|
||||||
/var/cache/samba/** rwk,
|
/var/cache/samba/** rwk,
|
||||||
/var/{cache,lib}/samba/printing/printers.tdb mrw,
|
/var/{cache,lib}/samba/printing/printers.tdb mrw,
|
||||||
|
/var/lib/nscd/netgroup r,
|
||||||
/var/lib/samba/** rwk,
|
/var/lib/samba/** rwk,
|
||||||
/var/lib/sss/pubconf/kdcinfo.* r,
|
/var/lib/sss/pubconf/kdcinfo.* r,
|
||||||
/{,var/}run/dbus/system_bus_socket rw,
|
/{,var/}run/dbus/system_bus_socket rw,
|
||||||
|
@@ -43,6 +43,11 @@ profile dhclient /{usr/,}sbin/dhclient {
|
|||||||
@{PROC}/interrupts r,
|
@{PROC}/interrupts r,
|
||||||
@{PROC}/@{pid}/net/dev r,
|
@{PROC}/@{pid}/net/dev r,
|
||||||
@{PROC}/rtc r,
|
@{PROC}/rtc r,
|
||||||
|
|
||||||
|
# dhcliet wants to update its threads with functional names
|
||||||
|
# see lp1918410
|
||||||
|
owner @{PROC}/@{pid}/task/[0-9]*/comm rw,
|
||||||
|
|
||||||
# following rule shouldn't work, self is a symlink
|
# following rule shouldn't work, self is a symlink
|
||||||
@{PROC}/self/status r,
|
@{PROC}/self/status r,
|
||||||
/{usr/,}sbin/arp mrix,
|
/{usr/,}sbin/arp mrix,
|
||||||
|
@@ -121,6 +121,10 @@
|
|||||||
deny /usr/share/mozilla/extensions/**/ w,
|
deny /usr/share/mozilla/extensions/**/ w,
|
||||||
deny /usr/share/mozilla/ w,
|
deny /usr/share/mozilla/ w,
|
||||||
|
|
||||||
|
# needed by widevine
|
||||||
|
ptrace (trace) peer=@{profile_name},
|
||||||
|
@{HOME}/.mozilla/firefox/*/gmp-widevinecdm/*/lib*so m,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
# Local path is disabled, we only enable them for profiles we promote
|
# Local path is disabled, we only enable them for profiles we promote
|
||||||
# out of extras.
|
# out of extras.
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
|
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
|
||||||
#include <abstractions/base>
|
#include <abstractions/base>
|
||||||
#include <abstractions/nameservice>
|
#include <abstractions/nameservice>
|
||||||
|
#include <abstractions/openssl>
|
||||||
#include <abstractions/postfix-common>
|
#include <abstractions/postfix-common>
|
||||||
|
|
||||||
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
|
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
/etc/hosts.allow r,
|
/etc/hosts.allow r,
|
||||||
/etc/hosts.deny r,
|
/etc/hosts.deny r,
|
||||||
@{PROC}/net/dev r,
|
@{PROC}/net/dev r,
|
||||||
|
@{PROC}/sys/net/ipv4/ip_local_port_range r,
|
||||||
/usr/sbin/dhcpd rmix,
|
/usr/sbin/dhcpd rmix,
|
||||||
/var/lib/dhcp/{db/,}dhcpd.leases* rwl,
|
/var/lib/dhcp/{db/,}dhcpd.leases* rwl,
|
||||||
/var/lib/dhcp/etc/dhcpd.conf r,
|
/var/lib/dhcp/etc/dhcpd.conf r,
|
||||||
|
@@ -69,8 +69,8 @@ endif # USE_SYSTEM
|
|||||||
|
|
||||||
CFLAGS += -g -O0 -Wall -Wstrict-prototypes
|
CFLAGS += -g -O0 -Wall -Wstrict-prototypes
|
||||||
|
|
||||||
USE_SYSCTL:=$(shell echo "#include <sys/sysctl.h>" | cpp -dM >/dev/null 2>/dev/null && echo true)
|
SYSCTL_INCLUDE="\#include <sys/sysctl.h>"
|
||||||
|
USE_SYSCTL:=$(shell echo $(SYSCTL_INCLUDE) | cpp -dM >/dev/null 2>/dev/null && echo true)
|
||||||
|
|
||||||
SRC=access.c \
|
SRC=access.c \
|
||||||
at_secure.c \
|
at_secure.c \
|
||||||
@@ -307,6 +307,9 @@ unix_socket_client: unix_socket_client.c unix_socket_common.o
|
|||||||
unix_socket: unix_socket.c unix_socket_common.o unix_socket_client
|
unix_socket: unix_socket.c unix_socket_common.o unix_socket_client
|
||||||
${CC} ${CFLAGS} ${LDFLAGS} $(filter-out unix_socket_client, $^) -o $@ ${LDLIBS}
|
${CC} ${CFLAGS} ${LDFLAGS} $(filter-out unix_socket_client, $^) -o $@ ${LDLIBS}
|
||||||
|
|
||||||
|
mount: mount.c
|
||||||
|
${CC} ${CFLAGS} -std=gnu99 ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
||||||
|
|
||||||
tests: all
|
tests: all
|
||||||
@if [ `whoami` = "root" ] ;\
|
@if [ `whoami` = "root" ] ;\
|
||||||
then \
|
then \
|
||||||
|
@@ -16,7 +16,7 @@ fi
|
|||||||
out=$($1 -- cat /proc/self/attr/current 2>&1)
|
out=$($1 -- cat /proc/self/attr/current 2>&1)
|
||||||
rc=$?
|
rc=$?
|
||||||
|
|
||||||
if [ $rc -eq 0 ] && [ "$out" == "$2" ]; then
|
if [ $rc -eq 0 ] && [ "$out" = "$2" ]; then
|
||||||
echo PASS
|
echo PASS
|
||||||
exit 0
|
exit 0
|
||||||
elif [ $rc -ne 0 ]; then
|
elif [ $rc -ne 0 ]; then
|
||||||
|
@@ -97,7 +97,7 @@ for TEST in ${TESTS} ; do
|
|||||||
|
|
||||||
# no capabilities allowed
|
# no capabilities allowed
|
||||||
genprofile ${my_entries}
|
genprofile ${my_entries}
|
||||||
if [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ] ; then
|
if [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ] ; then
|
||||||
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
|
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
|
||||||
# capability + ptrace rule needed between pids
|
# capability + ptrace rule needed between pids
|
||||||
runchecktest "${TEST} -- no caps" pass ${my_arg}
|
runchecktest "${TEST} -- no caps" pass ${my_arg}
|
||||||
@@ -111,9 +111,9 @@ for TEST in ${TESTS} ; do
|
|||||||
|
|
||||||
# iterate through each of the capabilities
|
# iterate through each of the capabilities
|
||||||
for cap in ${CAPABILITIES} ; do
|
for cap in ${CAPABILITIES} ; do
|
||||||
if [ "X$(eval echo \${${TEST}_${cap}})" == "XTRUE" ] ; then
|
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
|
||||||
expected_result=pass
|
expected_result=pass
|
||||||
elif [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ]; then
|
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
|
||||||
expected_result=pass
|
expected_result=pass
|
||||||
else
|
else
|
||||||
expected_result=fail
|
expected_result=fail
|
||||||
@@ -126,7 +126,7 @@ for TEST in ${TESTS} ; do
|
|||||||
# a subprofile.
|
# a subprofile.
|
||||||
settest ${testwrapper}
|
settest ${testwrapper}
|
||||||
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} ${my_entries}
|
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} ${my_entries}
|
||||||
if [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ] ; then
|
if [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ] ; then
|
||||||
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
|
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
|
||||||
# capability + ptrace rule needed between pids
|
# capability + ptrace rule needed between pids
|
||||||
runchecktest "${TEST} changehat -- no caps" pass $bin/${TEST} ${my_arg}
|
runchecktest "${TEST} changehat -- no caps" pass $bin/${TEST} ${my_arg}
|
||||||
@@ -139,9 +139,9 @@ for TEST in ${TESTS} ; do
|
|||||||
runchecktest "${TEST} changehat -- all caps" pass $bin/${TEST} ${my_arg}
|
runchecktest "${TEST} changehat -- all caps" pass $bin/${TEST} ${my_arg}
|
||||||
|
|
||||||
for cap in ${CAPABILITIES} ; do
|
for cap in ${CAPABILITIES} ; do
|
||||||
if [ "X$(eval echo \${${TEST}_${cap}})" == "XTRUE" ] ; then
|
if [ "X$(eval echo \${${TEST}_${cap}})" = "XTRUE" ] ; then
|
||||||
expected_result=pass
|
expected_result=pass
|
||||||
elif [ "${TEST}" == "syscall_ptrace" -a "$(kernel_features ptrace)" == "true" ]; then
|
elif [ "${TEST}" = "syscall_ptrace" -a "$(kernel_features ptrace)" = "true" ]; then
|
||||||
expected_result=pass
|
expected_result=pass
|
||||||
else
|
else
|
||||||
expected_result=fail
|
expected_result=fail
|
||||||
@@ -156,75 +156,75 @@ cap=sys_chroot
|
|||||||
settest syscall_chroot
|
settest syscall_chroot
|
||||||
|
|
||||||
# test deny keyword works
|
# test deny keyword works
|
||||||
genprofile cap:${cap}:deny ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, deny keyword" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, deny keyword" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow keyword works
|
# test allow keyword works
|
||||||
genprofile cap:${cap}:allow ${syscall_chroot_extra_entries}
|
genprofile qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow keyword" pass ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow keyword" pass ${syscall_chroot_args}
|
||||||
|
|
||||||
### allow/deny overlap tests ###
|
### allow/deny overlap tests ###
|
||||||
|
|
||||||
# test allow & deny keyword behavior, allow first
|
# test allow & deny keyword behavior, allow first
|
||||||
genprofile cap:${cap}:allow cap:${cap}:deny ${syscall_chroot_extra_entries}
|
genprofile qual=allow:cap:${cap} qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow & deny keyword behavior, allow first
|
# test implicit allow & deny keyword behavior, allow first
|
||||||
genprofile cap:${cap} cap:${cap}:deny ${syscall_chroot_extra_entries}
|
genprofile cap:${cap} qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow & deny keyword behavior, deny first
|
# test allow & deny keyword behavior, deny first
|
||||||
genprofile cap:${cap}:deny cap:${cap}:allow ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:${cap} qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow & deny keyword behavior, deny first
|
# test implicit allow & deny keyword behavior, deny first
|
||||||
genprofile cap:${cap}:deny cap:${cap} ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:${cap} cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow all & deny all capability keyword behavior, allow first
|
# test allow all & deny all capability keyword behavior, allow first
|
||||||
genprofile cap:ALL:allow cap:ALL:deny ${syscall_chroot_extra_entries}
|
genprofile qual=allow:cap:ALL qual=deny:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow all & deny all capability keyword behavior, allow first
|
# test implicit allow all & deny all capability keyword behavior, allow first
|
||||||
genprofile cap:ALL cap:ALL:deny ${syscall_chroot_extra_entries}
|
genprofile cap:ALL qual=deny:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny all caps keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny all caps keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow all & deny all capability keyword behavior, deny first
|
# test allow all & deny all capability keyword behavior, deny first
|
||||||
genprofile cap:ALL:deny cap:ALL:allow ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:ALL qual=allow:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow all & deny all capability keyword behavior, deny first
|
# test implicit allow all & deny all capability keyword behavior, deny first
|
||||||
genprofile cap:ALL:deny cap:ALL ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:ALL cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all caps keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow all & deny keywords behavior, allow first
|
# test allow all & deny keywords behavior, allow first
|
||||||
genprofile cap:ALL:allow cap:${cap}:deny ${syscall_chroot_extra_entries}
|
genprofile qual=allow:cap:ALL qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow all & deny keywords behavior, allow first
|
# test implicit allow all & deny keywords behavior, allow first
|
||||||
genprofile cap:ALL cap:${cap}:deny ${syscall_chroot_extra_entries}
|
genprofile cap:ALL qual=deny:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow all & deny keywords behavior, deny first
|
# test allow all & deny keywords behavior, deny first
|
||||||
genprofile cap:${cap}:deny cap:ALL:allow ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:${cap} qual=allow:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow all & deny keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow all & deny keywords behavior, deny first
|
# test implicit allow all & deny keywords behavior, deny first
|
||||||
genprofile cap:${cap}:deny cap:ALL ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:${cap} cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow all & deny keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow & deny all keywords behavior, allow first
|
# test allow & deny all keywords behavior, allow first
|
||||||
genprofile cap:${cap}:allow cap:ALL:deny ${syscall_chroot_extra_entries}
|
genprofile qual=allow:cap:${cap} qual=deny:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow & deny all keywords behavior, allow first
|
# test implicit allow & deny all keywords behavior, allow first
|
||||||
genprofile cap:${cap} cap:ALL:deny ${syscall_chroot_extra_entries}
|
genprofile cap:${cap} qual=deny:cap:ALL ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, allow first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, allow first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test allow & deny all keywords behavior, deny first
|
# test allow & deny all keywords behavior, deny first
|
||||||
genprofile cap:ALL:deny cap:${cap}:allow ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:ALL qual=allow:cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, allow & deny all keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
|
||||||
# test implicit allow & deny all keywords behavior, deny first
|
# test implicit allow & deny all keywords behavior, deny first
|
||||||
genprofile cap:ALL:deny cap:${cap} ${syscall_chroot_extra_entries}
|
genprofile qual=deny:cap:ALL cap:${cap} ${syscall_chroot_extra_entries}
|
||||||
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, deny first" fail ${syscall_chroot_args}
|
runchecktest "syscall_chroot -- capability ${cap}, implicit allow & deny all keyword, deny first" fail ${syscall_chroot_args}
|
||||||
|
@@ -47,7 +47,7 @@ runchecktest "NO CHANGEPROFILE (access parent file)" pass nochange $file
|
|||||||
runchecktest "NO CHANGEPROFILE (access sub file)" fail nochange $subfile
|
runchecktest "NO CHANGEPROFILE (access sub file)" fail nochange $subfile
|
||||||
|
|
||||||
errno=EACCES
|
errno=EACCES
|
||||||
if [ "$(kernel_features domain/stack)" == "true" ]; then
|
if [ "$(kernel_features domain/stack)" = "true" ]; then
|
||||||
# The returned errno changed in the set of kernel patches that
|
# The returned errno changed in the set of kernel patches that
|
||||||
# introduced AppArmor profile stacking
|
# introduced AppArmor profile stacking
|
||||||
errno=ENOENT
|
errno=ENOENT
|
||||||
|
@@ -18,7 +18,7 @@ cleancorefile()
|
|||||||
checkcorefile()
|
checkcorefile()
|
||||||
{
|
{
|
||||||
# global _testdesc _pfmode _known outfile
|
# global _testdesc _pfmode _known outfile
|
||||||
if [ ${1:0:1} == "x" ] ; then
|
if [ ${1:0:1} = "x" ] ; then
|
||||||
requirement=${1#x}
|
requirement=${1#x}
|
||||||
_known=" (known problem)"
|
_known=" (known problem)"
|
||||||
else
|
else
|
||||||
|
@@ -65,7 +65,9 @@ okperm=rwl
|
|||||||
badperm=wl
|
badperm=wl
|
||||||
af_unix=""
|
af_unix=""
|
||||||
|
|
||||||
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
|
if [ "$(kernel_features network_v8)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
|
||||||
|
af_unix="unix:create"
|
||||||
|
elif [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
|
||||||
af_unix="unix:create"
|
af_unix="unix:create"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ local_runchecktest()
|
|||||||
|
|
||||||
checktestbg
|
checktestbg
|
||||||
|
|
||||||
if [ "$teststatus" == "pass" -a -n "$actual_confinement" -a "$actual_confinement" != "$expected_confinement" ]
|
if [ "$teststatus" = "pass" -a -n "$actual_confinement" -a "$actual_confinement" != "$expected_confinement" ]
|
||||||
then
|
then
|
||||||
echo "Error: ${testname} failed. Test '${_testdesc}' actual confinement '$actual_confinement' differed from expected confinement '$expected_confinement'"
|
echo "Error: ${testname} failed. Test '${_testdesc}' actual confinement '$actual_confinement' differed from expected confinement '$expected_confinement'"
|
||||||
testfailed
|
testfailed
|
||||||
|
@@ -43,11 +43,19 @@ stackthirdok="change_profile->:&$thirdtest"
|
|||||||
|
|
||||||
touch $file $otherfile $sharedfile $thirdfile
|
touch $file $otherfile $sharedfile $thirdfile
|
||||||
|
|
||||||
if [ "$(kernel_features domain/fix_binfmt_elf_mmap)" == "true" ]; then
|
# We used to do a conditional test (below) for mmap permissions to
|
||||||
elfmmap="m"
|
# address the change introduced by
|
||||||
else
|
# 9f834ec18defc369d73ccf9e87a2790bfa05bf46 but there are too many
|
||||||
elfmmap=""
|
# kernels in the wild with a backport/cherrypick of that commit that
|
||||||
fi
|
# skipped cherry-picking 34c426acb75cc21bdf84685e106db0c1a3565057
|
||||||
|
# meaning the below conditional check has the wrong results for those
|
||||||
|
# kernels. Since this test is not about testing mmap just always add
|
||||||
|
# the mmap perm
|
||||||
|
#if [ "$(kernel_features domain/fix_binfmt_elf_mmap)" = "true" ]; then
|
||||||
|
# elfmmap="m"
|
||||||
|
#else
|
||||||
|
# elfmmap=""
|
||||||
|
#fi
|
||||||
|
|
||||||
# Verify file access and contexts by an unconfined process
|
# Verify file access and contexts by an unconfined process
|
||||||
runchecktest "EXEC_STACK (unconfined - file)" pass -f $file
|
runchecktest "EXEC_STACK (unconfined - file)" pass -f $file
|
||||||
@@ -72,7 +80,7 @@ runchecktest "EXEC_STACK (not stacked - bad mode)" fail -l "$test" -m complain
|
|||||||
|
|
||||||
# Verify file access and contexts by 2 stacked profiles
|
# Verify file access and contexts by 2 stacked profiles
|
||||||
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
||||||
image=$othertest addimage:$test $otherok $sharedok $getcon $test:r$elfmmap
|
image=$othertest addimage:$test $otherok $sharedok $getcon $test:rm
|
||||||
runchecktest_errno EACCES "EXEC_STACK (2 stacked - file)" fail -- $test -f $file
|
runchecktest_errno EACCES "EXEC_STACK (2 stacked - file)" fail -- $test -f $file
|
||||||
runchecktest_errno EACCES "EXEC_STACK (2 stacked - otherfile)" fail -- $test -f $otherfile
|
runchecktest_errno EACCES "EXEC_STACK (2 stacked - otherfile)" fail -- $test -f $otherfile
|
||||||
runchecktest_errno EACCES "EXEC_STACK (2 stacked - thirdfile)" fail -- $test -f $thirdfile
|
runchecktest_errno EACCES "EXEC_STACK (2 stacked - thirdfile)" fail -- $test -f $thirdfile
|
||||||
@@ -85,7 +93,7 @@ runchecktest "EXEC_STACK (2 stacked - bad mode)" fail -- $test -l "${test}//&${t
|
|||||||
# Verify file access and contexts by 3 stacked profiles
|
# Verify file access and contexts by 3 stacked profiles
|
||||||
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
||||||
image=$othertest addimage:$test $otherok $sharedok $getcon $test:"rix -> &$thirdtest" -- \
|
image=$othertest addimage:$test $otherok $sharedok $getcon $test:"rix -> &$thirdtest" -- \
|
||||||
image=$thirdtest addimage:$test $thirdok $sharedok $getcon $test:r$elfmmap
|
image=$thirdtest addimage:$test $thirdok $sharedok $getcon $test:rm
|
||||||
runchecktest_errno EACCES "EXEC_STACK (3 stacked - file)" fail -- $test -- $test -f $file
|
runchecktest_errno EACCES "EXEC_STACK (3 stacked - file)" fail -- $test -- $test -f $file
|
||||||
runchecktest_errno EACCES "EXEC_STACK (3 stacked - otherfile)" fail -- $test -- $test -f $otherfile
|
runchecktest_errno EACCES "EXEC_STACK (3 stacked - otherfile)" fail -- $test -- $test -f $otherfile
|
||||||
runchecktest_errno EACCES "EXEC_STACK (3 stacked - thirdfile)" fail -- $test -- $test -f $thirdfile
|
runchecktest_errno EACCES "EXEC_STACK (3 stacked - thirdfile)" fail -- $test -- $test -f $thirdfile
|
||||||
@@ -95,7 +103,7 @@ runchecktest "EXEC_STACK (3 stacked - okcon)" pass -- $test -- $test -l "${third
|
|||||||
|
|
||||||
genprofile -I $sharedok $stackotherok $stackthirdok $test:"rix -> &$othertest" -- \
|
genprofile -I $sharedok $stackotherok $stackthirdok $test:"rix -> &$othertest" -- \
|
||||||
image=$othertest addimage:$test $sharedok $stackthirdok $test:"rix -> &$thirdtest" -- \
|
image=$othertest addimage:$test $sharedok $stackthirdok $test:"rix -> &$thirdtest" -- \
|
||||||
image=$thirdtest addimage:$test $sharedok $stackthirdok $test:r$elfmmap
|
image=$thirdtest addimage:$test $sharedok $stackthirdok $test:rm
|
||||||
# Triggered an AppArmor WARN in the initial stacking patch set
|
# Triggered an AppArmor WARN in the initial stacking patch set
|
||||||
runchecktest "EXEC_STACK (3 stacked - old AA WARN)" pass -p $othertest -- $test -p $thirdtest -f $sharedfile
|
runchecktest "EXEC_STACK (3 stacked - old AA WARN)" pass -p $othertest -- $test -p $thirdtest -f $sharedfile
|
||||||
|
|
||||||
@@ -126,7 +134,7 @@ runchecktest "EXEC_STACK (stacked with namespaced profile - okcon)" pass -- $tes
|
|||||||
|
|
||||||
# Verify file access and contexts in mixed mode
|
# Verify file access and contexts in mixed mode
|
||||||
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
genprofile -I $fileok $sharedok $getcon $test:"ix -> &$othertest" -- \
|
||||||
image=$othertest flag:complain addimage:$test $otherok $sharedok $getcon $test:r$elfmmap
|
image=$othertest flag:complain addimage:$test $otherok $sharedok $getcon $test:rm
|
||||||
runchecktest "EXEC_STACK (mixed mode - file)" pass -- $test -f $file
|
runchecktest "EXEC_STACK (mixed mode - file)" pass -- $test -f $file
|
||||||
runchecktest_errno EACCES "EXEC_STACK (mixed mode - otherfile)" fail -- $test -f $otherfile
|
runchecktest_errno EACCES "EXEC_STACK (mixed mode - otherfile)" fail -- $test -f $otherfile
|
||||||
runchecktest "EXEC_STACK (mixed mode - sharedfile)" pass -- $test -f $sharedfile
|
runchecktest "EXEC_STACK (mixed mode - sharedfile)" pass -- $test -f $sharedfile
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
# in the name.
|
# in the name.
|
||||||
#=END
|
#=END
|
||||||
|
|
||||||
|
LANG=C
|
||||||
|
|
||||||
pwd=`dirname $0`
|
pwd=`dirname $0`
|
||||||
pwd=`cd $pwd ; /bin/pwd`
|
pwd=`cd $pwd ; /bin/pwd`
|
||||||
|
|
||||||
|
@@ -35,10 +35,17 @@ sub usage {
|
|||||||
print STDERR "Usage $0 [--nowarn|--escape] execname [rules]\n";
|
print STDERR "Usage $0 [--nowarn|--escape] execname [rules]\n";
|
||||||
print STDERR " $0 --help\n";
|
print STDERR " $0 --help\n";
|
||||||
print STDERR " $0 --stdin\n";
|
print STDERR " $0 --stdin\n";
|
||||||
|
print STDERR "Options:\n";
|
||||||
print STDERR " nowarn: don't warn if execname does not exist\n";
|
print STDERR " nowarn: don't warn if execname does not exist\n";
|
||||||
print STDERR " nodefault: don't include default rules/ldd output\n";
|
print STDERR " nodefault: don't include default rules/ldd output\n";
|
||||||
print STDERR " escape: escape stuff that would be treated as regexs\n";
|
print STDERR " escape: escape stuff that would be treated as regexs\n";
|
||||||
print STDERR " help: print this message\n";
|
print STDERR " help: print this message\n";
|
||||||
|
print STDERR "Rule Qualifiers:\n";
|
||||||
|
print STDERR " qualifiers can optionally be added to a rule with 'qual='\n";
|
||||||
|
print STDERR " Examples:\n";
|
||||||
|
print STDERR " /path/to/file:rw\n";
|
||||||
|
print STDERR " qual=audit:/path/to/file:rw\n";
|
||||||
|
print STDERR " qual=audit,deny:/path/to/file:rw\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
# genprofile passes in $bin:w as default rule atm
|
# genprofile passes in $bin:w as default rule atm
|
||||||
@@ -139,185 +146,183 @@ sub gen_binary($) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_netdomain($) {
|
sub gen_netdomain($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
# only split on single ':'s
|
# only split on single ':'s
|
||||||
my @rules = split (/(?<!:):(?!:)/, $rule);
|
my @rules = split (/(?<!:):(?!:)/, $rule);
|
||||||
# convert '::' to ':' -- for port designations
|
# convert '::' to ':' -- for port designations
|
||||||
foreach (@rules) { s/::/:/g; }
|
foreach (@rules) { s/::/:/g; }
|
||||||
push (@{$output_rules{$hat}}, " @rules,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}@rules,\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_network($) {
|
sub gen_network($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
push (@{$output_rules{$hat}}, " @rules,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}@rules,\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_unix($) {
|
sub gen_unix($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
if ($rule =~ /^unix:ALL$/) {
|
if ($rule =~ /^unix:ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " unix,\n");
|
push (@{$output_rules{$hat}}, " unix,\n");
|
||||||
} else {
|
} else {
|
||||||
$rule =~ s/:/ /g;
|
$rule =~ s/:/ /g;
|
||||||
push(@{$output_rules{$hat}}, " " . $rule . ",\n");
|
push(@{$output_rules{$hat}}, " " . $qualifier . $rule . ",\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_cap($) {
|
sub gen_cap($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " capability,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}capability,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " capability $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}capability $rules[1],\n");
|
||||||
}
|
|
||||||
} elsif (@rules == 3) {
|
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
|
||||||
push (@{$output_rules{$hat}}, " $rules[2] capability,\n");
|
|
||||||
} else {
|
|
||||||
push (@{$output_rules{$hat}}, " $rules[2] capability $rules[1],\n");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid capability description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid capability description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_ptrace($) {
|
sub gen_ptrace($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " ptrace,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}ptrace,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " ptrace $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}ptrace $rules[1],\n");
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " ptrace $rules[1] $rules[2],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}ptrace $rules[1] $rules[2],\n");
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid ptrace description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid ptrace description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_signal($) {
|
sub gen_signal($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " signal,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}signal,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " signal $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}signal $rules[1],\n");
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " signal $rules[1] $rules[2],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}signal $rules[1] $rules[2],\n");
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid signal description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid signal description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_mount($) {
|
sub gen_mount($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " mount,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1],\n");
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2],\n");
|
||||||
} elsif (@rules == 4) {
|
} elsif (@rules == 4) {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3],\n");
|
||||||
} elsif (@rules == 5) {
|
} elsif (@rules == 5) {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
||||||
} elsif (@rules == 6) {
|
} elsif (@rules == 6) {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
||||||
} elsif (@rules == 7) {
|
} elsif (@rules == 7) {
|
||||||
push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid mount description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid mount description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_remount($) {
|
sub gen_remount($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " remount,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1],\n");
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2],\n");
|
||||||
} elsif (@rules == 4) {
|
} elsif (@rules == 4) {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3],\n");
|
||||||
} elsif (@rules == 5) {
|
} elsif (@rules == 5) {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
||||||
} elsif (@rules == 6) {
|
} elsif (@rules == 6) {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
||||||
} elsif (@rules == 7) {
|
} elsif (@rules == 7) {
|
||||||
push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid remount description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid remount description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_umount($) {
|
sub gen_umount($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " umount,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1],\n");
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2],\n");
|
||||||
} elsif (@rules == 4) {
|
} elsif (@rules == 4) {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3],\n");
|
||||||
} elsif (@rules == 5) {
|
} elsif (@rules == 5) {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4],\n");
|
||||||
} elsif (@rules == 6) {
|
} elsif (@rules == 6) {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n");
|
||||||
} elsif (@rules == 7) {
|
} elsif (@rules == 7) {
|
||||||
push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n");
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid umount description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid umount description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_pivot_root($) {
|
sub gen_pivot_root($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " pivot_root,\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}pivot_root,\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " pivot_root $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}pivot_root $rules[1],\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid pivot_root description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid pivot_root description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_file($) {
|
sub gen_file($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
|
if (!$qualifier) {
|
||||||
|
$qualifier = "";
|
||||||
|
}
|
||||||
|
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
# default: file rules
|
# default: file rules
|
||||||
if (@rules == 1) {
|
if (@rules == 1) {
|
||||||
# support raw rules
|
# support raw rules
|
||||||
push (@{$output_rules{$hat}}, " $rules[0],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}$rules[0],\n");
|
||||||
} elsif (@rules == 2) {
|
} elsif (@rules == 2) {
|
||||||
if ($escape) {
|
if ($escape) {
|
||||||
$rules[0]=~ s/(["[\]{}\:])/\\$1/g;
|
$rules[0]=~ s/(["[\]{}\:])/\\$1/g;
|
||||||
$rules[0]=~ s/(\#)/\\043/g;
|
$rules[0]=~ s/(\#)/\\043/g;
|
||||||
}
|
}
|
||||||
if ($rules[0]=~ /[\s\!\"\^]/) {
|
if ($rules[0]=~ /[\s\!\"\^]/) {
|
||||||
push (@{$output_rules{$hat}}, " \"$rules[0]\" $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}\"$rules[0]\" $rules[1],\n");
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " $rules[0] $rules[1],\n");
|
push (@{$output_rules{$hat}}, " ${qualifier}$rules[0] $rules[1],\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid file access '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid file access '$rule', ignored\n";
|
||||||
@@ -334,33 +339,33 @@ sub gen_flag($) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_change_profile($) {
|
sub gen_change_profile($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules == 2) {
|
if (@rules == 2) {
|
||||||
if ($rules[1] =~ /^ALL$/) {
|
if ($rules[1] =~ /^ALL$/) {
|
||||||
push (@{$output_rules{$hat}}, " change_profile,\n",);
|
push (@{$output_rules{$hat}}, " ${qualifier}change_profile,\n",);
|
||||||
} else {
|
} else {
|
||||||
push (@{$output_rules{$hat}}, " change_profile -> $rules[1],\n",);
|
push (@{$output_rules{$hat}}, " ${qualifier}change_profile -> $rules[1],\n",);
|
||||||
}
|
}
|
||||||
} elsif (@rules == 3) {
|
} elsif (@rules == 3) {
|
||||||
push (@{$output_rules{$hat}}, " change_profile $rules[1] -> $rules[2],\n",);
|
push (@{$output_rules{$hat}}, " ${qualifier}change_profile $rules[1] -> $rules[2],\n",);
|
||||||
} elsif (@rules == 4) {
|
} elsif (@rules == 4) {
|
||||||
push (@{$output_rules{$hat}}, " change_profile $rules[1] $rules[2] -> $rules[3],\n",);
|
push (@{$output_rules{$hat}}, " ${qualifier}change_profile $rules[1] $rules[2] -> $rules[3],\n",);
|
||||||
} else {
|
} else {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid change_profile description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid change_profile description '$rule', ignored\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub gen_hat($) {
|
sub gen_hat($@) {
|
||||||
my $rule = shift;
|
my ($rule, $qualifier) = @_;
|
||||||
my @rules = split (/:/, $rule);
|
my @rules = split (/:/, $rule);
|
||||||
if (@rules != 2) {
|
if (@rules != 2) {
|
||||||
(!$nowarn) && print STDERR "Warning: invalid hat description '$rule', ignored\n";
|
(!$nowarn) && print STDERR "Warning: invalid hat description '$rule', ignored\n";
|
||||||
} else {
|
} else {
|
||||||
$hat = $rules[1];
|
$hat = $rules[1];
|
||||||
# give every profile/hat access to change_hat
|
# give every profile/hat access to change_hat
|
||||||
@{$output_rules{$hat}} = ( " /proc/*/attr/current w,\n",);
|
@{$output_rules{$hat}} = ( " ${qualifier}/proc/*/attr/current w,\n",);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,39 +403,47 @@ sub gen_from_args() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for my $rule (@ARGV) {
|
for my $rule (@ARGV) {
|
||||||
|
my $qualifier = "";
|
||||||
|
if ($rule =~ /^qual=([^:]*):(.*)/) {
|
||||||
|
# Strip qualifiers from rule to pass as separate argument
|
||||||
|
$qualifier = "$1 ";
|
||||||
|
$rule = $2;
|
||||||
|
$qualifier =~ s/,/ /g;
|
||||||
|
}
|
||||||
|
|
||||||
#($fn, @rules) = split (/:/, $rule);
|
#($fn, @rules) = split (/:/, $rule);
|
||||||
if ($rule =~ /^(tcp|udp)/) {
|
if ($rule =~ /^(tcp|udp)/) {
|
||||||
# netdomain rules
|
# netdomain rules
|
||||||
gen_netdomain($rule);
|
gen_netdomain($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^network:/) {
|
} elsif ($rule =~ /^network:/) {
|
||||||
gen_network($rule);
|
gen_network($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^unix:/) {
|
} elsif ($rule =~ /^unix:/) {
|
||||||
gen_unix($rule);
|
gen_unix($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^cap:/) {
|
} elsif ($rule =~ /^cap:/) {
|
||||||
gen_cap($rule);
|
gen_cap($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^ptrace:/) {
|
} elsif ($rule =~ /^ptrace:/) {
|
||||||
gen_ptrace($rule);
|
gen_ptrace($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^signal:/) {
|
} elsif ($rule =~ /^signal:/) {
|
||||||
gen_signal($rule);
|
gen_signal($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^mount:/) {
|
} elsif ($rule =~ /^mount:/) {
|
||||||
gen_mount($rule);
|
gen_mount($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^remount:/) {
|
} elsif ($rule =~ /^remount:/) {
|
||||||
gen_remount($rule);
|
gen_remount($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^umount:/) {
|
} elsif ($rule =~ /^umount:/) {
|
||||||
gen_umount($rule);
|
gen_umount($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^pivot_root:/) {
|
} elsif ($rule =~ /^pivot_root:/) {
|
||||||
gen_pivot_root($rule);
|
gen_pivot_root($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^flag:/) {
|
} elsif ($rule =~ /^flag:/) {
|
||||||
gen_flag($rule);
|
gen_flag($rule);
|
||||||
} elsif ($rule =~ /^hat:/) {
|
} elsif ($rule =~ /^hat:/) {
|
||||||
gen_hat($rule);
|
gen_hat($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^change_profile:/) {
|
} elsif ($rule =~ /^change_profile:/) {
|
||||||
gen_change_profile($rule);
|
gen_change_profile($rule, $qualifier);
|
||||||
} elsif ($rule =~ /^addimage:/) {
|
} elsif ($rule =~ /^addimage:/) {
|
||||||
gen_addimage($rule);
|
gen_addimage($rule);
|
||||||
$addimage = 1;
|
$addimage = 1;
|
||||||
} else {
|
} else {
|
||||||
gen_file($rule);
|
gen_file($rule, $qualifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,27 +14,163 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct mnt_keyword_table {
|
||||||
|
const char *keyword;
|
||||||
|
unsigned long set;
|
||||||
|
unsigned long clear;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mnt_keyword_table mnt_opts_table[] = {
|
||||||
|
{ "rw", 0, MS_RDONLY }, /* read-write */
|
||||||
|
{ "ro", MS_RDONLY, 0 }, /* read-only */
|
||||||
|
|
||||||
|
{ "exec", 0, MS_NOEXEC }, /* permit execution of binaries */
|
||||||
|
{ "noexec", MS_NOEXEC, 0 }, /* don't execute binaries */
|
||||||
|
|
||||||
|
{ "suid", 0, MS_NOSUID }, /* honor suid executables */
|
||||||
|
{ "nosuid", MS_NOSUID, 0 }, /* don't honor suid executables */
|
||||||
|
|
||||||
|
{ "dev", 0, MS_NODEV }, /* interpret device files */
|
||||||
|
{ "nodev", MS_NODEV, 0 }, /* don't interpret devices */
|
||||||
|
|
||||||
|
{ "async", 0, MS_SYNCHRONOUS }, /* asynchronous I/O */
|
||||||
|
{ "sync", MS_SYNCHRONOUS, 0 }, /* synchronous I/O */
|
||||||
|
|
||||||
|
{ "loud", 0, MS_SILENT }, /* print out messages. */
|
||||||
|
{ "silent", MS_SILENT, 0 }, /* be quiet */
|
||||||
|
|
||||||
|
{ "nomand", 0, MS_MANDLOCK }, /* forbid mandatory locks on this FS */
|
||||||
|
{ "mand", MS_MANDLOCK, 0 }, /* allow mandatory locks on this FS */
|
||||||
|
|
||||||
|
{ "atime", 0, MS_NOATIME }, /* update access time */
|
||||||
|
{ "noatime", MS_NOATIME, 0 }, /* do not update access time */
|
||||||
|
|
||||||
|
{ "noiversion", 0, MS_I_VERSION }, /* don't update inode I_version time */
|
||||||
|
{ "iversion", MS_I_VERSION, 0 }, /* update inode I_version time */
|
||||||
|
|
||||||
|
{ "diratime", 0, MS_NODIRATIME }, /* update dir access times */
|
||||||
|
{ "nodiratime", MS_NODIRATIME, 0 }, /* do not update dir access times */
|
||||||
|
|
||||||
|
{ "nostrictatime", 0, MS_STRICTATIME }, /* kernel default atime */
|
||||||
|
{ "strictatime", MS_STRICTATIME, 0 }, /* strict atime semantics */
|
||||||
|
|
||||||
|
/* MS_LAZYTIME added in 4.0 kernel */
|
||||||
|
#ifdef MS_LAZYTIME
|
||||||
|
{ "nolazytime", 0, MS_LAZYTIME },
|
||||||
|
{ "lazytime", MS_LAZYTIME, 0 }, /* update {a,m,c}time on the in-memory inode only */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ "acl", MS_POSIXACL, 0 },
|
||||||
|
{ "noacl", 0, MS_POSIXACL },
|
||||||
|
|
||||||
|
{ "norelatime", 0, MS_RELATIME },
|
||||||
|
{ "relatime", MS_RELATIME, 0 },
|
||||||
|
|
||||||
|
{ "dirsync", MS_DIRSYNC, 0 }, /* synchronous directory modifications */
|
||||||
|
{ "nodirsync", 0, MS_DIRSYNC },
|
||||||
|
|
||||||
|
/* MS_NOSYMFOLLOW added in 5.10 kernel */
|
||||||
|
#ifdef MS_NOSYMFOLLOW
|
||||||
|
{ "nosymfollow", MS_NOSYMFOLLOW, 0 },
|
||||||
|
{ "symfollow", 0, MS_NOSYMFOLLOW },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ "bind", MS_BIND, 0 }, /* remount part of the tree elsewhere */
|
||||||
|
{ "rbind", MS_BIND | MS_REC, 0 }, /* idem, plus mounted subtrees */
|
||||||
|
{ "unbindable", MS_UNBINDABLE, 0 }, /* unbindable */
|
||||||
|
{ "runbindable", MS_UNBINDABLE | MS_REC, 0 },
|
||||||
|
{ "private", MS_PRIVATE, 0 }, /* private */
|
||||||
|
{ "rprivate", MS_PRIVATE | MS_REC, 0 },
|
||||||
|
{ "slave", MS_SLAVE, 0 }, /* slave */
|
||||||
|
{ "rslave", MS_SLAVE | MS_REC, 0 },
|
||||||
|
{ "shared", MS_SHARED, 0 }, /* shared */
|
||||||
|
{ "rshared", MS_SHARED | MS_REC, 0 },
|
||||||
|
|
||||||
|
{ "move", MS_MOVE, 0 },
|
||||||
|
|
||||||
|
{ "remount", MS_REMOUNT, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned int mnt_opts_table_size =
|
||||||
|
sizeof(mnt_opts_table) / sizeof(struct mnt_keyword_table);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long get_mnt_opt_bit(char *key)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < mnt_opts_table_size; i++) {
|
||||||
|
if (strcmp(mnt_opts_table[i].keyword, key) == 0) {
|
||||||
|
return mnt_opts_table[i].set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "FAIL: invalid option\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(char *prog_name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s mount|umount <source> <target> [options]\n", prog_name);
|
||||||
|
fprintf(stderr, "Options are:\n");
|
||||||
|
fprintf(stderr, "-o flags sent to the mount syscall\n");
|
||||||
|
fprintf(stderr, "-d data sent to the mount syscall\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 4) {
|
char *options = NULL;
|
||||||
fprintf(stderr, "usage: %s [mount|umount] loopdev mountpoint\n",
|
char *data = NULL;
|
||||||
argv[0]);
|
int index;
|
||||||
return 1;
|
int c;
|
||||||
|
char *op, *source, *target, *token;
|
||||||
|
unsigned long flags = 0;
|
||||||
|
|
||||||
|
while ((c = getopt (argc, argv, "o:d:h")) != -1) {
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'o':
|
||||||
|
options = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
data = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(argv[1], "mount") == 0) {
|
index = optind;
|
||||||
if (mount(argv[2], argv[3], "ext2", 0xc0ed0000 | MS_NODEV, NULL ) == -1) {
|
if (argc - optind < 3) {
|
||||||
|
fprintf(stderr, "FAIL: missing positional arguments\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
op = argv[index++];
|
||||||
|
source = argv[index++];
|
||||||
|
target = argv[index++];
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
token = strtok(options, ",");
|
||||||
|
while (token) {
|
||||||
|
flags |= get_mnt_opt_bit(token);
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(op, "mount") == 0) {
|
||||||
|
if (mount(source, target, "ext2", flags, data) == -1) {
|
||||||
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
|
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
|
||||||
argv[2], argv[3],
|
source, target, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
} else if (strcmp(argv[1], "umount") == 0) {
|
} else if (strcmp(op, "umount") == 0) {
|
||||||
if (umount(argv[3]) == -1) {
|
if (umount(target) == -1) {
|
||||||
fprintf(stderr, "FAIL: umount %s failed - %s\n",
|
fprintf(stderr, "FAIL: umount %s failed - %s\n",
|
||||||
argv[3],
|
target, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -28,9 +28,11 @@ bin=$pwd
|
|||||||
|
|
||||||
mount_file=$tmpdir/mountfile
|
mount_file=$tmpdir/mountfile
|
||||||
mount_point=$tmpdir/mountpoint
|
mount_point=$tmpdir/mountpoint
|
||||||
|
mount_point2=$tmpdir/mountpoint2
|
||||||
mount_bad=$tmpdir/mountbad
|
mount_bad=$tmpdir/mountbad
|
||||||
loop_device="unset"
|
loop_device="unset"
|
||||||
fstype="ext2"
|
fstype="ext2"
|
||||||
|
root_was_shared="no"
|
||||||
|
|
||||||
setup_mnt() {
|
setup_mnt() {
|
||||||
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
|
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
|
||||||
@@ -41,6 +43,10 @@ remove_mnt() {
|
|||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
/bin/umount -t${fstype} ${mount_point}
|
/bin/umount -t${fstype} ${mount_point}
|
||||||
fi
|
fi
|
||||||
|
mountpoint -q "${mount_point2}"
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
/bin/umount -t${fstype} ${mount_point2}
|
||||||
|
fi
|
||||||
mountpoint -q "${mount_bad}"
|
mountpoint -q "${mount_bad}"
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
/bin/umount -t${fstype} ${mount_bad}
|
/bin/umount -t${fstype} ${mount_bad}
|
||||||
@@ -53,12 +59,16 @@ mount_cleanup() {
|
|||||||
then
|
then
|
||||||
/sbin/losetup -d ${loop_device} &> /dev/null
|
/sbin/losetup -d ${loop_device} &> /dev/null
|
||||||
fi
|
fi
|
||||||
|
if [ "${root_was_shared}" = "yes" ] ; then
|
||||||
|
mount --make-shared /
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
do_onexit="mount_cleanup"
|
do_onexit="mount_cleanup"
|
||||||
|
|
||||||
dd if=/dev/zero of=${mount_file} bs=1024 count=512 2> /dev/null
|
dd if=/dev/zero of=${mount_file} bs=1024 count=512 2> /dev/null
|
||||||
/sbin/mkfs -t${fstype} -F ${mount_file} > /dev/null 2> /dev/null
|
/sbin/mkfs -t${fstype} -F ${mount_file} > /dev/null 2> /dev/null
|
||||||
/bin/mkdir ${mount_point}
|
/bin/mkdir ${mount_point}
|
||||||
|
/bin/mkdir ${mount_point2}
|
||||||
/bin/mkdir ${mount_bad}
|
/bin/mkdir ${mount_bad}
|
||||||
|
|
||||||
# in a modular udev world, the devices won't exist until the loopback
|
# in a modular udev world, the devices won't exist until the loopback
|
||||||
@@ -71,6 +81,195 @@ fi
|
|||||||
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
|
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
|
||||||
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
|
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
|
||||||
|
|
||||||
|
# systemd mounts / and everything under it MS_SHARED which does
|
||||||
|
# not work with "move", so attempt to detect it, and remount /
|
||||||
|
# MS_PRIVATE temporarily. snippet from pivot_root.sh
|
||||||
|
FINDMNT=/bin/findmnt
|
||||||
|
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
||||||
|
if [ "$(${FINDMNT} -no PROPAGATION /)" == "shared" ] ; then
|
||||||
|
root_was_shared="yes"
|
||||||
|
fi
|
||||||
|
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
||||||
|
# no findmnt or findmnt doesn't know the PROPAGATION column,
|
||||||
|
# but init is systemd so assume rootfs is shared
|
||||||
|
root_was_shared="yes"
|
||||||
|
fi
|
||||||
|
if [ "${root_was_shared}" = "yes" ] ; then
|
||||||
|
mount --make-private /
|
||||||
|
fi
|
||||||
|
|
||||||
|
options=(
|
||||||
|
# default and non-default options
|
||||||
|
"rw,ro"
|
||||||
|
"exec,noexec"
|
||||||
|
"suid,nosuid"
|
||||||
|
"dev,nodev"
|
||||||
|
"async,sync"
|
||||||
|
"loud,silent"
|
||||||
|
"nomand,mand"
|
||||||
|
"atime,noatime"
|
||||||
|
"noiversion,iversion"
|
||||||
|
"diratime,nodiratime"
|
||||||
|
"nostrictatime,strictatime"
|
||||||
|
"norelatime,relatime"
|
||||||
|
"nodirsync,dirsync"
|
||||||
|
"noacl,acl"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Options added in newer kernels
|
||||||
|
new_options=(
|
||||||
|
"nolazytime,lazytime"
|
||||||
|
"symfollow,nosymfollow"
|
||||||
|
)
|
||||||
|
|
||||||
|
prop_options=(
|
||||||
|
"unbindable"
|
||||||
|
"runbindable"
|
||||||
|
"private"
|
||||||
|
"rprivate"
|
||||||
|
"slave"
|
||||||
|
"rslave"
|
||||||
|
"shared"
|
||||||
|
"rshared"
|
||||||
|
)
|
||||||
|
|
||||||
|
combinations=()
|
||||||
|
|
||||||
|
setup_all_combinations() {
|
||||||
|
n=${#options[@]}
|
||||||
|
for (( i = 1; i < (1 << n); i++ )); do
|
||||||
|
list=()
|
||||||
|
for (( j = 0; j < n; j++ )); do
|
||||||
|
if (( (1 << j) & i )); then
|
||||||
|
current_options="${options[j]}"
|
||||||
|
nondefault=${current_options#*,}
|
||||||
|
list+=("$nondefault")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
combination=$(IFS=,; printf "%s" "${list[*]}")
|
||||||
|
combinations+=($combination)
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
run_all_combinations_test() {
|
||||||
|
for combination in "${combinations[@]}"; do
|
||||||
|
if [ "$(parser_supports "mount options=($combination),")" = "true" ] ; then
|
||||||
|
genprofile cap:sys_admin "mount:options=($combination)"
|
||||||
|
runchecktest "MOUNT (confined cap mount combination pass test $combination)" pass mount ${loop_device} ${mount_point} -o $combination
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($combination)"
|
||||||
|
runchecktest "MOUNT (confined cap mount combination deny test $combination)" fail mount ${loop_device} ${mount_point} -o $combination
|
||||||
|
remove_mnt
|
||||||
|
else
|
||||||
|
echo " not supported by parser - skipping mount option=($combination),"
|
||||||
|
fi
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:options=(rw)"
|
||||||
|
runchecktest "MOUNT (confined cap mount combination fail test $combination)" fail mount ${loop_device} ${mount_point} -o $combination
|
||||||
|
remove_mnt
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
test_nonfs_options() {
|
||||||
|
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
|
||||||
|
echo " not supported by parser - skipping mount options=($1),"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount $1)" pass mount ${loop_device} ${mount_point} -o $1
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount deny $1)" fail mount ${loop_device} ${mount_point} -o $1
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount bad option $2)" fail mount ${loop_device} ${mount_point} -o $2
|
||||||
|
remove_mnt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_dir_options() {
|
||||||
|
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
|
||||||
|
echo " not supported by parser - skipping mount option=($1),"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL"
|
||||||
|
runchecktest "MOUNT (confined cap mount dir setup $1)" pass mount ${loop_device} ${mount_point}
|
||||||
|
genprofile cap:sys_admin "mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount dir $1)" pass mount ${mount_point} ${mount_point2} -o $1
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount dir setup 2 $1)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (confined cap mount dir deny $1)" fail mount ${mount_point} ${mount_point2} -o $1
|
||||||
|
remove_mnt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_propagation_options() {
|
||||||
|
if [ "$(parser_supports "mount options=($1),")" != "true" ] ; then
|
||||||
|
echo " not supported by parser - skipping mount option=($1),"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL"
|
||||||
|
runchecktest "MOUNT (confined cap mount propagation setup $1)" pass mount ${loop_device} ${mount_point}
|
||||||
|
genprofile cap:sys_admin "mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount propagation $1)" pass mount none ${mount_point} -o $1
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=($1)"
|
||||||
|
runchecktest "MOUNT (confined cap mount propagation deny setup 2 $1)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (confined cap mount propagation deny $1)" fail mount none ${mount_point} -o $1
|
||||||
|
remove_mnt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_remount() {
|
||||||
|
# setup by mounting first
|
||||||
|
genprofile cap:sys_admin "mount:ALL"
|
||||||
|
runchecktest "MOUNT (confined cap mount remount setup)" pass mount ${loop_device} ${mount_point}
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:options=(remount)"
|
||||||
|
runchecktest "MOUNT (confined cap mount remount option)" pass mount ${loop_device} ${mount_point} -o remount
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "remount:ALL"
|
||||||
|
runchecktest "MOUNT (confined cap mount remount)" pass mount ${loop_device} ${mount_point} -o remount
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "mount:ALL" "qual=deny:mount:options=(remount)"
|
||||||
|
runchecktest "MOUNT (confined cap mount remount deny option)" fail mount ${loop_device} ${mount_point} -o remount
|
||||||
|
|
||||||
|
genprofile cap:sys_admin "qual=deny:remount:ALL"
|
||||||
|
runchecktest "MOUNT (confined cap mount remount deny)" fail mount ${loop_device} ${mount_point} -o remount
|
||||||
|
|
||||||
|
# TODO: add test for remount options
|
||||||
|
remove_mnt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_options() {
|
||||||
|
for i in "${options[@]}"; do
|
||||||
|
default="${i%,*}"
|
||||||
|
nondefault="${i#*,}"
|
||||||
|
|
||||||
|
test_nonfs_options $default $nondefault
|
||||||
|
test_nonfs_options $nondefault $default
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "bind" "rbind" "move"; do
|
||||||
|
test_dir_options $i
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "${prop_options[@]}"; do
|
||||||
|
test_propagation_options $i
|
||||||
|
done
|
||||||
|
|
||||||
|
test_remount
|
||||||
|
|
||||||
|
# the following combinations tests take a long time to complete
|
||||||
|
# setup_all_combinations
|
||||||
|
# run_all_combinations_test
|
||||||
|
}
|
||||||
|
|
||||||
# TEST 1. Make sure can mount and umount unconfined
|
# TEST 1. Make sure can mount and umount unconfined
|
||||||
runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point}
|
runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point}
|
||||||
@@ -80,6 +279,43 @@ setup_mnt
|
|||||||
runchecktest "UMOUNT (unconfined)" pass umount ${loop_device} ${mount_point}
|
runchecktest "UMOUNT (unconfined)" pass umount ${loop_device} ${mount_point}
|
||||||
remove_mnt
|
remove_mnt
|
||||||
|
|
||||||
|
# Check mount options that may not be available on this kernel
|
||||||
|
for i in "${new_options[@]}"; do
|
||||||
|
default="${i%,*}"
|
||||||
|
if "$bin/mount" mount ${loop_device} ${mount_point} -o $default > /dev/null 2>&1; then
|
||||||
|
remove_mnt
|
||||||
|
options+=($i)
|
||||||
|
else
|
||||||
|
echo " not supported by kernel - skipping mount options=($i),"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "${options[@]}"; do
|
||||||
|
default="${i%,*}"
|
||||||
|
nondefault="${i#*,}"
|
||||||
|
|
||||||
|
runchecktest "MOUNT (unconfined mount $default)" pass mount ${loop_device} ${mount_point} -o $default
|
||||||
|
remove_mnt
|
||||||
|
runchecktest "MOUNT (unconfined mount $nondefault)" pass mount ${loop_device} ${mount_point} -o $nondefault
|
||||||
|
remove_mnt
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "bind" "rbind" "move"; do
|
||||||
|
runchecktest "MOUNT (unconfined mount setup $i)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (unconfined mount $i)" pass mount ${mount_point} ${mount_point2} -o $i
|
||||||
|
remove_mnt
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "${prop_options[@]}"; do
|
||||||
|
runchecktest "MOUNT (unconfined mount dir setup $i)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (unconfined mount dir $i)" pass mount none ${mount_point} -o $i
|
||||||
|
remove_mnt
|
||||||
|
done
|
||||||
|
|
||||||
|
runchecktest "MOUNT (unconfined mount remount setup)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (unconfined mount remount)" pass mount ${loop_device} ${mount_point} -o remount
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
# TEST A2. confine MOUNT no perms
|
# TEST A2. confine MOUNT no perms
|
||||||
genprofile
|
genprofile
|
||||||
runchecktest "MOUNT (confined no perm)" fail mount ${loop_device} ${mount_point}
|
runchecktest "MOUNT (confined no perm)" fail mount ${loop_device} ${mount_point}
|
||||||
@@ -91,6 +327,7 @@ remove_mnt
|
|||||||
|
|
||||||
|
|
||||||
if [ "$(kernel_features mount)" != "true" -o "$(parser_supports 'mount,')" != "true" ] ; then
|
if [ "$(kernel_features mount)" != "true" -o "$(parser_supports 'mount,')" != "true" ] ; then
|
||||||
|
echo " mount rules not supported, using capability check ..."
|
||||||
genprofile capability:sys_admin
|
genprofile capability:sys_admin
|
||||||
runchecktest "MOUNT (confined cap)" pass mount ${loop_device} ${mount_point}
|
runchecktest "MOUNT (confined cap)" pass mount ${loop_device} ${mount_point}
|
||||||
remove_mnt
|
remove_mnt
|
||||||
@@ -157,6 +394,7 @@ else
|
|||||||
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
|
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
|
||||||
remove_mnt
|
remove_mnt
|
||||||
|
|
||||||
|
test_options
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#need tests for move mount, remount, bind mount, chroot
|
#need tests for chroot
|
||||||
|
@@ -38,7 +38,7 @@ badchild=r
|
|||||||
# Add genprofile params that are common to all hats here
|
# Add genprofile params that are common to all hats here
|
||||||
common=""
|
common=""
|
||||||
|
|
||||||
if [ "$(kernel_features signal)" == "true" -a "$(parser_supports 'signal,')" == "true" ] ; then
|
if [ "$(kernel_features signal)" = "true" -a "$(parser_supports 'signal,')" = "true" ] ; then
|
||||||
# Allow send/receive of all signals
|
# Allow send/receive of all signals
|
||||||
common="${common} signal:ALL"
|
common="${common} signal:ALL"
|
||||||
fi
|
fi
|
||||||
|
@@ -44,7 +44,7 @@ do_test()
|
|||||||
shift 4
|
shift 4
|
||||||
|
|
||||||
desc="ONEXEC $desc ($prof -> $target_prof)"
|
desc="ONEXEC $desc ($prof -> $target_prof)"
|
||||||
if [ "$target_prof" == "nochange" ] ; then
|
if [ "$target_prof" = "nochange" ] ; then
|
||||||
runchecktest "$desc" $res -l "$prof" -- "$@"
|
runchecktest "$desc" $res -l "$prof" -- "$@"
|
||||||
else
|
else
|
||||||
runchecktest "$desc" $res -O "$target_prof" -l "$prof" -L "$target_prof" -- "$@"
|
runchecktest "$desc" $res -O "$target_prof" -l "$prof" -L "$target_prof" -- "$@"
|
||||||
|
@@ -50,7 +50,7 @@ do_onexit="pivot_root_cleanup"
|
|||||||
# MS_PRIVATE temporarily.
|
# MS_PRIVATE temporarily.
|
||||||
FINDMNT=/bin/findmnt
|
FINDMNT=/bin/findmnt
|
||||||
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
||||||
if [ "$(${FINDMNT} -no PROPAGATION /)" == "shared" ] ; then
|
if [ "$(${FINDMNT} -no PROPAGATION /)" = "shared" ] ; then
|
||||||
root_was_shared="yes"
|
root_was_shared="yes"
|
||||||
fi
|
fi
|
||||||
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
||||||
|
@@ -86,6 +86,19 @@ requires_kernel_features()
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requires_any_of_kernel_features()
|
||||||
|
{
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
local res=$(kernel_features "$1")
|
||||||
|
if [ "$res" = "true" ] ; then
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
echo "$res. Skipping tests ..."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
# requires_namespace_interface() - exit if namespace interface is not available
|
# requires_namespace_interface() - exit if namespace interface is not available
|
||||||
requires_namespace_interface()
|
requires_namespace_interface()
|
||||||
{
|
{
|
||||||
|
@@ -55,7 +55,7 @@ runchecktest "test 2 -h prog" pass -h -n 100 $helper ${bin_true}
|
|||||||
runchecktest "test 2 -hc prog" pass -h -c -n 100 $helper ${bin_true}
|
runchecktest "test 2 -hc prog" pass -h -c -n 100 $helper ${bin_true}
|
||||||
|
|
||||||
|
|
||||||
if [ "$(kernel_features ptrace)" == "true" -a "$(parser_supports 'ptrace,')" == "true" ] ; then
|
if [ "$(kernel_features ptrace)" = "true" -a "$(parser_supports 'ptrace,')" = "true" ] ; then
|
||||||
. $bin/ptrace_v6.inc
|
. $bin/ptrace_v6.inc
|
||||||
else
|
else
|
||||||
. $bin/ptrace_v5.inc
|
. $bin/ptrace_v5.inc
|
||||||
|
@@ -93,7 +93,7 @@ querytest()
|
|||||||
runchecktest "$desc" "$pf" "$expect" "$label" "$perms" $*
|
runchecktest "$desc" "$pf" "$expect" "$label" "$perms" $*
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$(kernel_features dbus)" == "true" ]; then
|
if [ "$(kernel_features dbus)" = "true" ]; then
|
||||||
# Check querying of a label that the kernel doesn't know about
|
# Check querying of a label that the kernel doesn't know about
|
||||||
# aa_query_label() should return an error
|
# aa_query_label() should return an error
|
||||||
expect anything
|
expect anything
|
||||||
@@ -217,7 +217,7 @@ fi
|
|||||||
genqueryprofile "file,"
|
genqueryprofile "file,"
|
||||||
expect allow
|
expect allow
|
||||||
perms file exec,write,read,append,create,delete,setattr,getattr,chmod,chown,link,linksubset,lock,exec_mmap
|
perms file exec,write,read,append,create,delete,setattr,getattr,chmod,chown,link,linksubset,lock,exec_mmap
|
||||||
if [ "$(kernel_features query/label/multi_transaction)" == "true" ] ; then
|
if [ "$(kernel_features query/label/multi_transaction)" = "true" ] ; then
|
||||||
querytest "QUERY file (all base perms #1)" pass /anything
|
querytest "QUERY file (all base perms #1)" pass /anything
|
||||||
querytest "QUERY file (all base perms #2)" pass /everything
|
querytest "QUERY file (all base perms #2)" pass /everything
|
||||||
else
|
else
|
||||||
|
@@ -37,7 +37,7 @@ af_unix_create_label=""
|
|||||||
af_unix_inherit=""
|
af_unix_inherit=""
|
||||||
aa_enabled="/sys/module/apparmor/parameters/enabled:r"
|
aa_enabled="/sys/module/apparmor/parameters/enabled:r"
|
||||||
|
|
||||||
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
|
if [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
|
||||||
# AppArmor requires that the process inheriting the sock file
|
# AppArmor requires that the process inheriting the sock file
|
||||||
# descriptors have send,receive perms in its profile
|
# descriptors have send,receive perms in its profile
|
||||||
af_unix_create="unix:(create,getopt)"
|
af_unix_create="unix:(create,getopt)"
|
||||||
|
@@ -29,7 +29,7 @@ bin=$pwd
|
|||||||
|
|
||||||
# check if we can run the test at all
|
# check if we can run the test at all
|
||||||
fstype=$(stat -f --format '%T' "${tmpdir}")
|
fstype=$(stat -f --format '%T' "${tmpdir}")
|
||||||
if [ "${fstype}" == "tmpfs" ] ; then
|
if [ "${fstype}" = "tmpfs" ] ; then
|
||||||
echo "ERROR: tmpdir '${tmpdir}' is of type tmpfs; can't mount a swapfile on it" 1>&2
|
echo "ERROR: tmpdir '${tmpdir}' is of type tmpfs; can't mount a swapfile on it" 1>&2
|
||||||
echo "ERROR: skipping swap tests" 1>&2
|
echo "ERROR: skipping swap tests" 1>&2
|
||||||
num_testfailures=1
|
num_testfailures=1
|
||||||
|
@@ -27,7 +27,9 @@ okperm=rw
|
|||||||
badperm=w
|
badperm=w
|
||||||
af_unix=""
|
af_unix=""
|
||||||
|
|
||||||
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ]; then
|
if [ "$(kernel_features network_v8)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
|
||||||
|
af_unix="unix:create"
|
||||||
|
elif [ "$(kernel_features network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ]; then
|
||||||
af_unix="unix:create"
|
af_unix="unix:create"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ runchecktest "fd passing; confined -> confined (no perm)" fail $file $socket $fd
|
|||||||
sleep 1
|
sleep 1
|
||||||
rm -f ${socket}
|
rm -f ${socket}
|
||||||
|
|
||||||
if [ "$(kernel_features policy/network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ] ; then
|
if [ "$(kernel_features policy/network/af_unix)" = "true" -a "$(parser_supports 'unix,')" = "true" ] ; then
|
||||||
# FAIL - confined client, no access to the socket file
|
# FAIL - confined client, no access to the socket file
|
||||||
|
|
||||||
genprofile $file:$okperm $af_unix $socket:rw $fd_client:px -- image=$fd_client $file:$okperm $af_unix
|
genprofile $file:$okperm $af_unix $socket:rw $fd_client:px -- image=$fd_client $file:$okperm $af_unix
|
||||||
|
@@ -29,7 +29,7 @@ bin=$pwd
|
|||||||
. $bin/prologue.inc
|
. $bin/prologue.inc
|
||||||
requires_kernel_features policy/versions/v6
|
requires_kernel_features policy/versions/v6
|
||||||
#af_mask for downgrade test af_unix for full test
|
#af_mask for downgrade test af_unix for full test
|
||||||
requires_kernel_features network/af_mask
|
requires_any_of_kernel_features network/af_mask network_v8/af_mask
|
||||||
|
|
||||||
settest unix_socket
|
settest unix_socket
|
||||||
|
|
||||||
@@ -43,9 +43,9 @@ message=4a0c83d87aaa7afa2baab5df3ee4df630f0046d5bfb7a3080c550b721f401b3b\
|
|||||||
okserver=w
|
okserver=w
|
||||||
badserver1=r
|
badserver1=r
|
||||||
badserver2=
|
badserver2=
|
||||||
if [ "$(kernel_features policy/versions/v7)" == "true" ] ; then
|
if [ "$(kernel_features policy/versions/v7)" = "true" ] ; then
|
||||||
okserver=rw
|
okserver=rw
|
||||||
badserver2=w
|
# badserver2=w
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# af_unix support requires 'unix create' to call socket()
|
# af_unix support requires 'unix create' to call socket()
|
||||||
@@ -54,9 +54,16 @@ fi
|
|||||||
# af_unix support requires 'unix getattr' to call getsockname()
|
# af_unix support requires 'unix getattr' to call getsockname()
|
||||||
af_unix_okserver=
|
af_unix_okserver=
|
||||||
af_unix_okclient=
|
af_unix_okclient=
|
||||||
if [ "$(kernel_features network/af_unix)" == "true" -a "$(parser_supports 'unix,')" == "true" ] ; then
|
if ( [ "$(kernel_features network_v8/af_unix)" = "true" ] ||
|
||||||
|
[ "$(kernel_features network/af_unix)" = "true" ] ) &&
|
||||||
|
[ "$(parser_supports 'unix,')" = "true" ] ; then
|
||||||
af_unix_okserver="create,setopt"
|
af_unix_okserver="create,setopt"
|
||||||
af_unix_okclient="create,getopt,setopt,getattr"
|
af_unix_okclient="create,getopt,setopt,getattr"
|
||||||
|
elif [ "$(kernel_features network_v8)" = "true" ] ; then
|
||||||
|
# af_unix_okserver="create,setopt"
|
||||||
|
# af_unix_okclient="create,getopt,setopt,getattr"
|
||||||
|
af_unix_okserver="create"
|
||||||
|
af_unix_okclient="create"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
okclient=rw
|
okclient=rw
|
||||||
@@ -88,7 +95,7 @@ testsocktype()
|
|||||||
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1373176
|
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1373176
|
||||||
# get resolved
|
# get resolved
|
||||||
local ex_result="pass"
|
local ex_result="pass"
|
||||||
if [ "${socktype}" == "dgram" ] ; then
|
if [ "${socktype}" = "dgram" ] ; then
|
||||||
ex_result="xpass"
|
ex_result="xpass"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -72,20 +72,14 @@ if args.json:
|
|||||||
aaui.set_json_mode()
|
aaui.set_json_mode()
|
||||||
|
|
||||||
profiling = args.program
|
profiling = args.program
|
||||||
profiledir = args.dir
|
|
||||||
|
|
||||||
apparmor.init_aa()
|
apparmor.init_aa(profiledir=args.dir)
|
||||||
apparmor.set_logfile(args.file)
|
apparmor.set_logfile(args.file)
|
||||||
|
|
||||||
aa_mountpoint = apparmor.check_for_apparmor()
|
aa_mountpoint = apparmor.check_for_apparmor()
|
||||||
if not aa_mountpoint:
|
if not aa_mountpoint:
|
||||||
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
|
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
|
||||||
|
|
||||||
if profiledir:
|
|
||||||
apparmor.profile_dir = apparmor.get_full_path(profiledir)
|
|
||||||
if not os.path.isdir(apparmor.profile_dir):
|
|
||||||
raise apparmor.AppArmorException(_("%s is not a directory.") %profiledir)
|
|
||||||
|
|
||||||
program = None
|
program = None
|
||||||
#if os.path.exists(apparmor.which(profiling.strip())):
|
#if os.path.exists(apparmor.which(profiling.strip())):
|
||||||
if os.path.exists(profiling):
|
if os.path.exists(profiling):
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user