mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 23:05:11 +00:00
Compare commits
145 Commits
fix-priori
...
v4.1.0-bet
Author | SHA1 | Date | |
---|---|---|---|
|
8d9a061a45 | ||
|
94ea0f00b1 | ||
|
99e919c288 | ||
|
d805b5c3f8 | ||
|
2aa7fe4659 | ||
|
c456101ebb | ||
|
9875ba19ef | ||
|
ab15e29654 | ||
|
320a2a5155 | ||
|
00dc6794f5 | ||
|
958a77a2db | ||
|
b4aa2cfde4 | ||
|
86273b746a | ||
|
6a26d1f58c | ||
|
17d3545d07 | ||
|
640c3dde26 | ||
|
380a5c8a72 | ||
|
f26f577742 | ||
|
2700e58755 | ||
|
427a895288 | ||
|
dc0a9dc599 | ||
|
74219b34dc | ||
|
5aaa45e4ce | ||
|
0c02c8afe1 | ||
|
70ed8d6f38 | ||
|
5751614928 | ||
|
73842b54f7 | ||
|
54f1cf8dca | ||
|
2de3b84de2 | ||
|
9fc848be81 | ||
|
fefbf514f7 | ||
|
ae0c588acb | ||
|
0af8c5e26f | ||
|
f4deae6759 | ||
|
0691cfcf3c | ||
|
760ddaeb80 | ||
|
4e46df38cf | ||
|
e9858c0c43 | ||
|
0e59b99623 | ||
|
9a2f0ff702 | ||
|
c153a6916f | ||
|
2316ad42d4 | ||
|
e46ca918a2 | ||
|
610d383de2 | ||
|
5ae6f202f8 | ||
|
d96d69a60c | ||
|
164526d16a | ||
|
5267a7eb14 | ||
|
fd24c230c9 | ||
|
14933dc768 | ||
|
9bf91bbe40 | ||
|
8597b04aac | ||
|
28537ff8ec | ||
|
f90a041921 | ||
|
ae0d1aafda | ||
|
403b3cad10 | ||
|
851f6013f6 | ||
|
0838496c32 | ||
|
191f01b749 | ||
|
788d29aacb | ||
|
1b70d1e9c2 | ||
|
00a5c07db5 | ||
|
6876448a24 | ||
|
297cd44aff | ||
|
32da740f1b | ||
|
b24f0bbfa8 | ||
|
5a4ddbeaeb | ||
|
fd253d1c31 | ||
|
505faeff10 | ||
|
3d5346b48e | ||
|
1d9e28df35 | ||
|
9995e36347 | ||
|
08aeeedc69 | ||
|
d426129baf | ||
|
cda7af8561 | ||
|
f5844dc267 | ||
|
52b83aeac4 | ||
|
89fd37abbf | ||
|
ffff25e21b | ||
|
0e7e509ba8 | ||
|
4722ff8e65 | ||
|
d88c6d3bca | ||
|
37ea52db0c | ||
|
da9c59ab09 | ||
|
8fde25d828 | ||
|
5aa7d046db | ||
|
9c3ac976ec | ||
|
f433acb219 | ||
|
5ee3c03101 | ||
|
6fdc08a5a5 | ||
|
e931449ffc | ||
|
203b4994e9 | ||
|
7b53763f92 | ||
|
ddb33d348c | ||
|
8274bff547 | ||
|
b17750163b | ||
|
9c229d1452 | ||
|
702f2863a4 | ||
|
989bf0b3ed | ||
|
9b1d0ea3d8 | ||
|
a577d92c7b | ||
|
a16aff8e20 | ||
|
4099bf6574 | ||
|
a102e9dc55 | ||
|
7c1eff3867 | ||
|
d69d4d3ddf | ||
|
5c04b791d2 | ||
|
be8d85603e | ||
|
450813869a | ||
|
65c41b7fac | ||
|
d19e5e8990 | ||
|
c11ad3e675 | ||
|
de2bb16ad6 | ||
|
4f1d2ac549 | ||
|
cc9f0ed538 | ||
|
1b8afda407 | ||
|
9aae96356e | ||
|
b5db2361f3 | ||
|
5db4a1e7ca | ||
|
230a975916 | ||
|
aa3592a57e | ||
|
a9aef6f37b | ||
|
c71c486313 | ||
|
4213dcc586 | ||
|
ff7f0ff0ea | ||
|
9da0f6d3db | ||
|
0c1c186267 | ||
|
bfd2a0e014 | ||
|
c87fb0a8c1 | ||
|
05debdb2d8 | ||
|
8b06f61bea | ||
|
34a706f566 | ||
|
a31cbd07aa | ||
|
c4c020cdc0 | ||
|
3c00ed7c85 | ||
|
bf8fd8cfac | ||
|
2ca7d30590 | ||
|
5a39ae82fe | ||
|
c7ce54bcbf | ||
|
2318ba598c | ||
|
3d403fe2a7 | ||
|
9074b20a95 | ||
|
7949339b93 | ||
|
80b6e4ddff | ||
|
d824adcf93 |
25
.gitignore
vendored
25
.gitignore
vendored
@@ -11,6 +11,17 @@ binutils/aa-status
|
||||
binutils/aa-status.8
|
||||
binutils/cJSON.o
|
||||
binutils/po/*.mo
|
||||
changehat/mod_apparmor/.libs
|
||||
changehat/mod_apparmor/mod_apparmor.8
|
||||
changehat/mod_apparmor/mod_apparmor.8.html
|
||||
changehat/mod_apparmor/mod_apparmor.la
|
||||
changehat/mod_apparmor/mod_apparmor.lo
|
||||
changehat/mod_apparmor/mod_apparmor.slo
|
||||
changehat/mod_apparmor/mod_apparmor.so
|
||||
changehat/mod_apparmor/pod2htmd.tmp
|
||||
changehat/pam_apparmor/get_options.o
|
||||
changehat/pam_apparmor/pam_apparmor.o
|
||||
changehat/pam_apparmor/pam_apparmor.so
|
||||
parser/po/*.mo
|
||||
parser/af_names.h
|
||||
parser/cap_names.h
|
||||
@@ -169,7 +180,6 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||
libraries/libapparmor/testsuite/test_multi/out
|
||||
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
||||
changehat/mod_apparmor/.libs
|
||||
utils/*.8
|
||||
utils/*.8.html
|
||||
utils/*.5
|
||||
@@ -209,6 +219,7 @@ tests/regression/apparmor/chgrp
|
||||
tests/regression/apparmor/chmod
|
||||
tests/regression/apparmor/chown
|
||||
tests/regression/apparmor/clone
|
||||
tests/regression/apparmor/complain
|
||||
tests/regression/apparmor/dbus_eavesdrop
|
||||
tests/regression/apparmor/dbus_message
|
||||
tests/regression/apparmor/dbus_service
|
||||
@@ -284,3 +295,15 @@ tests/regression/apparmor/xattrs_profile
|
||||
tests/regression/apparmor/coredump
|
||||
**/__pycache__/
|
||||
*.orig
|
||||
|
||||
# Patterns related to spread integration tests
|
||||
*.img
|
||||
*.iso
|
||||
*.lock
|
||||
*.log
|
||||
*.qcow2
|
||||
*.run
|
||||
.spread-reuse.yaml
|
||||
.spread-reuse.*.yaml
|
||||
spread-artifacts/
|
||||
spread-logs/
|
||||
|
68
.image-garden.mk
Normal file
68
.image-garden.mk
Normal file
@@ -0,0 +1,68 @@
|
||||
# This file is read by image-garden when spread is allocating test machines.
|
||||
# All the package installation happens through cloud-init profiles defined
|
||||
# below.
|
||||
|
||||
# This is the cloud-init user-data profile for all Debian systems. Note that it
|
||||
# is an extension of the default profile necessary for operation of
|
||||
# image-garden.
|
||||
define DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE
|
||||
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||
packages:
|
||||
- attr
|
||||
- autoconf
|
||||
- autoconf-archive
|
||||
- automake
|
||||
- bison
|
||||
- build-essential
|
||||
- dejagnu
|
||||
- flake8
|
||||
- flex
|
||||
- gettext
|
||||
- libdbus-1-dev
|
||||
- libtool
|
||||
- liburing-dev
|
||||
- pkg-config
|
||||
- python3-all-dev
|
||||
- python3-gi
|
||||
- python3-notify2
|
||||
- python3-psutil
|
||||
- python3-setuptools
|
||||
- python3-tk
|
||||
- python3-ttkthemes
|
||||
- swig
|
||||
endef
|
||||
|
||||
# Ubuntu shares cloud-init profile with Debian.
|
||||
UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE=$(DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||
|
||||
# This is the cloud-init user-data profile for openSUSE Tumbleweed.
|
||||
define OPENSUSE_tumbleweed_CLOUD_INIT_USER_DATA_TEMPLATE
|
||||
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||
packages:
|
||||
- attr
|
||||
- autoconf
|
||||
- autoconf-archive
|
||||
- automake
|
||||
- bison
|
||||
- dbus-1-devel
|
||||
- dejagnu
|
||||
- flex
|
||||
- gcc
|
||||
- gcc-c++
|
||||
- gettext
|
||||
- gobject-introspection
|
||||
- libtool
|
||||
- liburing2-devel
|
||||
- make
|
||||
- pkg-config
|
||||
- python3-flake8
|
||||
- python3-notify2
|
||||
- python3-psutil
|
||||
- python3-setuptools
|
||||
- python3-setuptools
|
||||
- python3-tk
|
||||
- python311
|
||||
- python3-devel
|
||||
- python311-devel
|
||||
- swig
|
||||
endef
|
27
README.md
27
README.md
@@ -197,6 +197,33 @@ usage and how to update and add tests. Below is a quick overview of their
|
||||
location and how to run them.
|
||||
|
||||
|
||||
Using spread with local virtual machines
|
||||
----------------------------------------
|
||||
|
||||
It may be convenient to use the spread tool to provision and run the test suite
|
||||
in an ephemeral virtual machine. This allows testing in isolation from the
|
||||
host, as well as testing across different commonly used distributions and their
|
||||
real kernels.
|
||||
|
||||
```sh
|
||||
sudo apt install git golang whois ovmf genisoimage qemu-utils qemu-system
|
||||
go install github.com/snapcore/spread/cmd/spread@latest
|
||||
git clone https://gitlab.com/zygoon/image-garden
|
||||
make -C image-garden
|
||||
sudo make -C image-garden install
|
||||
image-garden make ubuntu-cloud-24.10.x86_64.run
|
||||
cd $APPARMOR_PATH
|
||||
git clean -xdf
|
||||
~/go/bin/spread -artifacts ./spread-artifacts -v ubuntu-cloud-24.10
|
||||
# or ~/go/bin/spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
|
||||
```
|
||||
|
||||
Running the `run_spread.sh` script, with `spread` on `PATH` will run all the
|
||||
tests across several supported systems (Debian, Ubuntu and openSUSE).
|
||||
|
||||
If you include a `bzImage` file in the root of the repository then that kernel
|
||||
will be used in the integration test. Please look at `spread.yaml` for details.
|
||||
|
||||
Regression tests
|
||||
----------------
|
||||
For details on structure and adding tests, see
|
||||
|
@@ -488,7 +488,7 @@ static int filter_processes(struct process *processes,
|
||||
*
|
||||
* Return: 0 on success, else shell error code
|
||||
*/
|
||||
static int simple_filtered_count(FILE *outf, filters_t *filters,
|
||||
static int simple_filtered_count(FILE *outf, filters_t *filters, bool json,
|
||||
struct profile *profiles, size_t nprofiles)
|
||||
{
|
||||
struct profile *filtered = NULL;
|
||||
@@ -497,7 +497,13 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
|
||||
|
||||
ret = filter_profiles(profiles, nprofiles, filters,
|
||||
&filtered, &nfiltered);
|
||||
fprintf(outf, "%zd\n", nfiltered);
|
||||
|
||||
if (!json) {
|
||||
fprintf(outf, "%zd\n", nfiltered);
|
||||
} else {
|
||||
fprintf(outf, "\"profile_count\": %zd", nfiltered);
|
||||
}
|
||||
|
||||
free_profiles(filtered, nfiltered);
|
||||
|
||||
return ret;
|
||||
@@ -512,7 +518,7 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
|
||||
*
|
||||
* Return: 0 on success, else shell error code
|
||||
*/
|
||||
static int simple_filtered_process_count(FILE *outf, filters_t *filters,
|
||||
static int simple_filtered_process_count(FILE *outf, filters_t *filters, bool json,
|
||||
struct process *processes, size_t nprocesses) {
|
||||
struct process *filtered = NULL;
|
||||
size_t nfiltered;
|
||||
@@ -520,7 +526,12 @@ static int simple_filtered_process_count(FILE *outf, filters_t *filters,
|
||||
|
||||
ret = filter_processes(processes, nprocesses, filters, &filtered,
|
||||
&nfiltered);
|
||||
fprintf(outf, "%zd\n", nfiltered);
|
||||
if (!json) {
|
||||
fprintf(outf, "%zd\n", nfiltered);
|
||||
} else {
|
||||
fprintf(outf, "\"process_count\": %zd", nfiltered);
|
||||
}
|
||||
|
||||
free_processes(filtered, nfiltered);
|
||||
|
||||
return ret;
|
||||
@@ -539,7 +550,12 @@ static int compare_processes_by_executable(const void *a, const void *b) {
|
||||
|
||||
static void json_header(FILE *outf)
|
||||
{
|
||||
fprintf(outf, "{\"version\": \"%s\", ", aa_status_json_version);
|
||||
fprintf(outf, "{\"version\": \"%s\"", aa_status_json_version);
|
||||
}
|
||||
|
||||
static void json_seperator(FILE *outf)
|
||||
{
|
||||
fprintf(outf, ", ");
|
||||
}
|
||||
|
||||
static void json_footer(FILE *outf)
|
||||
@@ -607,7 +623,7 @@ static int detailed_profiles(FILE *outf, filters_t *filters, bool json,
|
||||
free_profiles(filtered, nfiltered);
|
||||
}
|
||||
if (json)
|
||||
fprintf(outf, "}, ");
|
||||
fprintf(outf, "}");
|
||||
|
||||
return AA_EXIT_ENABLED;
|
||||
}
|
||||
@@ -700,7 +716,7 @@ static int detailed_processes(FILE *outf, filters_t *filters, bool json,
|
||||
fprintf(outf, "]");
|
||||
}
|
||||
|
||||
fprintf(outf, "}\n");
|
||||
fprintf(outf, "}");
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -1028,8 +1044,10 @@ int main(int argc, char **argv)
|
||||
if (opt_json)
|
||||
json_header(outf);
|
||||
if (opt_show & SHOW_PROFILES) {
|
||||
if (opt_json)
|
||||
json_seperator(outf);
|
||||
if (opt_count) {
|
||||
ret = simple_filtered_count(outf, &filters,
|
||||
ret = simple_filtered_count(outf, &filters, opt_json,
|
||||
profiles, nprofiles);
|
||||
} else {
|
||||
ret = detailed_profiles(outf, &filters, opt_json,
|
||||
@@ -1040,6 +1058,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (opt_show & SHOW_PROCESSES) {
|
||||
if (opt_json)
|
||||
json_seperator(outf);
|
||||
|
||||
struct process *processes = NULL;
|
||||
size_t nprocesses = 0;
|
||||
|
||||
@@ -1047,7 +1068,7 @@ int main(int argc, char **argv)
|
||||
if (ret != 0) {
|
||||
eprintf("Failed to get processes: %d....\n", ret);
|
||||
} else if (opt_count) {
|
||||
ret = simple_filtered_process_count(outf, &filters,
|
||||
ret = simple_filtered_process_count(outf, &filters, opt_json,
|
||||
processes, nprocesses);
|
||||
} else {
|
||||
ret = detailed_processes(outf, &filters, opt_json,
|
||||
|
@@ -35,10 +35,7 @@ VERSION=$(shell cat $(COMMONDIR)/Version)
|
||||
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
||||
map = $(foreach a,$(2),$(call $(1),$(a)))
|
||||
|
||||
AWK:=$(shell which awk)
|
||||
ifndef AWK
|
||||
$(error awk utility required for build but not available)
|
||||
endif
|
||||
AWK?=$(or $(shell command -v awk),$(error awk utility required for build but not available))
|
||||
|
||||
define nl
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
4.1.0~beta1
|
||||
4.1.0~beta3
|
||||
|
@@ -149,8 +149,6 @@ typedef struct
|
||||
char *net_foreign_addr;
|
||||
unsigned long net_foreign_port;
|
||||
|
||||
char *execpath;
|
||||
|
||||
char *dbus_bus;
|
||||
char *dbus_path;
|
||||
char *dbus_interface;
|
||||
@@ -167,6 +165,7 @@ typedef struct
|
||||
|
||||
char *net_addr;
|
||||
char *peer_addr;
|
||||
char *execpath;
|
||||
} aa_log_record;
|
||||
|
||||
/**
|
||||
|
@@ -52,7 +52,7 @@ scanner.h: scanner.l
|
||||
scanner.c: scanner.l
|
||||
|
||||
af_protos.h:
|
||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dM - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dD - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||
|
||||
lib_LTLIBRARIES = libapparmor.la
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||
|
@@ -7,7 +7,7 @@ import sysconfig
|
||||
import setuptools
|
||||
|
||||
|
||||
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
||||
if tuple(map(int, setuptools.__version__.split(".")[:2])) >= (62, 1):
|
||||
identifier = sys.implementation.cache_tag
|
||||
else:
|
||||
identifier = "%d.%d" % sys.version_info[:2]
|
||||
|
@@ -0,0 +1 @@
|
||||
[ 310.308737] audit: type=1400 audit(1724847289.985:631): apparmor="ALLOWED" operation="getsockname" class="net" profile="/usr/bin/wg" pid=15374 comm="wg" laddr=::ffff:127.0.0.1 lport=53131 faddr=::ffff:127.0.0.1 fport=51821 saddr=::ffff:127.0.0.1 src=53131 family="inet6" sock_type="dgram" protocol=17 requested="getattr" denied="getattr"
|
@@ -0,0 +1,20 @@
|
||||
START
|
||||
File: testcase_network_12.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1724847289.985:631
|
||||
Operation: getsockname
|
||||
Mask: getattr
|
||||
Denied Mask: getattr
|
||||
Profile: /usr/bin/wg
|
||||
Command: wg
|
||||
PID: 15374
|
||||
Network family: inet6
|
||||
Socket type: dgram
|
||||
Protocol: udp
|
||||
Local addr: ::ffff:127.0.0.1
|
||||
Foreign addr: ::ffff:127.0.0.1
|
||||
Local port: 53131
|
||||
Foreign port: 51821
|
||||
Class: net
|
||||
Epoch: 1724847289
|
||||
Audit subid: 631
|
@@ -0,0 +1,4 @@
|
||||
/usr/bin/wg {
|
||||
network (getattr) inet6 dgram ip=::ffff:127.0.0.1 port=53131,
|
||||
|
||||
}
|
@@ -38,7 +38,7 @@ MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 aa-teardown.8 apparmor_xattrs
|
||||
# parse.error=verbose supported from 3.0 so just test on that
|
||||
# TODO move to autoconf
|
||||
BISON_MAJOR:=$(shell bison --version | awk '/^bison/ { print ($$NF) }' | awk -F. '{print $$1 }')
|
||||
USE_PARSE_ERROR:=$(shell test ${BISON_MAJOR} -ge 3 && echo true)
|
||||
USE_PARSE_ERROR:=$(shell test "${BISON_MAJOR}" -ge 3 && echo true)
|
||||
|
||||
YACC := bison
|
||||
YFLAGS := -d
|
||||
|
@@ -175,7 +175,7 @@ B<NETWORK PEER EXPR> = 'peer' '=' '(' ( I<NETWORK IP COND> | I<NETWORK PORT COND
|
||||
|
||||
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
|
||||
|
||||
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> )
|
||||
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> | I<NETWORK PORT> '-' I<NETWORK PORT> )
|
||||
|
||||
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
|
||||
|
||||
@@ -996,13 +996,14 @@ can be represented by:
|
||||
network ip=0.0.0.0; #allow INADDR_ANY
|
||||
|
||||
The network rules support the specification of local and remote IP
|
||||
addresses and ports.
|
||||
addresses, ports, and port ranges.
|
||||
|
||||
network ip=127.0.0.1 port=8080,
|
||||
network peer=(ip=10.139.15.23 port=8081),
|
||||
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
|
||||
network port=8080 peer=(port=8081),
|
||||
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
|
||||
network ip=127.0.0.1 port=8080-8084,
|
||||
|
||||
=head2 Mount Rules
|
||||
|
||||
|
@@ -43,7 +43,11 @@ optflag_table_t dumpflag_table[] = {
|
||||
{ 1, "dfa-progress", "Dump dfa creation as in progress",
|
||||
DUMP_DFA_PROGRESS | DUMP_DFA_STATS },
|
||||
{ 1, "dfa-stats", "Dump dfa creation stats", DUMP_DFA_STATS },
|
||||
{ 1, "dfa-states", "Dump dfa state diagram", DUMP_DFA_STATES },
|
||||
{ 1, "dfa-states", "Dump final dfa state information", DUMP_DFA_STATES },
|
||||
{ 1, "dfa-states-initial", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_INIT },
|
||||
{ 1, "dfa-states-post-filter", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_FILTER },
|
||||
{ 1, "dfa-states-post-minimize", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_POST_MINIMIZE },
|
||||
{ 1, "dfa-states-post-unreachable", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_UNREACHABLE },
|
||||
{ 1, "dfa-graph", "Dump dfa dot (graphviz) graph", DUMP_DFA_GRAPH },
|
||||
{ 1, "dfa-minimize", "Dump dfa minimization", DUMP_DFA_MINIMIZE },
|
||||
{ 1, "dfa-unreachable", "Dump dfa unreachable states",
|
||||
|
@@ -175,6 +175,28 @@ static inline int is_merged_x_consistent(int a, int b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Arbitrary max and minimum priority that userspace can specify,
|
||||
* internally we handle up to MAX_INTERNAL_PRIORITY and
|
||||
* MIN_INTERNAL_PRIORITY. Do not ever allow INT_MAX, or INT_MIN
|
||||
* because cmp uses subtraction and it can cause overflow. Ensure we
|
||||
* don't over/underflow make internal max/min one more than allowed on
|
||||
* rules.
|
||||
*
|
||||
* see
|
||||
* note on mediates_priority
|
||||
*/
|
||||
#define MIN_POLICY_PRIORITY (-1000)
|
||||
#define MAX_POLICY_PRIORITY (1000)
|
||||
|
||||
/* internally we need a priority that any policy based rule can override
|
||||
* and a priority that no policy based rule can override. These are
|
||||
* used on rules encoding what abi/classes are supported by the
|
||||
* compiled policy.
|
||||
*/
|
||||
#define MIN_INTERNAL_PRIORITY (MIN_POLICY_PRIORITY - 1)
|
||||
#define MAX_INTERNAL_PRIORITY (MAX_POLICY_PRIORITY + 1)
|
||||
|
||||
|
||||
#endif /* ! _IMMUNIX_H */
|
||||
|
||||
/* LocalWords: MMAP
|
||||
|
@@ -127,6 +127,13 @@ int io_uring_rule::gen_policy_re(Profile &prof)
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
/* add a mediates_io_uring rule for every rule added. It
|
||||
* needs to be the same priority
|
||||
*/
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
RULE_ALLOW, AA_MAY_READ, 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
|
||||
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
||||
buf = buffer.str(); /* update buf to have label */
|
||||
|
@@ -14,6 +14,14 @@ AR ?= ar
|
||||
CFLAGS ?= -g -Wall -O2 ${EXTRA_CFLAGS} -std=gnu++0x
|
||||
CXXFLAGS := ${CFLAGS} ${INCLUDE_APPARMOR}
|
||||
|
||||
LIB_HDRS = aare_rules.h flex-tables.h apparmor_re.h hfa.h chfa.h parse.h \
|
||||
expr-tree.h policy_compat.h
|
||||
|
||||
OTHER_HDRS = ../common_optarg.h ../common_flags.h ../immunix.h \
|
||||
../policydb.h ../perms.h ../rule.h
|
||||
|
||||
HDRS = ${LIB_HDRS} ${OTHER_HDRS}
|
||||
|
||||
ARFLAGS=-rcs
|
||||
|
||||
BISON := bison
|
||||
@@ -27,17 +35,17 @@ libapparmor_re.a: parse.o expr-tree.o hfa.o chfa.o aare_rules.o policy_compat.o
|
||||
|
||||
expr-tree.o: expr-tree.cc expr-tree.h
|
||||
|
||||
hfa.o: hfa.cc apparmor_re.h hfa.h ../immunix.h policy_compat.h
|
||||
hfa.o: hfa.cc ${HDRS}
|
||||
|
||||
aare_rules.o: aare_rules.cc aare_rules.h apparmor_re.h expr-tree.h hfa.h chfa.h parse.h ../immunix.h
|
||||
aare_rules.o: aare_rules.cc ${HDRS}
|
||||
|
||||
chfa.o: chfa.cc chfa.h ../immunix.h
|
||||
chfa.o: chfa.cc ${HDRS}
|
||||
|
||||
policy_compat.o: policy_compat.cc policy_compat.h ../perms.h ../immunix.h
|
||||
policy_compat.o: policy_compat.cc ${HDRS}
|
||||
|
||||
parse.o : parse.cc apparmor_re.h expr-tree.h
|
||||
parse.o : parse.cc ${HDRS}
|
||||
|
||||
parse.cc : parse.y parse.h flex-tables.h ../immunix.h
|
||||
parse.cc : parse.y ${HDRS}
|
||||
${BISON} -o $@ $<
|
||||
|
||||
clean:
|
||||
|
@@ -258,6 +258,9 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
||||
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
||||
dfa.dump_uniq_perms("dfa");
|
||||
|
||||
if (opts.dump & DUMP_DFA_STATES_INIT)
|
||||
dfa.dump(cerr);
|
||||
|
||||
/* since we are building a chfa, use the info about
|
||||
* whether the chfa supports extended perms to help
|
||||
* determine whether we clear the deny info.
|
||||
@@ -265,23 +268,24 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
||||
* information supported by the backed
|
||||
*/
|
||||
if (!extended_perms ||
|
||||
// TODO: we should drop DFA_MINIMIZE check here but doing
|
||||
// so changes behavior. Do as a separate patch and fixup
|
||||
// tests, etc.
|
||||
((opts.control & CONTROL_DFA_FILTER_DENY) &&
|
||||
(opts.control & CONTROL_DFA_MINIMIZE)))
|
||||
((opts.control & CONTROL_DFA_FILTER_DENY))) {
|
||||
dfa.apply_and_clear_deny();
|
||||
|
||||
if (opts.dump & DUMP_DFA_STATES_POST_FILTER)
|
||||
dfa.dump(cerr);
|
||||
}
|
||||
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
||||
dfa.minimize(opts);
|
||||
|
||||
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
|
||||
dfa.dump_uniq_perms("minimized dfa");
|
||||
if (opts.dump & DUMP_DFA_STATES_POST_MINIMIZE)
|
||||
dfa.dump(cerr);
|
||||
}
|
||||
|
||||
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
|
||||
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE) {
|
||||
dfa.remove_unreachable(opts);
|
||||
|
||||
if (opts.dump & DUMP_DFA_STATES_POST_UNREACHABLE)
|
||||
dfa.dump(cerr);
|
||||
}
|
||||
if (opts.dump & DUMP_DFA_STATES)
|
||||
dfa.dump(cerr);
|
||||
|
||||
@@ -310,7 +314,19 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
||||
//cerr << "Checking extended perms " << extended_perms << "\n";
|
||||
if (extended_perms) {
|
||||
//cerr << "creating permstable\n";
|
||||
dfa.compute_perms_table(perms_table, prompt);
|
||||
dfa.compute_perms_table(perms_table, prompt);
|
||||
// TODO: move perms table to a class
|
||||
if (opts.dump & DUMP_DFA_TRANS_TABLE && perms_table.size()) {
|
||||
cerr << "Perms Table size: " << perms_table.size() << "\n";
|
||||
perms_table[0].dump_header(cerr);
|
||||
for (size_t i = 0; i < perms_table.size(); i++) {
|
||||
perms_table[i].dump(cerr);
|
||||
cerr << "accept1: 0x";
|
||||
cerr << ", accept2: 0x";
|
||||
cerr << "\n";
|
||||
}
|
||||
cerr << "\n";
|
||||
}
|
||||
}
|
||||
chfa = new CHFA(dfa, eq, opts, extended_perms, prompt);
|
||||
if (opts.dump & DUMP_DFA_TRANS_TABLE)
|
||||
|
@@ -90,8 +90,10 @@ public:
|
||||
else
|
||||
node = new MatchFlag(priority, perms, audit);
|
||||
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
||||
if (val.second == false)
|
||||
if (val.second == false) {
|
||||
delete node;
|
||||
return val.first->second;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
return res->second;
|
||||
|
@@ -60,5 +60,9 @@
|
||||
#define DUMP_RULE_MERGE (1 << 22)
|
||||
#define DUMP_DFA_STATE32 (1 << 23)
|
||||
#define DUMP_DFA_FLAGS_TABLE (1 << 24)
|
||||
#define DUMP_DFA_STATES_INIT (1 << 25)
|
||||
#define DUMP_DFA_STATES_POST_FILTER (1 << 26)
|
||||
#define DUMP_DFA_STATES_POST_MINIMIZE (1 << 27)
|
||||
#define DUMP_DFA_STATES_POST_UNREACHABLE (1 << 28)
|
||||
|
||||
#endif /* APPARMOR_RE_H */
|
||||
|
@@ -307,11 +307,16 @@ void CHFA::dump(ostream &os)
|
||||
st.insert(make_pair(i->second, i->first));
|
||||
}
|
||||
|
||||
os << "size=" << default_base.size() << " (accept, default, base): {state} -> {default state}" << "\n";
|
||||
os << "size=" << default_base.size() << " (accept, accept2, default, base): {state} -> {default state}" << "\n";
|
||||
for (size_t i = 0; i < default_base.size(); i++) {
|
||||
os << i << ": ";
|
||||
os << "(" << accept[i] << ", " << num[default_base[i].first]
|
||||
<< ", " << default_base[i].second << ")";
|
||||
os << "(" << accept[i] << ", ";
|
||||
if (accept2.size() > 0)
|
||||
os << accept2[i];
|
||||
else
|
||||
os << "---, ";
|
||||
os << num[default_base[i].first] << ", " <<
|
||||
default_base[i].second << ")";
|
||||
if (st[i])
|
||||
os << " " << *st[i];
|
||||
if (default_base[i].first)
|
||||
|
@@ -890,7 +890,7 @@ public:
|
||||
{
|
||||
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||
}
|
||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << '>'; }
|
||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << std::dec << '>'; }
|
||||
|
||||
int priority;
|
||||
perm32_t perms;
|
||||
|
@@ -1334,8 +1334,7 @@ void DFA::compute_perms_table(vector <aa_perms> &perms_table, bool prompt)
|
||||
perms_table.resize(states.size() * mult);
|
||||
|
||||
// nonmatching and start need to be 0 and 1 so handle outside of loop
|
||||
if (filedfa)
|
||||
compute_perms_table_ent(nonmatching, 0, perms_table, prompt);
|
||||
compute_perms_table_ent(nonmatching, 0, perms_table, prompt);
|
||||
compute_perms_table_ent(start, 1, perms_table, prompt);
|
||||
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
|
@@ -52,7 +52,7 @@ ostream &operator<<(ostream &os, State &state);
|
||||
|
||||
class perms_t {
|
||||
public:
|
||||
perms_t(void): priority(INT_MIN), allow(0), deny(0), prompt(0), audit(0), quiet(0), exact(0) { };
|
||||
perms_t(void): priority(MIN_INTERNAL_PRIORITY), allow(0), deny(0), prompt(0), audit(0), quiet(0), exact(0) { };
|
||||
|
||||
bool is_accept(void) { return (allow | deny | prompt | audit | quiet); }
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
}
|
||||
|
||||
void clear(void) {
|
||||
priority = INT_MIN;
|
||||
priority = MIN_INTERNAL_PRIORITY;
|
||||
allow = deny = prompt = audit = quiet = exact = 0;
|
||||
}
|
||||
void clear(int p) {
|
||||
@@ -131,12 +131,23 @@ public:
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* returns true if perm is no longer accept */
|
||||
int apply_and_clear_deny(void)
|
||||
{
|
||||
if (deny) {
|
||||
allow &= ~deny;
|
||||
exact &= ~deny;
|
||||
prompt &= ~deny;
|
||||
quiet &= deny;
|
||||
/* don't change audit or quiet based on clearing
|
||||
* deny at this stage. This was made unique in
|
||||
* accept_perms, and the info about whether
|
||||
* we are auditing or quieting based on the explicit
|
||||
* deny has been discarded and can only be inferred.
|
||||
* But we know it is correct from accept_perms()
|
||||
* audit &= deny;
|
||||
* quiet &= deny;
|
||||
*/
|
||||
deny = 0;
|
||||
return !is_accept();
|
||||
}
|
||||
@@ -282,9 +293,9 @@ public:
|
||||
{
|
||||
accept1 = perms.allow;
|
||||
if (prompt && prompt_compat_mode == PROMPT_COMPAT_DEV)
|
||||
accept2 = PACK_AUDIT_CTL(perms.prompt, perms.quiet & perms.deny);
|
||||
accept2 = PACK_AUDIT_CTL(perms.prompt, perms.quiet);
|
||||
else
|
||||
accept2 = PACK_AUDIT_CTL(perms.audit, perms.quiet & perms.deny);
|
||||
accept2 = PACK_AUDIT_CTL(perms.audit, perms.quiet);
|
||||
accept3 = perms.prompt;
|
||||
}
|
||||
|
||||
|
@@ -182,6 +182,8 @@ struct aa_perms compute_perms_entry(uint32_t accept1, uint32_t accept2,
|
||||
perms.prompt = dfa_user_allow(accept3);
|
||||
perms.audit = dfa_user_audit(accept1, accept2);
|
||||
perms.quiet = dfa_user_quiet(accept1, accept2);
|
||||
if (accept1 & AA_COMPAT_CONT_MATCH)
|
||||
perms.allow |= AA_CONT_MATCH;
|
||||
|
||||
/*
|
||||
* This mapping is convulated due to history.
|
||||
|
@@ -247,8 +247,8 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
||||
{"nodev", MS_NODEV, 0},
|
||||
{"exec", 0, MS_NOEXEC},
|
||||
{"noexec", MS_NOEXEC, 0},
|
||||
{"sync", MS_SYNC, 0},
|
||||
{"async", 0, MS_SYNC},
|
||||
{"sync", MS_SYNCHRONOUS, 0},
|
||||
{"async", 0, MS_SYNCHRONOUS},
|
||||
{"remount", MS_REMOUNT, 0},
|
||||
{"mand", MS_MAND, 0},
|
||||
{"nomand", 0, MS_MAND},
|
||||
@@ -313,10 +313,16 @@ static struct mnt_keyword_table mnt_conds_table[] = {
|
||||
static ostream &dump_flags(ostream &os,
|
||||
pair <unsigned int, unsigned int> flags)
|
||||
{
|
||||
bool is_first = true;
|
||||
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))
|
||||
(flags.second & mnt_opts_table[i].clear)) {
|
||||
if (!is_first) {
|
||||
os << ", ";
|
||||
}
|
||||
is_first = false;
|
||||
os << mnt_opts_table[i].keyword;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@
|
||||
#define MS_DEV 0
|
||||
#define MS_NOEXEC (1 << 3)
|
||||
#define MS_EXEC 0
|
||||
#define MS_SYNC (1 << 4)
|
||||
#define MS_SYNCHRONOUS (1 << 4)
|
||||
#define MS_ASYNC 0
|
||||
#define MS_REMOUNT (1 << 5)
|
||||
#define MS_MAND (1 << 6)
|
||||
@@ -78,7 +78,7 @@
|
||||
#define MS_RSHARED (MS_SHARED | MS_REC)
|
||||
|
||||
#define MS_ALL_FLAGS (MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC | \
|
||||
MS_SYNC | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
|
||||
MS_SYNCHRONOUS | MS_REMOUNT | MS_MAND | MS_DIRSYNC | \
|
||||
MS_NOSYMFOLLOW | \
|
||||
MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_RBIND | \
|
||||
MS_MOVE | MS_VERBOSE | MS_ACL | \
|
||||
@@ -108,7 +108,13 @@
|
||||
#define MS_MOVE_FLAGS (MS_MOVE)
|
||||
|
||||
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | MS_MAKE_CMDS)
|
||||
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
|
||||
/*
|
||||
* This allows MS_MAKE_CMDS, by design: while remount and make-* shouldn't be
|
||||
* used together, real-world applications do use them together, and the Linux
|
||||
* kernel ignores the make-* flags when doing a remount instead of returning
|
||||
* EINVAL. See https://bugs.launchpad.net/apparmor/+bug/2091424 for an example.
|
||||
*/
|
||||
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~MS_MOVE_FLAGS)
|
||||
#define MS_NEW_FLAGS (MS_ALL_FLAGS & ~MS_CMDS)
|
||||
|
||||
#define MNT_SRC_OPT 1
|
||||
|
@@ -352,10 +352,41 @@ bool parse_port_number(const char *port_entry, uint16_t *port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse_range(const char *range, uint16_t *from, uint16_t *to)
|
||||
{
|
||||
char *range_tmp = strdup(range);
|
||||
char *dash = strchr(range_tmp, '-');
|
||||
bool ret = false;
|
||||
if (dash == NULL)
|
||||
goto out;
|
||||
*dash = '\0';
|
||||
|
||||
if (parse_port_number(range_tmp, from)) {
|
||||
if (parse_port_number(dash + 1, to)) {
|
||||
if (*from > *to) {
|
||||
goto out;
|
||||
}
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(range_tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool network_rule::parse_port(ip_conds &entry)
|
||||
{
|
||||
entry.is_port = true;
|
||||
return parse_port_number(entry.sport, &entry.port);
|
||||
if (parse_range(entry.sport, &entry.from_port, &entry.to_port))
|
||||
return true;
|
||||
if (parse_port_number(entry.sport, &entry.from_port)) {
|
||||
/* if range is not used, from and to have the same value */
|
||||
entry.to_port = entry.from_port;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool network_rule::parse_address(ip_conds &entry)
|
||||
@@ -650,23 +681,23 @@ std::list<std::ostringstream> copy_streams_list(std::list<std::ostringstream> &s
|
||||
return streams_copy;
|
||||
}
|
||||
|
||||
bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd)
|
||||
bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, uint16_t port, bool is_port, bool is_cmd)
|
||||
{
|
||||
std::string buf;
|
||||
perm32_t cond_perms;
|
||||
std::list<std::ostringstream> ip_streams;
|
||||
|
||||
for (auto &oss : streams) {
|
||||
if (entry.is_port && !(entry.is_ip && entry.is_none)) {
|
||||
if (is_port && !(entry.is_ip && entry.is_none)) {
|
||||
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
|
||||
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
|
||||
if (!is_peer && perms & AA_NET_BIND && port < IPPORT_RESERVED)
|
||||
oss << "\\x01";
|
||||
else if (is_peer)
|
||||
oss << "\\x02";
|
||||
else
|
||||
oss << "\\x00";
|
||||
|
||||
oss << gen_port_cond(entry.port);
|
||||
oss << gen_port_cond(port);
|
||||
} else {
|
||||
/* port type + port number */
|
||||
oss << "...";
|
||||
@@ -690,7 +721,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
||||
|
||||
cond_perms = map_perms(perms);
|
||||
if (!is_cmd && (label || is_peer))
|
||||
cond_perms = (AA_CONT_MATCH << 1);
|
||||
cond_perms = AA_COMPAT_CONT_MATCH;
|
||||
|
||||
for (auto &oss : streams) {
|
||||
oss << "\\x00"; /* null transition */
|
||||
@@ -764,68 +795,83 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
||||
}
|
||||
|
||||
if (perms & AA_PEER_NET_PERMS) {
|
||||
for (int peer_port = peer.from_port; peer_port <= peer.to_port; peer_port++) {
|
||||
std::list<std::ostringstream> streams;
|
||||
std::ostringstream cmd_buffer;
|
||||
|
||||
cmd_buffer << buffer.str();
|
||||
streams.push_back(std::move(cmd_buffer));
|
||||
|
||||
if (!gen_ip_conds(prof, streams, peer, true, peer_port, peer.is_port, false))
|
||||
return false;
|
||||
|
||||
for (auto &oss : streams) {
|
||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
||||
}
|
||||
|
||||
for (int local_port = local.from_port; local_port <= local.to_port; local_port++) {
|
||||
std::list<std::ostringstream> localstreams;
|
||||
|
||||
for (auto &oss : streams) {
|
||||
/* we need to copy streams because each local_port should be an unique entry */
|
||||
std::ostringstream local_buffer;
|
||||
local_buffer << oss.str();
|
||||
localstreams.push_back(std::move(local_buffer));
|
||||
}
|
||||
|
||||
if (!gen_ip_conds(prof, localstreams, local, false, local_port, local.is_port, true))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int local_port = local.from_port; local_port <= local.to_port; local_port++) {
|
||||
std::list<std::ostringstream> streams;
|
||||
std::ostringstream cmd_buffer;
|
||||
std::ostringstream common_buffer;
|
||||
|
||||
cmd_buffer << buffer.str();
|
||||
streams.push_back(std::move(cmd_buffer));
|
||||
|
||||
if (!gen_ip_conds(prof, streams, peer, true, false))
|
||||
common_buffer << buffer.str();
|
||||
streams.push_back(std::move(common_buffer));
|
||||
if (!gen_ip_conds(prof, streams, local, false, local_port, local.is_port, false))
|
||||
return false;
|
||||
|
||||
for (auto &oss : streams) {
|
||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
||||
if (perms & AA_NET_LISTEN) {
|
||||
std::list<std::ostringstream> cmd_streams;
|
||||
cmd_streams = copy_streams_list(streams);
|
||||
|
||||
for (auto &cmd_buffer : streams) {
|
||||
std::ostringstream listen_buffer;
|
||||
listen_buffer << cmd_buffer.str();
|
||||
listen_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
||||
/* length of queue allowed - not used for now */
|
||||
listen_buffer << "..";
|
||||
buf = listen_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (perms & AA_NET_OPT) {
|
||||
std::list<std::ostringstream> cmd_streams;
|
||||
cmd_streams = copy_streams_list(streams);
|
||||
|
||||
if (!gen_ip_conds(prof, streams, local, false, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<std::ostringstream> streams;
|
||||
std::ostringstream common_buffer;
|
||||
|
||||
common_buffer << buffer.str();
|
||||
streams.push_back(std::move(common_buffer));
|
||||
|
||||
if (!gen_ip_conds(prof, streams, local, false, false))
|
||||
return false;
|
||||
|
||||
if (perms & AA_NET_LISTEN) {
|
||||
std::list<std::ostringstream> cmd_streams;
|
||||
cmd_streams = copy_streams_list(streams);
|
||||
|
||||
for (auto &cmd_buffer : streams) {
|
||||
std::ostringstream listen_buffer;
|
||||
listen_buffer << cmd_buffer.str();
|
||||
listen_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
||||
/* length of queue allowed - not used for now */
|
||||
listen_buffer << "..";
|
||||
buf = listen_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (perms & AA_NET_OPT) {
|
||||
std::list<std::ostringstream> cmd_streams;
|
||||
cmd_streams = copy_streams_list(streams);
|
||||
|
||||
for (auto &cmd_buffer : streams) {
|
||||
std::ostringstream opt_buffer;
|
||||
opt_buffer << cmd_buffer.str();
|
||||
opt_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
||||
/* level - not used for now */
|
||||
opt_buffer << "..";
|
||||
/* socket mapping - not used for now */
|
||||
opt_buffer << "..";
|
||||
buf = opt_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
for (auto &cmd_buffer : streams) {
|
||||
std::ostringstream opt_buffer;
|
||||
opt_buffer << cmd_buffer.str();
|
||||
opt_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
||||
/* level - not used for now */
|
||||
opt_buffer << "..";
|
||||
/* socket mapping - not used for now */
|
||||
opt_buffer << "..";
|
||||
buf = opt_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -130,7 +130,9 @@ public:
|
||||
bool is_ip = false;
|
||||
bool is_port = false;
|
||||
|
||||
uint16_t port;
|
||||
uint16_t from_port = 0;
|
||||
uint16_t to_port = 0;
|
||||
|
||||
struct ip_address ip;
|
||||
|
||||
bool is_none = false;
|
||||
@@ -187,7 +189,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd);
|
||||
bool gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, uint16_t port, bool is_port, bool is_cmd);
|
||||
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol);
|
||||
void set_netperm(unsigned int family, unsigned int type, unsigned int protocol);
|
||||
void update_compat_net(void);
|
||||
|
@@ -53,12 +53,6 @@ using namespace std;
|
||||
*/
|
||||
extern int parser_token;
|
||||
|
||||
/* Arbitrary max and minimum priority that userspace can specify, internally
|
||||
* we handle up to INT_MAX and INT_MIN. Do not ever allow INT_MAX, see
|
||||
* note on mediates_priority
|
||||
*/
|
||||
#define MAX_PRIORITY 1000
|
||||
#define MIN_PRIORITY -1000
|
||||
|
||||
#define WARN_RULE_NOT_ENFORCED 0x1
|
||||
#define WARN_RULE_DOWNGRADED 0x2
|
||||
|
@@ -110,7 +110,12 @@ FILE *ofile = NULL;
|
||||
IncludeCache_t *g_includecache;
|
||||
|
||||
optflags parseopts = {
|
||||
.control = (optflags_t)(CONTROL_DFA_TREE_NORMAL | CONTROL_DFA_TREE_SIMPLE | CONTROL_DFA_MINIMIZE | CONTROL_DFA_DIFF_ENCODE | CONTROL_RULE_MERGE),
|
||||
.control = (optflags_t)(CONTROL_DFA_TREE_NORMAL | CONTROL_DFA_TREE_SIMPLE | CONTROL_DFA_MINIMIZE | CONTROL_DFA_DIFF_ENCODE | CONTROL_RULE_MERGE |
|
||||
/* TODO: remove when we have better auto
|
||||
* selection on when/which explicit denies
|
||||
* to remove
|
||||
*/
|
||||
CONTROL_DFA_FILTER_DENY),
|
||||
.dump = 0,
|
||||
.warn = DEFAULT_WARNINGS,
|
||||
.Werror = 0
|
||||
|
@@ -54,6 +54,9 @@ static int file_comp(const void *c1, const void *c2)
|
||||
if ((*e1)->audit != (*e2)->audit)
|
||||
return (*e1)->audit < (*e2)->audit ? -1 : 1;
|
||||
|
||||
if ((*e1)->priority != (*e2)->priority)
|
||||
return (*e2)->priority - (*e1)->priority;
|
||||
|
||||
return strcmp((*e1)->name, (*e2)->name);
|
||||
}
|
||||
|
||||
|
@@ -1079,6 +1079,8 @@ void debug_cod_entries(struct cod_entry *list)
|
||||
debug_base_perm_mask(SHIFT_TO_BASE(item->perms, AA_USER_SHIFT));
|
||||
printf(":");
|
||||
debug_base_perm_mask(SHIFT_TO_BASE(item->perms, AA_OTHER_SHIFT));
|
||||
|
||||
printf(" priority=%d ", item->priority);
|
||||
if (item->name)
|
||||
printf("\tName:\t(%s)\n", item->name);
|
||||
else
|
||||
@@ -1122,6 +1124,8 @@ bool entry_add_prefix(struct cod_entry *entry, const prefixes &p, const char *&e
|
||||
else if (p.owner == 2)
|
||||
entry->perms &= (AA_OTHER_PERMS | AA_SHARED_PERMS);
|
||||
|
||||
entry->priority = p.priority;
|
||||
|
||||
/* implied audit modifier */
|
||||
if (p.audit == AUDIT_FORCE && (entry->rule_mode != RULE_DENY))
|
||||
entry->audit = AUDIT_FORCE;
|
||||
|
@@ -1093,9 +1093,21 @@ static const char *deny_file = ".*";
|
||||
*
|
||||
* Note: it turns out the above bug does exist for dbus rules in parsers
|
||||
* that do not support priority, and we don't have a way to fix it.
|
||||
* We fix it here by capping user specified priority to be < INT_MAX.
|
||||
* We fix it here by capping user specified priority to be less than
|
||||
* MAX_INTERNAL_PRIORITY.
|
||||
*/
|
||||
static int mediates_priority = INT_MAX;
|
||||
static int mediates_priority = MAX_INTERNAL_PRIORITY;
|
||||
|
||||
/* some rule types unfortunately encoded permissions on the class byte
|
||||
* to fix the above bug, they need a different solution. The generic
|
||||
* mediates rule will get encoded at the minimum priority, and then
|
||||
* for every rule of those classes a mediates rule of the same priority
|
||||
* will be added. This way the mediates rule never has higher priority,
|
||||
* which would wipe out the rule permissions encoded on the class state,
|
||||
* and it is guaranteed to have the same priority as the highest priority
|
||||
* rule.
|
||||
*/
|
||||
static int perms_onclass_mediates_priority = MIN_INTERNAL_PRIORITY;
|
||||
|
||||
int process_profile_policydb(Profile *prof)
|
||||
{
|
||||
@@ -1112,7 +1124,7 @@ int process_profile_policydb(Profile *prof)
|
||||
* to be supported
|
||||
*/
|
||||
if (features_supports_userns &&
|
||||
!prof->policy.rules->add_rule(mediates_ns, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_ns, perms_onclass_mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
|
||||
/* don't add mediated classes to unconfined profiles */
|
||||
@@ -1148,7 +1160,7 @@ int process_profile_policydb(Profile *prof)
|
||||
!prof->policy.rules->add_rule(mediates_sysv_mqueue, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_io_uring &&
|
||||
!prof->policy.rules->add_rule(mediates_io_uring, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_io_uring, perms_onclass_mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@@ -640,10 +640,10 @@ opt_priority: { $$ = 0; }
|
||||
yyerror("invalid priority %s", $3);
|
||||
free($3);
|
||||
/* see note on mediates_priority */
|
||||
if (tmp > MAX_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MAX_PRIORITY);
|
||||
if (tmp < MIN_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MIN_PRIORITY);
|
||||
if (tmp > MAX_POLICY_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MAX_POLICY_PRIORITY);
|
||||
if (tmp < MIN_POLICY_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MIN_POLICY_PRIORITY);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
@@ -24,6 +24,11 @@
|
||||
* older versions
|
||||
*/
|
||||
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
using std::ostream;
|
||||
using std::cerr;
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
@@ -65,6 +70,9 @@
|
||||
#define AA_MAY_DELEGATE
|
||||
#define AA_CONT_MATCH 0x08000000
|
||||
|
||||
// TODO: move into a reworked immunix.h that is dependent on perms.h
|
||||
#define AA_COMPAT_CONT_MATCH (AA_CONT_MATCH << 1)
|
||||
|
||||
#define AA_MAY_STACK 0x10000000
|
||||
#define AA_MAY_ONEXEC 0x20000000 /* either stack or change_profile */
|
||||
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
||||
@@ -79,7 +87,7 @@
|
||||
* - exec type - which determines how the executable name and index are used
|
||||
* - flags - which modify how the destination name is applied
|
||||
*/
|
||||
#define AA_X_INDEX_MASK AA_INDEX_MASK
|
||||
#define AA_X_INDEX_MASK 0xffffff
|
||||
|
||||
#define AA_X_TYPE_MASK 0x0c000000
|
||||
#define AA_X_NONE AA_INDEX_NONE
|
||||
@@ -93,7 +101,8 @@
|
||||
|
||||
typedef uint32_t perm32_t;
|
||||
|
||||
struct aa_perms {
|
||||
class aa_perms {
|
||||
public:
|
||||
perm32_t allow;
|
||||
perm32_t deny; /* explicit deny, or conflict if allow also set */
|
||||
|
||||
@@ -112,6 +121,33 @@ struct aa_perms {
|
||||
uint32_t xindex;
|
||||
uint32_t tag; /* tag string index, if present */
|
||||
uint32_t label; /* label string index, if present */
|
||||
|
||||
void dump_header(ostream &os)
|
||||
{
|
||||
os << "(allow/deny/prompt//audit/quiet//xindex)\n";
|
||||
}
|
||||
|
||||
void dump(ostream &os)
|
||||
{
|
||||
os << std::hex << "(0x" << allow << "/0x" << deny << "/0x"
|
||||
<< prompt << "//0x" << audit << "/0x" << quiet
|
||||
<< std::dec << "//";
|
||||
if (xindex & AA_X_UNSAFE)
|
||||
os << "unsafe ";
|
||||
if (xindex & AA_X_TYPE_MASK) {
|
||||
if (xindex & AA_X_CHILD)
|
||||
os << "c";
|
||||
else
|
||||
os << "p";
|
||||
}
|
||||
if (xindex & AA_X_INHERIT)
|
||||
os << "i";
|
||||
if (xindex & AA_X_UNCONFINED)
|
||||
os << "u";
|
||||
os << (xindex & AA_X_INDEX_MASK);
|
||||
os << ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* __AA_PERM_H */
|
||||
|
@@ -252,9 +252,9 @@ public:
|
||||
tmp = (int) rule_mode - (int) rhs.rule_mode;
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
if ((uint) owner < (uint) rhs.owner)
|
||||
if ((unsigned int) owner < (unsigned int) rhs.owner)
|
||||
return -1;
|
||||
if ((uint) owner > (uint) rhs.owner)
|
||||
if ((unsigned int) owner > (unsigned int) rhs.owner)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -28,11 +28,104 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-${_SCRIPTDIR}/../apparmor_parser}"
|
||||
fails=0
|
||||
errors=0
|
||||
verbose="${VERBOSE:-}"
|
||||
default_features_file="features.all"
|
||||
features_file=$default_features_file
|
||||
retain=0
|
||||
dumpdfa=0
|
||||
testtype=""
|
||||
description="Manually run test"
|
||||
tmpdir=$(mktemp -d /tmp/eq.$$-XXXXXX)
|
||||
chmod 755 ${tmpdir}
|
||||
export tmpdir
|
||||
|
||||
map_priority()
|
||||
{
|
||||
if [ -z "$1" -o "$1" == "priority=0" ] ; then
|
||||
echo "0";
|
||||
elif [ "$1" == "priority=-1" ] ; then
|
||||
echo "-1"
|
||||
elif [ "$1" == "priority=1" ] ;then
|
||||
echo "1"
|
||||
else
|
||||
echo "unknown priority '$1'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
priority_eq()
|
||||
{
|
||||
local p1=$(map_priority "$1")
|
||||
local p2=$(map_priority "$2")
|
||||
|
||||
if [ $p1 -eq $p2 ] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
priority_lt()
|
||||
{
|
||||
local p1=$(map_priority "$1")
|
||||
local p2=$(map_priority "$2")
|
||||
|
||||
if [ $p1 -lt $p2 ] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
priority_gt()
|
||||
{
|
||||
local p1=$(map_priority "$1")
|
||||
local p2=$(map_priority "$2")
|
||||
|
||||
if [ $p1 -gt $p2 ] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
hash_binary_policy()
|
||||
{
|
||||
printf %s "$1" | ${APPARMOR_PARSER} --features-file "${_SCRIPTDIR}/features_files/features.all" -qS 2>/dev/null| md5sum | cut -d ' ' -f 1
|
||||
return $?
|
||||
local hash="parser_failure"
|
||||
local dump="/dev/null"
|
||||
local flags="-QKSq"
|
||||
local rc=0
|
||||
|
||||
if [ $dumpdfa -ne 0 ] ; then
|
||||
flags="$flags -D rule-exprs -D dfa-states"
|
||||
dump="${tmpdir}/$1.state"
|
||||
fi
|
||||
|
||||
printf %s "$2" | ${APPARMOR_PARSER} --features-file "${_SCRIPTDIR}/features_files/$features_file" ${flags} > "$tmpdir/$1.bin" 2>"$dump"
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ] ; then
|
||||
hash=$(sha256sum "${tmpdir}/$1.bin" | cut -d ' ' -f 1)
|
||||
rc=$?
|
||||
fi
|
||||
|
||||
printf %s $hash
|
||||
if [ $retain -eq 0 -a $rc -ne 0 ] ; then
|
||||
rm ${tmpdir}/*
|
||||
else
|
||||
mv "${tmpdir}/$1.bin" "${tmpdir}/$1.bin.$hash"
|
||||
if [ $dumpdfa -ne 0 ] ; then
|
||||
mv "${tmpdir}/$1.state" "$tmpdir/$1.state.$hash"
|
||||
fi
|
||||
fi
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
check_retain()
|
||||
{
|
||||
if [ ${retain} -ne 0 ] ; then
|
||||
printf " files retained in \"%s/\"\n" ${tmpdir} 1>&2
|
||||
exit $ret
|
||||
fi
|
||||
}
|
||||
|
||||
# verify_binary - compares the binary policy of multiple profiles
|
||||
@@ -55,26 +148,28 @@ verify_binary()
|
||||
shift
|
||||
shift
|
||||
|
||||
if [ "$t" != "equality" ] && [ "$t" != "inequality" ]
|
||||
if [ "$t" != "equality" ] && [ "$t" != "inequality" ] && \
|
||||
[ "$t" != "xequality" ] && [ "$t" != "xinequality" ]
|
||||
then
|
||||
printf "\nERROR: Unknown test mode:\n%s\n\n" "$t" 1>&2
|
||||
((errors++))
|
||||
return $((ret + 1))
|
||||
fi
|
||||
rm -f $tmpdir/*
|
||||
|
||||
if [ -n "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
if ! good_hash=$(hash_binary_policy "$good_profile")
|
||||
then
|
||||
if ! good_hash=$(hash_binary_policy "known" "$good_profile") ; then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nERROR: Error hashing the following \"known-good\" profile:\n%s\n\n" \
|
||||
"$good_profile" 1>&2
|
||||
((errors++))
|
||||
rm -f ${tmpdir}/*
|
||||
return $((ret + 1))
|
||||
fi
|
||||
|
||||
for profile in "$@"
|
||||
do
|
||||
if ! hash=$(hash_binary_policy "$profile")
|
||||
if ! hash=$(hash_binary_policy "test" "$profile")
|
||||
then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nERROR: Error hashing the following profile:\n%s\n\n" \
|
||||
@@ -84,20 +179,52 @@ verify_binary()
|
||||
elif [ "$t" == "equality" ] && [ "$hash" != "$good_hash" ]
|
||||
then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nFAIL: Hash values do not match\n" 2>&1
|
||||
printf "known-good (%s) != profile-under-test (%s) for the following profile:\n%s\n\n" \
|
||||
"$good_hash" "$hash" "$profile" 1>&2
|
||||
printf "\nFAIL: Hash values do not match\n" 1>&2
|
||||
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
|
||||
printf "known-good (%s) != profile-under-test (%s) for the following profiles:\nknown-good %s\nprofile-under-test %s\n\n" \
|
||||
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
|
||||
((fails++))
|
||||
((ret++))
|
||||
check_retain
|
||||
elif [ "$t" == "xequality" ] && [ "$hash" == "$good_hash" ]
|
||||
then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nunexpected PASS: equality test with known problem, Hash values match\n" 1>&2
|
||||
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
|
||||
printf "known-good (%s) == profile-under-test (%s) for the following profile:\nknown-good %s\nprofile-under-test %s\n\n" \
|
||||
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
|
||||
((fails++))
|
||||
((ret++))
|
||||
check_retain
|
||||
elif [ "$t" == "xequality" ] && [ "$hash" != "$good_hash" ]
|
||||
then
|
||||
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
|
||||
elif [ "$t" == "inequality" ] && [ "$hash" == "$good_hash" ]
|
||||
then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nFAIL: Hash values match\n" 2>&1
|
||||
printf "known-good (%s) == profile-under-test (%s) for the following profile:\n%s\n\n" \
|
||||
"$good_hash" "$hash" "$profile" 1>&2
|
||||
printf "\nFAIL: Hash values match\n" 1>&2
|
||||
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
|
||||
printf "known-good (%s) == profile-under-test (%s) for the following profiles:\nknown-good %s\nprofile-under-test %s\n\n" \
|
||||
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
|
||||
((fails++))
|
||||
((ret++))
|
||||
check_retain
|
||||
elif [ "$t" == "xinequality" ] && [ "$hash" != "$good_hash" ]
|
||||
then
|
||||
if [ -z "$verbose" ] ; then printf "Binary %s %s" "$t" "$desc" ; fi
|
||||
printf "\nunexpected PASS: inequality test with known problem, Hash values do not match\n" 1>&2
|
||||
printf "parser: %s -QKSq --features-file %s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
|
||||
printf "known-good (%s) != profile-under-test (%s) for the following profile:\nknown-good %s\nprofile-under-test %s\n\n" \
|
||||
"$good_hash" "$hash" "$good_profile" "$profile" 1>&2
|
||||
((fails++))
|
||||
((ret++))
|
||||
check_retain
|
||||
elif [ "$t" == "xinequality" ] && [ "$hash" == "$good_hash" ]
|
||||
then
|
||||
printf "\nknown problem %s %s: unchanged" "$t" "$desc" 1>&2
|
||||
printf "parser: %s -QKSq --features-file=%s\n" "${APPARMOR_PARSER}" "${_SCRIPTDIR}/features_files/$features_file" 1>&2
|
||||
fi
|
||||
rm -f ${tmpdir}/test*
|
||||
done
|
||||
|
||||
if [ $ret -eq 0 ]
|
||||
@@ -117,11 +244,56 @@ verify_binary_equality()
|
||||
verify_binary "equality" "$@"
|
||||
}
|
||||
|
||||
# test we want to be equal but is currently a known problem
|
||||
verify_binary_xequality()
|
||||
{
|
||||
verify_binary "xequality" "$@"
|
||||
}
|
||||
|
||||
verify_binary_inequality()
|
||||
{
|
||||
verify_binary "inequality" "$@"
|
||||
}
|
||||
|
||||
# test we want to be not equal but is currently a know problem
|
||||
verify_binary_xinequality()
|
||||
{
|
||||
verify_binary "xinequality" "$@"
|
||||
}
|
||||
|
||||
# kernel_features - test whether path(s) are present
|
||||
# $@: feature path(s) to test
|
||||
# Returns: 0 and outputs "true" if all paths exist
|
||||
# 1 and error message if features dir is not available
|
||||
# 2 and error message if path does not exist
|
||||
kernel_features()
|
||||
{
|
||||
features_dir="/sys/kernel/security/apparmor/features/"
|
||||
if [ ! -e "$features_dir" ] ; then
|
||||
echo "Kernel feature masks not supported."
|
||||
return 1;
|
||||
fi
|
||||
|
||||
for f in $@ ; do
|
||||
if [ ! -e "$features_dir/$f" ] ; then
|
||||
# check if feature is in file
|
||||
feature=$(basename "$features_dir/$f")
|
||||
file=$(dirname "$features_dir/$f")
|
||||
if [ -f $file ]; then
|
||||
if ! grep -q $feature $file; then
|
||||
echo "Required feature '$f' not available."
|
||||
return 2;
|
||||
fi
|
||||
else
|
||||
echo "Required feature '$f' not available."
|
||||
return 3;
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "true"
|
||||
return 0;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
### wrapper fn, should be indented but isn't to reduce wrap
|
||||
@@ -129,7 +301,7 @@ verify_set()
|
||||
{
|
||||
local p1="$1"
|
||||
local p2="$2"
|
||||
echo -e "\n equality $e of '$p1' vs '$p2'\n"
|
||||
[ -n "${verbose}" ] && echo -e "\n equality $e of '$p1' vs '$p2'\n"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus send" \
|
||||
"/t { $p1 dbus send, }" \
|
||||
@@ -477,37 +649,86 @@ do
|
||||
"pix -> b" "Pix -> b" "cux -> b" "Cux -> b" \
|
||||
"cix -> b" "Cix -> b"
|
||||
do
|
||||
if [ "$perm1" == "$perm2" ] ; then
|
||||
# Fixme: have to do special handling for -> b, as this
|
||||
# creates an entry in the transition table. However
|
||||
# priority rules can make it so the reference to the
|
||||
# transition table is removed, but the parser still keeps
|
||||
# the tranition. This can lead to a situation where the
|
||||
# test dfa with a "-> b" transition is functionally equivalent
|
||||
# but will fail equality comparison.
|
||||
# fix this by adding two none overlapping x rules to add
|
||||
# xtable entries
|
||||
# /c -> /t//b, for cx rules being converted to px -> /t//b
|
||||
# /a -> b, for px rules
|
||||
# the rules must come last guarantee xtable order
|
||||
if [ "$perm1" == "$perm2" ] || priority_gt "$p1" "" ; then
|
||||
verify_binary_equality "'$p1'x'$p2' Exec perm \"${perm1}\" - most specific match: same as glob" \
|
||||
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
"/t { $p1 /f* ${perm1}, /f ${perm2}, /a px -> b, /c px -> /t//b, }" \
|
||||
"/t { $p2 /f* ${perm1}, /a px -> b, /c px -> /t//b, }"
|
||||
else
|
||||
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs \"${perm2}\" - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
"/t { $p1 /f* ${perm1}, /f ${perm2}, /a px -> b, /c px -> /t//b, }" \
|
||||
"/t { $p2 /f* ${perm1}, /a px -> b, /c px -> /t//b, }"
|
||||
fi
|
||||
done
|
||||
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
if priority_gt "$p1" "" ; then
|
||||
# priority stops permission carve out
|
||||
verify_binary_equality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
else
|
||||
# deny rule carves out some of the match
|
||||
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
#Test deny carves out permission
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
||||
if priority_gt "$p1" "" ; then
|
||||
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[ac] r, }"
|
||||
|
||||
#this one may not be true in the future depending on if the compiled profile
|
||||
#is explicitly including deny permissions for dynamic composition
|
||||
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
|
||||
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
elif priority_eq "$p1" "" ; then
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[ac] r, }"
|
||||
|
||||
#this one may not be true in the future depending on if the compiled profile
|
||||
#is explicitly including deny permissions for dynamic composition
|
||||
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
else
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[ac] r, }"
|
||||
|
||||
#this one may not be true in the future depending on if the compiled profile
|
||||
#is explicitly including deny permissions for dynamic composition
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny of ungranted perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
fi
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' change_profile == change_profile -> **" \
|
||||
"/t { $p1 change_profile, }" \
|
||||
@@ -587,9 +808,25 @@ verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc
|
||||
# the "write" permission in the second profile and the test will fail.
|
||||
# If the parser is adding the change_hat proc attr rules then the
|
||||
# rules should merge and be equivalent.
|
||||
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
|
||||
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
||||
#
|
||||
# if priorities are different then the implied rule priority then the
|
||||
# implied rule will completely override or completely be overriden.
|
||||
# (the change_hat implied rule has a priority of 0)
|
||||
# because of the difference in 'a' vs 'w' permission the two rules should
|
||||
# only be equal when the append rule has the same priority as the implied
|
||||
# rule (allowing them to combine) AND the other rule is not overridden by
|
||||
# the implied rule, or both being overridden by the implied rule
|
||||
# the implied rule
|
||||
if { priority_lt "$p1" "" && priority_lt "$p2" "" ; } ||
|
||||
{ priority_eq "$p1" "" && ! priority_lt "$p2" "" ; }; then
|
||||
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
|
||||
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
||||
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
|
||||
else
|
||||
verify_binary_inequality "'$p1'x'$p2' change_hat rules automatically inserted"\
|
||||
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
||||
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
|
||||
fi
|
||||
|
||||
# verify slash filtering for unix socket address paths.
|
||||
# see https://bugs.launchpad.net/apparmor/+bug/1856738
|
||||
@@ -677,7 +914,7 @@ verify_binary_equality "'$p1'x'$p2' mount specific deny doesn't affect non-overl
|
||||
|
||||
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
|
||||
then
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 1>&2
|
||||
exit $((fails + errors))
|
||||
fi
|
||||
|
||||
@@ -758,12 +995,14 @@ verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
|
||||
}
|
||||
|
||||
|
||||
printf "Equality Tests:\n"
|
||||
run_tests()
|
||||
{
|
||||
printf "Equality Tests:\n"
|
||||
|
||||
#rules that don't support priority
|
||||
#rules that don't support priority
|
||||
|
||||
# verify rlimit data conversions
|
||||
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||
# verify rlimit data conversions
|
||||
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||
"/t { set rlimit rttime <= 12 weeks, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
|
||||
@@ -773,7 +1012,7 @@ verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
|
||||
|
||||
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||
"/t { set rlimit cpu <= 42 weeks, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
|
||||
@@ -781,39 +1020,209 @@ verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
|
||||
|
||||
verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||
verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||
"/t { set rlimit memlock <= 2GB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
|
||||
|
||||
|
||||
# verify combinations of different priority levels
|
||||
# for single rule comparisons, rules should keep same expected result
|
||||
# even when the priorities are different.
|
||||
# different priorities within a profile comparison resulting in
|
||||
# different permission could affected expected results
|
||||
|
||||
|
||||
priorities="none 0 1 -1"
|
||||
|
||||
for pri1 in $priorities ; do
|
||||
if [ "$pri1" = "none" ] ; then
|
||||
priority1=""
|
||||
else
|
||||
priority1="priority=$pri1"
|
||||
fi
|
||||
for pri2 in $priorities ; do
|
||||
if [ "$pri2" = "none" ] ; then
|
||||
priority2=""
|
||||
run_port_range=$(kernel_features network_v8/af_inet)
|
||||
if [ "$run_port_range" != "true" ]; then
|
||||
echo -e "\nSkipping network af_inet tests. $run_port_range\n"
|
||||
else
|
||||
priority2="priority=$pri2"
|
||||
# network port range
|
||||
# select features file that contains netv8 af_inet
|
||||
features_file="features.af_inet"
|
||||
verify_binary_equality "network port range" \
|
||||
"/t { network port=3456-3460, }" \
|
||||
"/t { network port=3456, \
|
||||
network port=3457, \
|
||||
network port=3458, \
|
||||
network port=3459, \
|
||||
network port=3460, }"
|
||||
|
||||
verify_binary_equality "network peer port range" \
|
||||
"/t { network peer=(port=3456-3460), }" \
|
||||
"/t { network peer=(port=3456), \
|
||||
network peer=(port=3457), \
|
||||
network peer=(port=3458), \
|
||||
network peer=(port=3459), \
|
||||
network peer=(port=3460), }"
|
||||
|
||||
verify_binary_inequality "network port range allows more than single port" \
|
||||
"/t { network port=3456-3460, }" \
|
||||
"/t { network port=3456, }"
|
||||
|
||||
verify_binary_inequality "network peer port range allows more than single port" \
|
||||
"/t { network peer=(port=3456-3460), }" \
|
||||
"/t { network peer=(port=3456), }"
|
||||
# return to default
|
||||
features_file=$default_features_file
|
||||
fi
|
||||
|
||||
verify_set "$priority1" "$priority2"
|
||||
done
|
||||
# Equality tests that set explicit priority level
|
||||
# TODO: priority handling for file paths is currently broken
|
||||
|
||||
# This test is not actually correct due to two subtle
|
||||
# interactions: - /* is special-cased to expand to /[^/\x00]+
|
||||
# with at least one character - Quieting of [^a] in the DFA is
|
||||
# different and cannot be manually fixed
|
||||
|
||||
#verify_binary_xequality "file rule carveout regex vs priority" \
|
||||
# "/t { deny /[^a]* rwxlk, /a r, }" \
|
||||
# "/t { priority=-1 deny /* rwxlk, /a r, }" \
|
||||
|
||||
# Not grouping all three together because parser correctly handles
|
||||
# the equivalence of carveout regex and default audit deny
|
||||
verify_binary_equality "file rule carveout regex vs priority (audit)" \
|
||||
"/t { audit deny /[^a]* rwxlk, /a r, }" \
|
||||
"/t { priority=-1 audit deny /* rwxlk, /a r, }"
|
||||
|
||||
verify_binary_equality "file rule default audit deny vs audit priority carveout" \
|
||||
"/t { /a r, }" \
|
||||
"/t { priority=-1 audit deny /* rwxlk, /a r, }"
|
||||
|
||||
# verify combinations of different priority levels
|
||||
# for single rule comparisons, rules should keep same expected result
|
||||
# even when the priorities are different.
|
||||
# different priorities within a profile comparison resulting in
|
||||
# different permission could affected expected results
|
||||
|
||||
|
||||
priorities="none 0 1 -1"
|
||||
|
||||
for pri1 in $priorities ; do
|
||||
if [ "$pri1" = "none" ] ; then
|
||||
priority1=""
|
||||
else
|
||||
priority1="priority=$pri1"
|
||||
fi
|
||||
for pri2 in $priorities ; do
|
||||
if [ "$pri2" = "none" ] ; then
|
||||
priority2=""
|
||||
else
|
||||
priority2="priority=$pri2"
|
||||
fi
|
||||
|
||||
verify_set "$priority1" "$priority2"
|
||||
done
|
||||
done
|
||||
|
||||
[ -z "${verbose}" ] && printf "\n"
|
||||
printf "PASS\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
usage()
|
||||
{
|
||||
local progname="$0"
|
||||
local rc="$1"
|
||||
local msg="usage: ${progname} [Options]
|
||||
|
||||
Run the equality tests if no options given, otherwise run as directed
|
||||
by the options.
|
||||
|
||||
Options:
|
||||
-h, --help display this help
|
||||
-e base args run an equality test on the following args
|
||||
-n base args run an inequality test on the following args
|
||||
-xequality run a known proble equality test
|
||||
-xinequality run a known proble inequality test
|
||||
-r on failure retain failed test output and abort
|
||||
-d include dfa dumps with failed test output
|
||||
-f arg features file to use
|
||||
-p arg parser to invoke
|
||||
--description description to print with test
|
||||
-v verbose
|
||||
examples:
|
||||
$ equality.sh
|
||||
...
|
||||
$ equality.sh -r
|
||||
....
|
||||
inary equality 'priority=1'x'' Exec perm \"ux\" - most specific match: same as glob
|
||||
FAIL: Hash values do not match
|
||||
parser: ../apparmor_parser --config-file=./parser.conf --features-file=./features_files/features.all
|
||||
known-good (0344cd377ccb239aba4cce768b818010961d68091d8c7fae72c755cfcb48d4a2) != profile-under-test (33fdf4575322a036c2acb75f93a7154179036f1189ef68ab9f1ae98e7f865780) for the following profiles:
|
||||
known-good /t { priority=1 /* ux, /f px -> b, }
|
||||
profile-under-test /t { /* ux, }
|
||||
|
||||
$ equality.sh -e \"/t { priority=1 /* Px -> b, /f Px, }\" \"/t { /* Px, }\"
|
||||
$ equality.sh -e \"/t { priority=1 /* Px -> b, /f Px, }\" \"/t { /* Px, }\""
|
||||
|
||||
echo "$msg"
|
||||
}
|
||||
|
||||
|
||||
POSITIONAL_ARGS=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-e|--equality)
|
||||
testtype="equality"
|
||||
shift # past argument
|
||||
;;
|
||||
--xequality)
|
||||
testtype="xequality"
|
||||
shift # past argument
|
||||
;;
|
||||
-n|--inequality)
|
||||
testtype="inequality"
|
||||
shift # past argument
|
||||
;;
|
||||
--xinequality)
|
||||
testtype="xinequality"
|
||||
shift # past argument
|
||||
;;
|
||||
-d|--dfa)
|
||||
dumpdfa=1
|
||||
shift # past argument
|
||||
;;
|
||||
-r|--retain)
|
||||
retain=1
|
||||
shift # past argument
|
||||
;;
|
||||
-v|--verbose)
|
||||
verbos=1
|
||||
shift # past argument
|
||||
;;
|
||||
-f|--feature-file)
|
||||
features_file="$2"
|
||||
shift # past argument
|
||||
shift # past option
|
||||
;;
|
||||
--description)
|
||||
description="$2"
|
||||
shift # past argument
|
||||
shift # past option
|
||||
;;
|
||||
-p|--parser)
|
||||
APPARMOR_PARSER="$2"
|
||||
shift # past argument
|
||||
shift # past option
|
||||
;;
|
||||
-*|--*)
|
||||
echo "Unknown option $1"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
POSITIONAL_ARGS+=("$1") # save positional arg
|
||||
shift # past argument
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -z "${verbose}" ] && printf "\n"
|
||||
printf "PASS\n"
|
||||
exit 0
|
||||
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
|
||||
|
||||
if [ $# -eq 0 -o -z $testtype] ; then
|
||||
run_tests "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
for profile in "$@" ; do
|
||||
verify_binary "$testtype" "$description" "$known" "$profile"
|
||||
done
|
||||
|
117
parser/tst/features_files/features.af_inet
Normal file
117
parser/tst/features_files/features.af_inet
Normal file
@@ -0,0 +1,117 @@
|
||||
capability {0xffffff
|
||||
}
|
||||
caps {extended {yes
|
||||
}
|
||||
mask {chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read perfmon bpf checkpoint_restore
|
||||
}
|
||||
}
|
||||
dbus {mask {acquire send receive
|
||||
}
|
||||
}
|
||||
domain {attach_conditions {xattr {yes
|
||||
}
|
||||
}
|
||||
change_hat {yes
|
||||
}
|
||||
change_hatv {yes
|
||||
}
|
||||
change_onexec {yes
|
||||
}
|
||||
change_profile {yes
|
||||
}
|
||||
computed_longest_left {yes
|
||||
}
|
||||
disconnected.path {yes
|
||||
}
|
||||
fix_binfmt_elf_mmap {yes
|
||||
}
|
||||
interruptible {yes
|
||||
}
|
||||
kill.signal {yes
|
||||
}
|
||||
post_nnp_subset {yes
|
||||
}
|
||||
stack {yes
|
||||
}
|
||||
unconfined_allowed_children {yes
|
||||
}
|
||||
version {1.2
|
||||
}
|
||||
}
|
||||
file {mask {create read write exec append mmap_exec link lock
|
||||
}
|
||||
}
|
||||
io_uring {mask {sqpoll override_creds
|
||||
}
|
||||
}
|
||||
ipc {posix_mqueue {create read write open delete setattr getattr
|
||||
}
|
||||
}
|
||||
mount {mask {mount umount pivot_root
|
||||
}
|
||||
move_mount {detached
|
||||
}
|
||||
}
|
||||
namespaces {mask {userns_create
|
||||
}
|
||||
pivot_root {no
|
||||
}
|
||||
profile {yes
|
||||
}
|
||||
userns_create {pciu&
|
||||
}
|
||||
}
|
||||
network {af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
|
||||
}
|
||||
af_unix {yes
|
||||
}
|
||||
}
|
||||
network_v8 {af_inet {yes
|
||||
}
|
||||
af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
|
||||
}
|
||||
}
|
||||
policy {outofband {0x000001
|
||||
}
|
||||
permstable32 {allow deny subtree cond kill complain prompt audit quiet hide xindex tag label
|
||||
}
|
||||
permstable32_version {0x000003
|
||||
}
|
||||
set_load {yes
|
||||
}
|
||||
unconfined_restrictions {change_profile {yes
|
||||
}
|
||||
io_uring {0
|
||||
}
|
||||
userns {1
|
||||
}
|
||||
}
|
||||
versions {v5 {yes
|
||||
}
|
||||
v6 {yes
|
||||
}
|
||||
v7 {yes
|
||||
}
|
||||
v8 {yes
|
||||
}
|
||||
v9 {yes
|
||||
}
|
||||
}
|
||||
}
|
||||
ptrace {mask {read trace
|
||||
}
|
||||
}
|
||||
query {label {data {yes
|
||||
}
|
||||
multi_transaction {yes
|
||||
}
|
||||
perms {allow deny audit quiet
|
||||
}
|
||||
}
|
||||
}
|
||||
rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
|
||||
}
|
||||
}
|
||||
signal {mask {hup int quit ill trap abrt bus fpe kill usr1 segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg xcpu xfsz vtalrm prof winch io pwr sys emt lost
|
||||
}
|
||||
}
|
7
parser/tst/simple_tests/file/priority/bad_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/bad_1.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=Description to rule priority out of low end of range
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1001 /usr/bin/foo r,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/bad_2.sd
Normal file
7
parser/tst/simple_tests/file/priority/bad_2.sd
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
#=Description basic file rule priority outside high end of range.
|
||||
#=EXRESULT FAIL
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=1001 /usr/bin/foo r,
|
||||
}
|
12
parser/tst/simple_tests/network/network_ok_17.sd
Normal file
12
parser/tst/simple_tests/network/network_ok_17.sd
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
#=DESCRIPTION network port range conditional test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
network peer=(port=22-443),
|
||||
network port=22-443,
|
||||
network port=22-443 peer=(port=1-100),
|
||||
network ip=127.0.0.1 port=3456-3457,
|
||||
network ip=127.0.0.1 port=3456-3457 peer=(ip=127.0.0.2 port=8765-8770),
|
||||
|
||||
}
|
@@ -99,6 +99,14 @@ int userns_rule::gen_policy_re(Profile &prof)
|
||||
rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
|
||||
goto fail;
|
||||
/* add a mediates_userns rule for every rule added. It
|
||||
* needs to be the same priority
|
||||
*/
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
RULE_ALLOW, AA_MAY_READ, 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@@ -5,8 +5,9 @@
|
||||
# permissions for querying dconf settings; granting write access should
|
||||
# be specified in a specific application's profile.
|
||||
|
||||
/etc/dconf/** r,
|
||||
owner @{run}/user/*/dconf/user r,
|
||||
@{etc_ro}/dconf/** r,
|
||||
# TODO: make w conditional when an override is available, so it can be moved to a portal.
|
||||
owner @{run}/user/*/dconf/user rw,
|
||||
owner @{HOME}/.config/dconf/user r,
|
||||
|
||||
# Include additions to the abstraction
|
||||
|
@@ -20,6 +20,12 @@
|
||||
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
|
||||
|
||||
owner @{HOME}/.cache/mesa_shader_cache_db/ rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache_db/index rwk,
|
||||
owner @{HOME}/.cache/mesa_shader_cache_db/part*/ rw,
|
||||
owner @{HOME}/.cache/mesa_shader_cache_db/part*/mesa_cache.db rwk,
|
||||
owner @{HOME}/.cache/mesa_shader_cache_db/part*/mesa_cache.idx rwk,
|
||||
|
||||
# Fallback location when @{HOME}/.cache is not available
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/ rw,
|
||||
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/index rw,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#
|
||||
# Copyright (C) 2002-2009 Novell/SUSE
|
||||
# Copyright (C) 2009-2011 Canonical Ltd.
|
||||
# Copyright (C) 2011-2024 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
|
||||
@@ -11,29 +12,11 @@
|
||||
|
||||
abi <abi/4.0>,
|
||||
|
||||
# Many programs wish to perform nameservice-like operations, such as
|
||||
# looking up users by name or id, groups by name or id, hosts by name
|
||||
# or IP, etc. These operations may be performed through files, dns,
|
||||
# NIS, NIS+, LDAP, hesiod, wins, etc. Allow them all here.
|
||||
@{etc_ro}/group r,
|
||||
@{etc_ro}/host.conf r,
|
||||
@{etc_ro}/hosts r,
|
||||
@{etc_ro}/nsswitch.conf r,
|
||||
@{etc_ro}/gai.conf r,
|
||||
@{etc_ro}/passwd r,
|
||||
@{etc_ro}/protocols r,
|
||||
|
||||
# On systems with authselect installed, /etc/nsswitch.conf is a symlink to /etc/authselect/nsswitch.conf
|
||||
@{etc_ro}/authselect/nsswitch.conf r,
|
||||
include <abstractions/nameservice-strict>
|
||||
|
||||
# libtirpc (used for NIS/YP login) needs this
|
||||
@{etc_ro}/netconfig r,
|
||||
|
||||
# When using libnss-extrausers, the passwd and group files are merged from
|
||||
# an alternate path
|
||||
/var/lib/extrausers/group r,
|
||||
/var/lib/extrausers/passwd r,
|
||||
|
||||
# When using sssd, the passwd and group files are stored in an alternate path
|
||||
# and the nss plugin also needs to talk to a pipe
|
||||
/var/lib/sss/mc/group r,
|
||||
@@ -41,16 +24,13 @@
|
||||
/var/lib/sss/mc/passwd r,
|
||||
/var/lib/sss/pipes/nss rw,
|
||||
|
||||
@{etc_ro}/resolv.conf r,
|
||||
# On systems where /etc/resolv.conf is managed programmatically, it is
|
||||
# a symlink to @{run}/(whatever program is managing it)/resolv.conf.
|
||||
@{run}/{resolvconf,NetworkManager,systemd/resolve,connman,netconfig}/resolv.conf r,
|
||||
@{run}/{NetworkManager,connman,netconfig}/resolv.conf r,
|
||||
@{etc_ro}/resolvconf/run/resolv.conf r,
|
||||
@{run}/systemd/resolve/stub-resolv.conf r,
|
||||
/mnt/wsl/resolv.conf r,
|
||||
|
||||
@{etc_ro}/samba/lmhosts r,
|
||||
@{etc_ro}/services r,
|
||||
# db backend
|
||||
/var/lib/misc/*.db r,
|
||||
# The Name Service Cache Daemon can cache lookups, sometimes leading
|
||||
@@ -60,13 +40,19 @@
|
||||
/{var/db,var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts} r,
|
||||
# nscd renames and unlinks files in it's operation that clients will
|
||||
# have open
|
||||
@{run}/nscd/db* rmix,
|
||||
@{run}/nscd/db* mix,
|
||||
|
||||
# make libnss-libvirt name resolution work.
|
||||
/var/lib/libvirt/dnsmasq/* r,
|
||||
|
||||
# make libnss-libvirt name resolution work.
|
||||
/var/lib/libvirt/dnsmasq/ r,
|
||||
/var/lib/libvirt/dnsmasq/*.status r,
|
||||
|
||||
# The nss libraries are sometimes used in addition to PAM; make sure
|
||||
# they are available
|
||||
/{usr/,}lib{,32,64}/libnss_*.so* mr,
|
||||
/{usr/,}lib/@{multiarch}/libnss_*.so* mr,
|
||||
@{etc_ro}/default/nss r,
|
||||
|
||||
# avahi-daemon is used for mdns4 resolution
|
||||
@{run}/avahi-daemon/socket rw,
|
||||
@@ -93,9 +79,6 @@
|
||||
# kerberos
|
||||
include <abstractions/kerberosclient>
|
||||
|
||||
#libnss-systemd
|
||||
include <abstractions/nss-systemd>
|
||||
|
||||
# Also allow lookups for systemd-exec's DynamicUsers via D-Bus
|
||||
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
dbus send
|
||||
|
40
profiles/apparmor.d/abstractions/nameservice-strict
Normal file
40
profiles/apparmor.d/abstractions/nameservice-strict
Normal file
@@ -0,0 +1,40 @@
|
||||
# apparmor.d - Full set of apparmor profiles
|
||||
# Copyright (C) 2019-2022 Mikhail Morfikov
|
||||
# Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Many programs wish to perform nameservice-like operations, such as looking up
|
||||
# users by name or id, groups by name or id, hosts by name or IP, etc.
|
||||
|
||||
abi <abi/4.0>,
|
||||
|
||||
include <abstractions/nss-systemd>
|
||||
|
||||
@{etc_ro}/default/nss r,
|
||||
@{etc_ro}/gai.conf r,
|
||||
@{etc_ro}/group r,
|
||||
@{etc_ro}/host.conf r,
|
||||
@{etc_ro}/hosts r,
|
||||
@{etc_ro}/nsswitch.conf r,
|
||||
@{etc_ro}/passwd r,
|
||||
@{etc_ro}/protocols r,
|
||||
@{etc_ro}/resolv.conf r,
|
||||
@{etc_ro}/services r,
|
||||
|
||||
# On systems with authselect installed, /etc/nsswitch.conf is a symlink to /etc/authselect/nsswitch.conf
|
||||
@{etc_ro}/authselect/nsswitch.conf r,
|
||||
|
||||
# Alternative location for group & passwd files
|
||||
/var/lib/extrausers/group r,
|
||||
/var/lib/extrausers/passwd r,
|
||||
/var/lib/nscd/group r,
|
||||
/var/lib/nscd/passwd r,
|
||||
|
||||
@{run}/nscd/db* r,
|
||||
@{run}/resolvconf/resolv.conf r,
|
||||
@{run}/systemd/resolve/resolv.conf r,
|
||||
@{run}/systemd/resolve/stub-resolv.conf r,
|
||||
|
||||
include if exists <abstractions/nameservice-strict.d>
|
||||
|
||||
# vim:syntax=apparmor
|
@@ -13,25 +13,25 @@
|
||||
abi <abi/4.0>,
|
||||
|
||||
# shared snippets for config files
|
||||
/etc/php{,5,7,8}/** r,
|
||||
/etc/php{,5,7,8,-legacy}/** r,
|
||||
|
||||
# Xlibs
|
||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||
# php extensions
|
||||
/usr/lib{64,}/php{,5,7,8}/*/*.so mr,
|
||||
/usr/lib{64,}/php{,5,7,8,-legacy}/*/*.so mr,
|
||||
|
||||
# ICU (unicode support) data tables
|
||||
/usr/share/icu/*/*.dat r,
|
||||
|
||||
# php session mmap socket
|
||||
/var/lib/php{,5,7,8}/session_mm_* rwlk,
|
||||
/var/lib/php{,5,7,8,-legacy}/session_mm_* rwlk,
|
||||
# file based session handler
|
||||
/var/lib/php{,5,7,8}/sess_* rwlk,
|
||||
/var/lib/php{,5,7,8}/sessions/* rwlk,
|
||||
/var/lib/php{,5,7,8,-legacy}/sess_* rwlk,
|
||||
/var/lib/php{,5,7,8,-legacy}/sessions/* rwlk,
|
||||
|
||||
# php libraries
|
||||
/usr/share/php{,5,7,8}/ r,
|
||||
/usr/share/php{,5,7,8}/** mr,
|
||||
/usr/share/php{,5,7,8,-legacy}/ r,
|
||||
/usr/share/php{,5,7,8,-legacy}/** mr,
|
||||
|
||||
# MySQL extension
|
||||
/usr/share/mysql/** r,
|
||||
|
@@ -45,5 +45,10 @@
|
||||
owner @{HOME}/.local/lib/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
|
||||
owner @{HOME}/.local/lib/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/**/ r,
|
||||
|
||||
# Starting with Python 3.8, you can use the PYTHONPYCACHEPREFIX environment
|
||||
# variable to define a cache directory for Python.
|
||||
owner @{HOME}/.cache/Python/ rw,
|
||||
owner @{HOME}/.cache/Python/** rw,
|
||||
|
||||
# Include additions to the abstraction
|
||||
include if exists <abstractions/python.d>
|
||||
|
@@ -24,6 +24,7 @@ profile ping /{usr/,}bin/{,iputils-}ping {
|
||||
|
||||
/{,usr/}bin/{,iputils-}ping mixr,
|
||||
/etc/modules.conf r,
|
||||
@{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/bin.ping>
|
||||
|
@@ -4,7 +4,7 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
|
||||
profile php-fpm /usr/{bin,sbin}/php-fpm* flags=(attach_disconnected) {
|
||||
# load common libraries and their support files
|
||||
include <abstractions/base>
|
||||
# resolve hostnames/usernames
|
||||
@@ -32,15 +32,15 @@ profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
|
||||
/var/log/php*-fpm.log rw,
|
||||
|
||||
# we need to be able to create all sockets
|
||||
@{run}/php{,-fpm}/php*-fpm.pid rw,
|
||||
@{run}/php{,-fpm,-fpm-legacy}/php*-fpm.pid rw,
|
||||
@{run}/php*-fpm.pid rw,
|
||||
@{run}/php{,-fpm}/php*-fpm.sock rwlk,
|
||||
@{run}/php{,-fpm,-fpm-legacy}/*.sock{,et} rwlk,
|
||||
|
||||
# LP: #2061113
|
||||
owner @{run}/systemd/notify w,
|
||||
|
||||
# to reload
|
||||
/usr/sbin/php-fpm* rix,
|
||||
/usr/{bin,sbin}/php-fpm* rix,
|
||||
|
||||
# no idea why php tries to open / read/write
|
||||
deny / rw,
|
||||
|
@@ -7,6 +7,10 @@ include <tunables/global>
|
||||
profile slirp4netns /usr/bin/slirp4netns flags=(unconfined) {
|
||||
userns,
|
||||
|
||||
# pivot_root is required for running `slirp4netns --enable-sandbox` inside LXD.
|
||||
# https://github.com/rootless-containers/slirp4netns/issues/348
|
||||
pivot_root,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/slirp4netns>
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain) {
|
||||
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain,attach_disconnected) {
|
||||
# Don't use abstractions/transmission-common here, as the
|
||||
# access needed is narrower than the user applications
|
||||
include <abstractions/base>
|
||||
@@ -47,7 +47,7 @@ profile transmission-cli /usr/bin/transmission-cli flags=(complain) {
|
||||
include if exists <local/transmission-cli>
|
||||
}
|
||||
|
||||
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain) {
|
||||
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain,attach_disconnected) {
|
||||
include <abstractions/transmission-common>
|
||||
include <abstractions/dbus-session-strict>
|
||||
include <abstractions/dconf>
|
||||
|
@@ -45,6 +45,7 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
|
||||
/etc/SuSE-release r,
|
||||
@{PROC}/@{pid}/mounts r,
|
||||
@{PROC}/sys/fs/suid_dumpable r,
|
||||
@{PROC}/sys/kernel/core_pattern r,
|
||||
/usr/bin/doveconf rix,
|
||||
/usr/lib*/dovecot/anvil mrPx,
|
||||
/usr/lib*/dovecot/auth mrPx,
|
||||
|
@@ -13,6 +13,7 @@ profile smbd /usr/{bin,sbin}/smbd {
|
||||
include <abstractions/wutmp>
|
||||
|
||||
capability audit_write,
|
||||
capability chown,
|
||||
capability dac_override,
|
||||
capability dac_read_search,
|
||||
capability fowner,
|
||||
|
@@ -17,6 +17,8 @@ profile zgrep /usr/bin/{x,}zgrep {
|
||||
include <abstractions/bash>
|
||||
|
||||
/dev/tty rw,
|
||||
@{etc_ro}/nsswitch.conf r,
|
||||
/etc/passwd r,
|
||||
/usr/bin/{ba,da,}sh ix,
|
||||
/usr/bin/bzip2 Cx -> helper,
|
||||
/usr/bin/cat ix,
|
||||
@@ -35,6 +37,9 @@ profile zgrep /usr/bin/{x,}zgrep {
|
||||
owner /tmp/zgrep* rw,
|
||||
/usr/bin/zgrep r,
|
||||
|
||||
deny /etc/nsswitch.conf r,
|
||||
deny /etc/passwd r,
|
||||
|
||||
include if exists <local/zgrep>
|
||||
|
||||
profile helper {
|
||||
|
@@ -1,17 +1,12 @@
|
||||
# This profile allows almost everything and only exists to allow
|
||||
# bwrap to work on a system with user namespace restrictions
|
||||
# being enforced.
|
||||
# bwrap is allowed access to user namespaces and capabilities
|
||||
# within the user namespace, but its children do not have
|
||||
# capabilities, blocking bwrap from being able to be used to
|
||||
# arbitrarily by-pass the user namespace restrictions.
|
||||
#
|
||||
# Note: the bwrap child is stacked against the bwrap profile due to
|
||||
# bwraps use of no-new-privs
|
||||
# This profile allows almost everything and only exists to allow bwrap
|
||||
# to work on a system with user namespace restrictions being enforced.
|
||||
# bwrap is allowed access to user namespaces and capabilities within
|
||||
# the user namespace, but its children do not have capabilities,
|
||||
# blocking bwrap from being able to be used to arbitrarily by-pass the
|
||||
# user namespace restrictions.
|
||||
|
||||
# disabled by default as it can break some use cases on a system that
|
||||
# doesn't have or has disable user namespace restrictions for unconfined
|
||||
# use aa-enforce to enable it
|
||||
# Note: the bwrap child is stacked against the bwrap profile due to
|
||||
# bwraps use of no-new-privs.
|
||||
|
||||
abi <abi/4.0>,
|
||||
|
||||
@@ -19,9 +14,11 @@ include <tunables/global>
|
||||
|
||||
profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||
allow capability,
|
||||
# not allow all, to allow for pix stack
|
||||
# sadly we have to allow m every where to allow children to work under
|
||||
# stacking.
|
||||
# not allow all, to allow for pix stack on systems that don't support
|
||||
# rule priority.
|
||||
#
|
||||
# sadly we have to allow 'm' every where to allow children to work under
|
||||
# profile stacking atm.
|
||||
allow file rwlkm /{**,},
|
||||
allow network,
|
||||
allow unix,
|
||||
@@ -34,7 +31,23 @@ profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||
allow umount,
|
||||
allow pivot_root,
|
||||
allow dbus,
|
||||
allow px /** -> bwrap//&unpriv_bwrap,
|
||||
|
||||
# stacked like this due to no-new-privs restriction
|
||||
# this will stack a target profile against bwrap and unpriv_bwrap
|
||||
# Ideally
|
||||
# - there would be a transition at userns creation first. This would allow
|
||||
# for the bwrap profile to be tighter, and looser within the user
|
||||
# ns. bwrap will still have to fairly loose until a transition at
|
||||
# namespacing in general (not just user ns) is available.
|
||||
# - there would be an independent second target as fallback
|
||||
# This would allow for select target profiles to be used, and not
|
||||
# necessarily stack the unpriv_bwrap in cases where this is desired
|
||||
#
|
||||
# the ix works here because stack will apply to ix fallback
|
||||
# Ideally we would sanitize the environment across a privilege boundry
|
||||
# (leaving bwarp into application) but flatpak etc use environment glibc
|
||||
# sanitized environment variables as part of the sandbox setup.
|
||||
allow pix /** -> &bwrap//&unpriv_bwrap,
|
||||
|
||||
# the local include should not be used without understanding the userns
|
||||
# restriction.
|
||||
@@ -42,6 +55,7 @@ profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||
include if exists <local/bwrap-userns-restrict>
|
||||
}
|
||||
|
||||
# The unpriv_bwrap profile is used to strip capabilities within the userns
|
||||
profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||
# not allow all, to allow for pix stack
|
||||
allow file rwlkm /{**,},
|
||||
@@ -57,6 +71,9 @@ profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||
allow pivot_root,
|
||||
allow dbus,
|
||||
|
||||
# bwrap profile does stacking against itself this will keep the target
|
||||
# profile from having elevated privileges in the container.
|
||||
# If done recursively the stack will remove any duplicate
|
||||
allow pix /** -> &unpriv_bwrap,
|
||||
|
||||
audit deny capability,
|
||||
|
@@ -13,12 +13,12 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-anvil /usr/lib/postfix/{bin/,sbin/,}anvil {
|
||||
profile postfix-anvil /usr/lib{,exec}/postfix/{bin/,sbin/,}anvil {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}anvil mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}anvil mrix,
|
||||
|
||||
/etc/postfix/main.cf r,
|
||||
/{var/spool/postfix/,}private/anvil rw,
|
||||
|
@@ -14,12 +14,12 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-bounce /usr/lib/postfix/{bin/,sbin/,}bounce {
|
||||
profile postfix-bounce /usr/lib{,exec}/postfix/{bin/,sbin/,}bounce {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}bounce mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}bounce mrix,
|
||||
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwkl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-cleanup /usr/lib/postfix/{bin/,sbin/,}cleanup {
|
||||
profile postfix-cleanup /usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
@@ -22,7 +22,7 @@ profile postfix-cleanup /usr/lib/postfix/{bin/,sbin/,}cleanup {
|
||||
capability net_bind_service,
|
||||
capability dac_read_search,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}cleanup mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup mrix,
|
||||
|
||||
/{var/spool/postfix/,}incoming/[0-9]*.[0-9]* rwl,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
|
@@ -14,10 +14,10 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-discard /usr/lib/postfix/{bin/,sbin/,}discard {
|
||||
profile postfix-discard /usr/lib{,exec}/postfix/{bin/,sbin/,}discard {
|
||||
include <abstractions/base>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}discard mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}discard mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-discard>
|
||||
|
@@ -13,10 +13,10 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-dnsblog /usr/lib/postfix/{bin/,sbin/,}dnsblog {
|
||||
profile postfix-dnsblog /usr/lib{,exec}/postfix/{bin/,sbin/,}dnsblog {
|
||||
include <abstractions/base>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}dnsblog mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}dnsblog mrix,
|
||||
|
||||
/var/spool/postfix/private/dnsblog rw,
|
||||
|
||||
|
@@ -14,12 +14,12 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-error /usr/lib/postfix/{bin/,sbin/,}error {
|
||||
profile postfix-error /usr/lib{,exec}/postfix/{bin/,sbin/,}error {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}error mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}error mrix,
|
||||
|
||||
owner /var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/pid/unix.error rwk,
|
||||
|
@@ -14,12 +14,12 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
|
||||
profile postfix-flush /usr/lib{,exec}/postfix/{bin/,sbin/,}flush {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}flush mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}flush mrix,
|
||||
|
||||
/{var/spool/postfix/,}deferred/ r,
|
||||
/{var/spool/postfix/,}deferred/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
|
@@ -14,12 +14,12 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-lmtp /usr/lib/postfix/{bin/,sbin/,}lmtp {
|
||||
profile postfix-lmtp /usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}lmtp mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp mrix,
|
||||
|
||||
/var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/pid/unix.lmtp rwk,
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
|
||||
profile postfix-local /usr/lib{,exec}/postfix/{bin/,sbin/,}local {
|
||||
include <abstractions/base>
|
||||
include <abstractions/bash>
|
||||
include <abstractions/nameservice>
|
||||
@@ -27,7 +27,7 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
|
||||
/var/mailman/mail/wrapper Px,
|
||||
/usr/bin/mlmmj-recieve Px,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}local mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}local mrix,
|
||||
/{usr/,}bin/bash mixr,
|
||||
/{usr/,}bin/date mixr,
|
||||
|
||||
|
@@ -14,7 +14,7 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-master /usr/lib/postfix/{bin/,sbin/,}master {
|
||||
profile postfix-master /usr/lib{,exec}/postfix/{bin/,sbin/,}master {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
@@ -37,25 +37,28 @@ profile postfix-master /usr/lib/postfix/{bin/,sbin/,}master {
|
||||
/{var/spool/postfix/,}private/tlsmgr rwl,
|
||||
/{var/spool/postfix/,}public/{cleanup,flush,pickup,postlog,qmgr,showq,tlsmgr} rwl,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}anvil Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}bounce Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}cleanup Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}error Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}flush Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}local Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}lmtp mrPx,
|
||||
/usr/lib/postfix/{bin/,sbin/,}master mrix,
|
||||
/usr/lib/postfix/{bin/,sbin/,}nqmgr Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}proxymap Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}pickup Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}pipe Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}qmgr Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}scache Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}smtp Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}smtpd Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}tlsmgr Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}trivial-rewrite Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}anvil Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}bounce Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}cleanup Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}error Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}flush Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}local Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}lmtp mrPx,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}master mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}pickup Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}pipe Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}postfix-tlsproxy Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}scache Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtp Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}spawn Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite Px,
|
||||
|
||||
owner /var/lib/postfix/master.lock rwk,
|
||||
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-nqmgr /usr/lib/postfix/{bin/,sbin/,}nqmgr {
|
||||
profile postfix-nqmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}nqmgr mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}nqmgr mrix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/ r,
|
||||
|
@@ -14,12 +14,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-oqmgr /usr/lib/postfix/{bin/,sbin/,}oqmgr {
|
||||
profile postfix-oqmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}oqmgr {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}oqmgr mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}oqmgr mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-oqmgr>
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-pickup /usr/lib/postfix/{bin/,sbin/,}pickup {
|
||||
profile postfix-pickup /usr/lib{,exec}/postfix/{bin/,sbin/,}pickup {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}pickup mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}pickup mrix,
|
||||
|
||||
/{var/spool/postfix/,}public/cleanup rw,
|
||||
/{var/spool/postfix/,}public/pickup r,
|
||||
|
@@ -14,12 +14,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-pipe /usr/lib/postfix/{bin/,sbin/,}pipe {
|
||||
profile postfix-pipe /usr/lib{,exec}/postfix/{bin/,sbin/,}pipe {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}pipe mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}pipe mrix,
|
||||
|
||||
/var/spool/postfix/active/* rwk,
|
||||
/var/spool/postfix/private/bounce w,
|
||||
|
@@ -12,10 +12,13 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-postscreen /usr/lib/postfix/{bin/,sbin/,}postscreen {
|
||||
profile postfix-postscreen /usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}postscreen mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}postscreen mrix,
|
||||
owner /var/lib/postfix/{,__db.}postscreen_cache.db rwk,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-postscreen>
|
||||
|
@@ -14,14 +14,14 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-proxymap /usr/lib/postfix/{bin/,sbin/,}proxymap {
|
||||
profile postfix-proxymap /usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/etc/my.cnf r,
|
||||
/usr/lib/postfix/{bin/,sbin/,}proxymap mrix,
|
||||
/{var/spool/postfix/,}private/proxymap rw,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}proxymap mrix,
|
||||
/{var/spool/postfix/,}private/proxymap rw,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-proxymap>
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-qmgr /usr/lib/postfix/{bin/,sbin/,}qmgr {
|
||||
profile postfix-qmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}qmgr mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmgr mrix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-qmqpd /usr/lib/postfix/{bin/,sbin/,}qmqpd {
|
||||
profile postfix-qmqpd /usr/lib{,exec}/postfix/{bin/,sbin/,}qmqpd {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}qmqpd mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}qmqpd mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-qmqpd>
|
||||
|
@@ -15,12 +15,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-scache /usr/lib/postfix/{bin/,sbin/,}scache {
|
||||
profile postfix-scache /usr/lib{,exec}/postfix/{bin/,sbin/,}scache {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}scache mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}scache mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-scache>
|
||||
|
@@ -14,12 +14,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
|
||||
profile postfix-showq /usr/lib{,exec}/postfix/{bin/,sbin/,}showq {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}showq mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq mrix,
|
||||
|
||||
/{var/spool/postfix/,}active/ r,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* r,
|
||||
@@ -38,6 +38,7 @@ profile postfix-showq /usr/lib/postfix/{bin/,sbin/,}showq {
|
||||
/{var/spool/postfix/,}hold/[0-9A-F]/[0-9A-F]/* r,
|
||||
/{var/spool/postfix/,}hold/[0-9A-F]/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}hold/[0-9A-F]/ r,
|
||||
/{var/spool/postfix/,}hold/[0-9A-F]* r,
|
||||
/{var/spool/postfix/,}incoming/ r,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/* r,
|
||||
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ r,
|
||||
|
@@ -14,7 +14,7 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
||||
profile postfix-smtp /usr/lib{,exec}/postfix/{bin/,sbin/,}smtp {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
@@ -23,7 +23,7 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
||||
capability dac_read_search,
|
||||
capability net_bind_service,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}smtp mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtp mrix,
|
||||
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rwl,
|
||||
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rwl,
|
||||
@@ -39,7 +39,7 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
||||
/{var/spool/postfix/,}private/trace w,
|
||||
/{var/spool/postfix/,}public/flush w,
|
||||
/{var/spool/postfix/,}pid/unix.smtp rwk,
|
||||
/{var/spool/postfix/,}pid/unix.relay rw,
|
||||
/{var/spool/postfix/,}pid/unix.relay rwk,
|
||||
/etc/postfix/{ssl/,}*.pem r,
|
||||
/etc/postfix/prng_exch rw,
|
||||
/usr/share/ssl/certs/ca-bundle.crt r,
|
||||
|
@@ -14,7 +14,7 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
|
||||
profile postfix-smtpd /usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
@@ -24,7 +24,7 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
|
||||
capability dac_override,
|
||||
capability dac_read_search,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}smtpd mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd mrix,
|
||||
/usr/sbin/postdrop rPx,
|
||||
|
||||
/dev/urandom r,
|
||||
@@ -44,6 +44,7 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
|
||||
|
||||
/{var/spool/postfix/,}incoming/* rw,
|
||||
/{var/spool/postfix/,}pid/inet.* rwk,
|
||||
/{var/spool/postfix/,}pid/pass.smtpd rwk,
|
||||
/{var/spool/postfix/,}private/anvil rw,
|
||||
/{var/spool/postfix/,}private/proxymap rw,
|
||||
/{var/spool/postfix/,}private/rewrite rw,
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-spawn /usr/lib/postfix/{bin/,sbin/,}spawn {
|
||||
profile postfix-spawn /usr/lib{,exec}/postfix/{bin/,sbin/,}spawn {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}spawn mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}spawn mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-spawn>
|
||||
|
@@ -14,12 +14,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
|
||||
profile postfix-tlsmgr /usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsmgr mrix,
|
||||
|
||||
/var/spool/postfix/dev/urandom r,
|
||||
/{etc,var/lib}/postfix/prng_exch rwk,
|
||||
|
27
profiles/apparmor/profiles/extras/postfix-tlsproxy
Normal file
27
profiles/apparmor/profiles/extras/postfix-tlsproxy
Normal file
@@ -0,0 +1,27 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2024 pyllyukko
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-tlsproxy /usr/lib{,exec}/postfix/{bin/,sbin/,}tlsproxy {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
include <abstractions/ssl_keys>
|
||||
|
||||
capability dac_read_search,
|
||||
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}tlsproxy mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-tlsproxy>
|
||||
}
|
@@ -14,14 +14,14 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-trivial-rewrite /usr/lib/postfix/{bin/,sbin/,}trivial-rewrite {
|
||||
profile postfix-trivial-rewrite /usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
capability dac_read_search,
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}trivial-rewrite mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}trivial-rewrite mrix,
|
||||
|
||||
/etc/{m,fs}tab r,
|
||||
/var/spool/postfix/pid/unix.rewrite rw,
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-verify /usr/lib/postfix/{bin/,sbin/,}verify {
|
||||
profile postfix-verify /usr/lib{,exec}/postfix/{bin/,sbin/,}verify {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}verify mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}verify mrix,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/postfix-verify>
|
||||
|
@@ -13,12 +13,12 @@ abi <abi/4.0>,
|
||||
|
||||
include <tunables/global>
|
||||
|
||||
profile postfix-virtual /usr/lib/postfix/{bin/,sbin/,}virtual {
|
||||
profile postfix-virtual /usr/lib{,exec}/postfix/{bin/,sbin/,}virtual {
|
||||
include <abstractions/base>
|
||||
include <abstractions/nameservice>
|
||||
include <abstractions/postfix-common>
|
||||
|
||||
/usr/lib/postfix/{bin/,sbin/,}virtual mrix,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}virtual mrix,
|
||||
|
||||
/var/spool/postfix/active/* rw,
|
||||
/var/spool/postfix/pid/unix.virtual rw,
|
||||
|
@@ -23,28 +23,28 @@ include <tunables/global>
|
||||
/{usr/,}bin/cat ix,
|
||||
|
||||
/usr/bin/foomatic-rip ixr,
|
||||
/etc/foomatic/** r,
|
||||
@{etc_ro}/foomatic/** r,
|
||||
|
||||
/usr/bin/gs ix,
|
||||
/usr/lib/ghostscript/** m,
|
||||
/usr/lib64/ghostscript/** m,
|
||||
/usr/share/ghostscript/** r,
|
||||
/etc/ghostscript/** r,
|
||||
@{etc_ro}/ghostscript/** r,
|
||||
|
||||
/dev/lp0 rw,
|
||||
/dev/tty rw,
|
||||
/dev/ttyS? w,
|
||||
/etc/cups rw,
|
||||
/etc/cups/ r,
|
||||
/etc/cups/** r,
|
||||
/etc/cups/certs w,
|
||||
/etc/cups/certs/* w,
|
||||
/etc/cups/*.conf* rw,
|
||||
/etc/cups/ppd rw,
|
||||
/etc/printcap rw,
|
||||
/etc/cups/printcap rw,
|
||||
/etc/cups/ssl rw,
|
||||
/etc/cups/yes/* rw,
|
||||
@{etc_rw}/cups rw,
|
||||
@{etc_rw}/cups/ r,
|
||||
@{etc_rw}/cups/** r,
|
||||
@{etc_rw}/cups/certs w,
|
||||
@{etc_rw}/cups/certs/* w,
|
||||
@{etc_rw}/cups/*.conf* rw,
|
||||
@{etc_rw}/cups/ppd rw,
|
||||
@{etc_rw}/printcap rw,
|
||||
@{etc_rw}/cups/printcap rw,
|
||||
@{etc_rw}/cups/ssl rw,
|
||||
@{etc_rw}/cups/yes/* rw,
|
||||
@{PROC}/meminfo r,
|
||||
@{PROC}/sys/dev/parport/** r,
|
||||
/sys/class/usb r,
|
||||
@@ -65,6 +65,8 @@ include <tunables/global>
|
||||
/var/cache/cups/ rw,
|
||||
/var/cache/cups/** rw,
|
||||
|
||||
@{etc_ro}/paperspecs r,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
include if exists <local/usr.sbin.cupsd>
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ include <tunables/global>
|
||||
|
||||
/etc/postfix r,
|
||||
/usr/sbin/postqueue rmix,
|
||||
/usr/lib/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/share/icu/[0-9]*.[0-9]*/*.dat r,
|
||||
/var/spool/postfix r,
|
||||
/var/spool/postfix/maildrop r,
|
||||
|
@@ -46,10 +46,10 @@ include <tunables/global>
|
||||
/root/dead.letter w,
|
||||
/root/.forward rw,
|
||||
/usr/kerberos/lib/lib*.so* mr,
|
||||
/usr/lib/postfix/{bin/,sbin/,}master Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}smtpd Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}master Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}smtpd Px,
|
||||
/usr/lib/postfix r,
|
||||
/usr/lib/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib/sasl2 r,
|
||||
/usr/lib/sasl2/* mr,
|
||||
/usr/lib/sasl r,
|
||||
|
@@ -28,8 +28,8 @@ include <tunables/global>
|
||||
/etc/postfix/postfix-script Px,
|
||||
@{PROC}/net/if_inet6 r,
|
||||
/usr/lib/postfix r,
|
||||
/usr/lib/postfix/{bin/,sbin/,}master Px,
|
||||
/usr/lib/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}master Px,
|
||||
/usr/lib{,exec}/postfix/{bin/,sbin/,}showq Px,
|
||||
/usr/sbin/postalias Px,
|
||||
/usr/sbin/postdrop Px,
|
||||
/usr/sbin/postqueue Px,
|
||||
|
29
run-spread.sh
Executable file
29
run-spread.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
# Run integration tests with spread sequentially on all the systems, using
|
||||
# multiple workers per system. This mode is suitable to run on a single
|
||||
# quad-core CPU with 8GB of RAM and no desktop session.
|
||||
set -xeu
|
||||
|
||||
if test -z "$(command -v spread)"; then
|
||||
echo "You need to install spread from https://github.com/snapcore/spread with the Go compiler and the command: go install github.com/snapcore/spread/cmd/spread@latest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$(command -v image-garden)"; then
|
||||
echo "You need to install image-garden from https://gitlab.com/zygoon/image-garden: make install prefix=/usr/local" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf spread-logs spread-artifacts
|
||||
mkdir -p spread-logs
|
||||
for system in \
|
||||
opensuse-cloud-tumbleweed \
|
||||
debian-cloud-12 \
|
||||
debian-cloud-13 \
|
||||
ubuntu-cloud-22.04 \
|
||||
ubuntu-cloud-24.04 \
|
||||
ubuntu-cloud-24.10; do
|
||||
if ! spread -artifacts ./spread-artifacts -v "$system" | tee spread-logs/"$system".log; then
|
||||
echo "Spread exited with code $?" >spread-logs/"$system".failed
|
||||
fi
|
||||
done
|
171
spread.yaml
Normal file
171
spread.yaml
Normal file
@@ -0,0 +1,171 @@
|
||||
project: apparmor
|
||||
backends:
|
||||
garden:
|
||||
# The garden backend relies on https://gitlab.com/zygoon/image-garden
|
||||
# TODO: Switch to a released version for better stability.
|
||||
type: adhoc
|
||||
allocate: |
|
||||
# Use just enough RAM to link the parser on a virtual system with
|
||||
# two cores. Using more cores may easily consume more memory, due
|
||||
# to make -j$(nproc), used below than a small CI/CD system is
|
||||
# typically granted. It is better to have more workers than to
|
||||
# have one big worker with lots of resources.
|
||||
export QEMU_MEM_OPTION="-m 1536"
|
||||
export QEMU_SMP_OPTION="-smp 2"
|
||||
ARCH="$(uname -m)"
|
||||
# If a locally built kernel image exist then use it for booting.
|
||||
# Care needs to be taken to make sure the kernel is compatible with
|
||||
# loadable modules present in the file system.
|
||||
if [ -f bzImage ]; then
|
||||
# Create the qcow2/run files before setting custom kernel
|
||||
# options, so that first boot and initialization happen in a
|
||||
# standardized manner.
|
||||
image-garden make "$SPREAD_SYSTEM"."$ARCH".run "$SPREAD_SYSTEM"."$ARCH".qcow2 1>&2
|
||||
# Pass a simple drive instead of the more elaborate virtio
|
||||
# configuration that is used by default. Some images may not
|
||||
# support virtio enough for booting.
|
||||
export QEMU_STORAGE_OPTION="-drive file=$SPREAD_SYSTEM.$ARCH.qcow2,format=qcow2"
|
||||
# Refrain from passing EFI firmware to qemu so that we boot a
|
||||
# kernel directly and bypass both EFI and BIOS.
|
||||
export QEMU_BOOT_FIRMWARE_OPTION=""
|
||||
# Pass the kernel and cmdline by hand. At present this is tuned
|
||||
# to the Ubuntu cloud images that have the rootfs as the first
|
||||
# partition.
|
||||
exec image-garden allocate "$SPREAD_SYSTEM"."$ARCH" \
|
||||
-kernel bzImage \
|
||||
-append 'root=/dev/sda1 ro console=tty1 console=ttyS0'
|
||||
fi
|
||||
# Ask image garden to allocate the system and relay the result back
|
||||
# to spread as either success of failure.
|
||||
exec image-garden allocate "$SPREAD_SYSTEM"."$ARCH"
|
||||
discard: image-garden discard "$SPREAD_SYSTEM_ADDRESS"
|
||||
systems:
|
||||
# All systems except for the one Ubuntu system are marked as
|
||||
# manual. This way we don't accidentally spin up everything when
|
||||
# someone runs spread without knowing better.
|
||||
- opensuse-cloud-tumbleweed:
|
||||
username: opensuse
|
||||
password: opensuse
|
||||
workers: 4
|
||||
manual: true
|
||||
- debian-cloud-12:
|
||||
username: debian
|
||||
password: debian
|
||||
workers: 4
|
||||
manual: true
|
||||
- debian-cloud-13:
|
||||
username: debian
|
||||
password: debian
|
||||
workers: 4
|
||||
manual: true
|
||||
- ubuntu-cloud-22.04:
|
||||
username: ubuntu
|
||||
password: ubuntu
|
||||
workers: 4
|
||||
manual: true
|
||||
- ubuntu-cloud-24.04:
|
||||
username: ubuntu
|
||||
password: ubuntu
|
||||
workers: 4
|
||||
manual: true
|
||||
- ubuntu-cloud-24.10:
|
||||
username: ubuntu
|
||||
password: ubuntu
|
||||
workers: 4
|
||||
|
||||
exclude:
|
||||
- .git
|
||||
- "*.o"
|
||||
# Files related to spread and image-garden.
|
||||
- "*.qcow2"
|
||||
- "*.iso"
|
||||
- "*.img"
|
||||
- "*.log"
|
||||
- "*.run"
|
||||
- "*.lock"
|
||||
- spread-logs
|
||||
- spread-artifacts
|
||||
# Locally provided kernel image. See allocate section in system backends,
|
||||
# this image, if present, is passed directly to qemu.
|
||||
- bzImage
|
||||
|
||||
# Copy the project to this path on the test system.
|
||||
# This is also available as $SPREAD_PATH.
|
||||
path: /tmp/apparmor
|
||||
|
||||
prepare: |
|
||||
# Configure libapparmor but only if a makefile is not already present.
|
||||
# This makes repeated iteration with -reuse much faster, as the chain of
|
||||
# invocations of make below are efficient if nothing needs to be done.
|
||||
if [ ! -f "$SPREAD_PATH"/libraries/libapparmor/Makefile ]; then
|
||||
(
|
||||
cd $SPREAD_PATH/libraries/libapparmor
|
||||
sh ./autogen.sh && sh ./configure --prefix=/usr --with-perl --with-python
|
||||
)
|
||||
fi
|
||||
# Build libapparmor.
|
||||
make -C $SPREAD_PATH/libraries/libapparmor -j"$(nproc)"
|
||||
# Build apparmor_parser.
|
||||
make -C $SPREAD_PATH/parser -j"$(nproc)"
|
||||
# Build binary utilities (aa-exec and firends).
|
||||
make -C $SPREAD_PATH/binutils -j"$(nproc)"
|
||||
# Build python utilities.
|
||||
make -C $SPREAD_PATH/utils -j"$(nproc)"
|
||||
|
||||
# In case of failure, include the kernel version in the log.
|
||||
debug-each: |
|
||||
uname -a
|
||||
|
||||
suites:
|
||||
utils/:
|
||||
summary: Unit tests for the Python utilities.
|
||||
prepare: |
|
||||
# Generate apparmor profiles that the tests rely on.
|
||||
make -C "$SPREAD_PATH"/parser/tst gen_xtrans gen_dbus
|
||||
# Spread does not support programmatically generated test variants.
|
||||
# Ensure that the list baked into utils/test/task.yaml contains all
|
||||
# the files matching utils/test/test-*.py
|
||||
fail=0
|
||||
for V in $SPREAD_PATH/utils/test/test-*.py; do
|
||||
Vdash="$(basename "$V" | sed -e 's,^test-,,' -e 's,\.py$,,')"
|
||||
Vunder="$(basename "$V" | sed -e 's,^test-,,' -e 's,\.py$,,' -e 's,-,_,g')"
|
||||
if ! grep -xF ' TEST/'"$Vunder"': '"$Vdash" "$SPREAD_PATH"/utils/test/task.yaml; then
|
||||
echo "utils/test/task.yaml: missing test variant: TEST/$Vunder: $Vdash" >&2
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo "exiting due to missing variants listed above" >&2
|
||||
exit 1
|
||||
fi
|
||||
tests/unit/:
|
||||
summary: Unit tests that do not exercise the kernel layer.
|
||||
tests/regression/:
|
||||
summary: Regression tests for parser-kernel interaction.
|
||||
prepare: |
|
||||
# Spread does not support programmatically generated test variants.
|
||||
# Ensure that the list baked into tests/regression/apparmor/task.yaml
|
||||
# contains all the tests defined in tests/regression/apparmor/Makefile.
|
||||
echo '$(foreach t,$(TESTS),$(info TEST/$t))' | \
|
||||
make -n -f "$SPREAD_PATH"/tests/regression/apparmor/Makefile -f /dev/stdin | \
|
||||
grep -F TEST/ | \
|
||||
cut -d / -f 2 | \
|
||||
tee apparmor-regression-tests.txt
|
||||
fail=0
|
||||
while read -r V; do
|
||||
if ! grep -xF ' TEST/'"$V"': 1' "$SPREAD_PATH"/tests/regression/apparmor/task.yaml; then
|
||||
echo "tests/regression/task.yaml: missing test variant: TEST/$V" >&2
|
||||
fail=1
|
||||
fi
|
||||
done <apparmor-regression-tests.txt
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo "exiting due to missing variants listed above" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build all the apparmor regression test programs.
|
||||
make -C "$SPREAD_PATH"/tests/regression/apparmor -j"$(nproc)"
|
||||
restore: |
|
||||
rm -f apparmor-regression-tests.txt
|
||||
tests/snapd/:
|
||||
summary: Tests exercising a subset of behavior of snapd
|
@@ -27,7 +27,7 @@ manually, or build against in-tree libapparmor.${nl}\
|
||||
endif # LIBAPPARMOR not set
|
||||
LDLIBS += $(LIBAPPARMOR)
|
||||
|
||||
AA_EXEC = $(shell which aa-exec)
|
||||
AA_EXEC = $(shell command -v aa-exec)
|
||||
ifeq ($(AA_EXEC),)
|
||||
AA_EXEC_ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
@@ -67,6 +67,21 @@ system aa-exec by adding USE_SYSTEM=1 to your make command.${nl}\
|
||||
LDLIBS += -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
|
||||
endif # USE_SYSTEM
|
||||
|
||||
# the test suite is run as root but many of the tests restrict root
|
||||
# capabilities like dac_override and dac_readsearch so the test
|
||||
# suite needs recursive other rx perms from / on all dirs not owned by
|
||||
# root
|
||||
DIRCHECK_MESSAGE = $(shell ./check_dac_perms.sh)
|
||||
ifneq ($(strip $(DIRCHECK_MESSAGE)),)
|
||||
DIR_PERM_ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
The regression test suite at times is run as root but with restricted${nl}\
|
||||
capabilities. In these situations it needs to be able to still access${nl}\
|
||||
the test suite files.${nl}\
|
||||
${DIRCHECK_MESSAGE}${nl}\
|
||||
************************************************************************${nl})
|
||||
endif
|
||||
|
||||
SYSCTL_INCLUDE="\#include <sys/sysctl.h>"
|
||||
USE_SYSCTL:=$(shell echo $(SYSCTL_INCLUDE) | cpp -dM >/dev/null 2>/dev/null && echo true)
|
||||
|
||||
@@ -90,6 +105,7 @@ SRC=access.c \
|
||||
chmod.c \
|
||||
chown.c \
|
||||
clone.c \
|
||||
complain.c \
|
||||
coredump.c \
|
||||
deleted.c \
|
||||
environ.c \
|
||||
@@ -151,8 +167,7 @@ SRC=access.c \
|
||||
unlink.c \
|
||||
userns.c \
|
||||
userns_setns.c \
|
||||
xattrs.c \
|
||||
xattrs_profile.c
|
||||
xattrs.c
|
||||
|
||||
#only do the ioperm/iopl tests for x86 derived architectures
|
||||
ifneq (,$(findstring $(shell uname -i),i386 i486 i586 i686 x86 x86_64))
|
||||
@@ -165,6 +180,17 @@ ifeq ($(USE_SYSCTL),true)
|
||||
SRC+=syscall_sysctl.c
|
||||
endif
|
||||
|
||||
# Only do xattrs_profile test if we have the required setfattr binary
|
||||
ifneq (,$(shell command -v setfattr))
|
||||
SRC+=xattrs_profile.c
|
||||
else
|
||||
$(warning ${nl}\
|
||||
************************************************************************${nl}\
|
||||
No setfattr skipping xattrs_profile tests ...${nl}\
|
||||
Install attr or equivalent package to build and run this test${nl}\
|
||||
************************************************************************${nl})
|
||||
endif
|
||||
|
||||
#only do dbus if proper libs are installl
|
||||
ifneq (,$(shell pkg-config --exists dbus-1 && echo TRUE))
|
||||
SRC+=dbus_eavesdrop.c dbus_message.c dbus_service.c dbus_unrequested_reply.c
|
||||
@@ -232,6 +258,7 @@ TESTS=aa_exec \
|
||||
changehat_misc \
|
||||
chdir \
|
||||
clone \
|
||||
complain \
|
||||
coredump \
|
||||
deleted \
|
||||
e2e \
|
||||
@@ -240,6 +267,7 @@ TESTS=aa_exec \
|
||||
exec_qual \
|
||||
fchdir \
|
||||
fd_inheritance \
|
||||
file_unbindable_mount \
|
||||
fork \
|
||||
i18n \
|
||||
link \
|
||||
@@ -279,10 +307,14 @@ TESTS=aa_exec \
|
||||
unlink\
|
||||
userns\
|
||||
xattrs\
|
||||
xattrs_profile\
|
||||
longpath \
|
||||
nfs
|
||||
|
||||
# Only do xattrs_profile test if we have the required setfattr binary
|
||||
ifneq (,$(shell command -v setfattr))
|
||||
TESTS+=xattrs_profile
|
||||
endif
|
||||
|
||||
#only do dbus if proper libs are installl
|
||||
ifneq (,$(shell pkg-config --exists dbus-1 && echo TRUE))
|
||||
TESTS+=dbus_eavesdrop dbus_message dbus_service dbus_unrequested_reply
|
||||
@@ -304,6 +336,9 @@ libapparmor_check: ; $(LIBAPPARMOR_ERROR_MESSAGE)
|
||||
|
||||
aa_exec_check: ; $(AA_EXEC_ERROR_MESSAGE)
|
||||
|
||||
dirperm_check: ; $(DIR_PERM_ERROR_MESSAGE)
|
||||
|
||||
|
||||
all: libapparmor_check aa_exec_check $(EXEC) changehat.h uservars.inc
|
||||
|
||||
uservars.inc: uservars.inc.source uservars.inc.system
|
||||
@@ -401,7 +436,7 @@ build-dep:
|
||||
tests: RISKY_TESTS=
|
||||
tests: alltests
|
||||
|
||||
alltests: all
|
||||
alltests: all dirperm_check check_dac_perms.sh
|
||||
@if [ `whoami` = "root" ] ;\
|
||||
then \
|
||||
rc=0; \
|
||||
|
@@ -19,7 +19,7 @@ pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
ns=aa_exec_ns
|
||||
|
||||
@@ -31,18 +31,19 @@ genprofile_aa_exec()
|
||||
mode="(complain) "
|
||||
fi
|
||||
fi
|
||||
genprofile --stdin <<EOF
|
||||
genprofile image=$1 --stdin <<EOF
|
||||
$1 ${mode}{
|
||||
file,
|
||||
}
|
||||
|
||||
EOF
|
||||
genprofile --append image=:${ns}:${1} --stdin <<EOF
|
||||
:${ns}:${1} ${mode}{
|
||||
file,
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
settest aa_exec_profile ${bin}/aa_exec_wrapper.sh
|
||||
settest aa_exec_profile "${bin}/aa_exec_wrapper.sh"
|
||||
|
||||
genprofile_aa_exec "$test" 0
|
||||
runchecktest "unconfined" pass "$aa_exec" "unconfined"
|
||||
@@ -81,11 +82,12 @@ genprofile_aa_exec "$test" 0
|
||||
runchecktest "negative test: bad ns (--namespace=${ns}XXX)" fail "$aa_exec -n ${ns}XXX -p $test" "$test (enforce)"
|
||||
|
||||
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||
genprofile --stdin <<EOF
|
||||
genprofile image=$test --stdin <<EOF
|
||||
$test {
|
||||
all,
|
||||
}
|
||||
|
||||
EOF
|
||||
genprofile --append image=:${ns}:${test} --stdin <<EOF
|
||||
:${ns}:${test} {
|
||||
all,
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
# cacheloc is the top level directory of cache directories
|
||||
cacheloc="$tmpdir/cache"
|
||||
|
@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
file=$tmpdir/file
|
||||
|
||||
|
@@ -16,7 +16,7 @@ pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
settest transition
|
||||
at_secure=$pwd/at_secure
|
||||
|
@@ -17,7 +17,7 @@ pwd=`cd $pwd ; /bin/pwd`
|
||||
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
settest unix_fd_server
|
||||
disk_img=$tmpdir/disk_img
|
||||
@@ -28,7 +28,7 @@ file=$tmpdir/file
|
||||
socket=$tmpdir/unix_fd_test
|
||||
att_dis_client=$pwd/attach_disconnected
|
||||
|
||||
. $bin/mount.inc
|
||||
. "$bin/mount.inc"
|
||||
|
||||
attach_disconnected_cleanup() {
|
||||
if [ ! -z "$loop_device" ]; then
|
||||
|
@@ -27,7 +27,7 @@ pwd=`dirname $0`
|
||||
pwd=`cd $pwd ; /bin/pwd`
|
||||
bin=$pwd
|
||||
|
||||
. $bin/prologue.inc
|
||||
. "$bin/prologue.inc"
|
||||
|
||||
TESTS="syscall_ptrace syscall_sethostname \
|
||||
syscall_setdomainname syscall_setpriority syscall_setscheduler \
|
||||
@@ -139,18 +139,18 @@ for TEST in ${TESTS} ; do
|
||||
# okay, now check to see if the capability functions from within
|
||||
# a subprofile.
|
||||
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
|
||||
# ptrace between profiles confining tasks of same pid is controlled by the ptrace rule
|
||||
# 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}
|
||||
else
|
||||
runchecktest "${TEST} changehat -- no caps" fail $bin/${TEST} ${my_arg}
|
||||
runchecktest "${TEST} changehat -- no caps" fail "$bin/${TEST}" ${my_arg}
|
||||
fi
|
||||
|
||||
# all capabilities allowed
|
||||
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} cap:ALL ${my_entries}
|
||||
runchecktest "${TEST} changehat -- all caps" ${expected} $bin/${TEST} ${my_arg}
|
||||
genprofile "hat:$bin/${TEST}" "addimage:${bin}/${TEST}" cap:ALL ${my_entries}
|
||||
runchecktest "${TEST} changehat -- all caps" ${expected} "$bin/${TEST}" ${my_arg}
|
||||
|
||||
for cap in ${CAPABILITIES} ; do
|
||||
if [ ${expected} = "fail" ]; then
|
||||
@@ -162,8 +162,8 @@ for TEST in ${TESTS} ; do
|
||||
else
|
||||
expected_result=fail
|
||||
fi
|
||||
genprofile hat:$bin/${TEST} addimage:${bin}/${TEST} cap:${cap} ${my_entries}
|
||||
runchecktest "${TEST} changehat -- capability ${cap}" ${expected_result} $bin/${TEST} ${my_arg}
|
||||
genprofile "hat:$bin/${TEST}" "addimage:${bin}/${TEST}" cap:${cap} ${my_entries}
|
||||
runchecktest "${TEST} changehat -- capability ${cap}" ${expected_result} "$bin/${TEST}" ${my_arg}
|
||||
done
|
||||
|
||||
done
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user