1
Author: John Johansen <john.johansen@canonical.com>
3
Subject: Hack rework of the feature/match file support
7
This is not the cleanup this code needs, but a quick hack to add the
8
-M flag so we can specify a feature file (or directory) to use for
11
It mostly just moves around existing code and adds the -M option,
12
though it does introduce a few changes.
14
While I didn't do it in this patch I propose we drop support for
15
the match file without create support. This is several years old
16
now and would clean things up a lot.
18
Note: that the manually input -m or -M drop support for it already
19
I just can't see a good way to support a single input stream indicating
20
the result/existance of two separate files.
22
This needs more work but is needed to support tests and the policy_mediates
23
frame work depends on the policydb getting generated with the special
24
stub rules to indicate whether policy was compiled expecting a certain
25
feature. But this can break the current tests, at least once a bug
26
in the policy rule counting is fixed in a follow on patch.
28
Signed-off-by: John Johansen <john.johansen@canonical.com>
31
parser/parser_main.c | 198 +++++++++++++-------------
32
parser/tst/features_files/features.dbus | 34 ++++
33
parser/tst/features_files/features.mount | 34 ++++
34
parser/tst/features_files/features.mount+dbus | 37 ++++
35
parser/tst/features_files/features.nopolicydb | 31 ++++
36
parser/tst/minimize.sh | 16 +-
37
6 files changed, 247 insertions(+), 103 deletions(-)
39
--- 2.9-test.orig/parser/parser_main.c
40
+++ 2.9-test/parser/parser_main.c
42
#define OLD_MODULE_NAME "subdomain"
43
#define PROC_MODULES "/proc/modules"
44
#define DEFAULT_APPARMORFS "/sys/kernel/security/" MODULE_NAME
45
-#define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
46
-#define FLAGS_FILE "/sys/kernel/security/" MODULE_NAME "/features"
47
+#define MATCH_FILE "/sys/kernel/security/" MODULE_NAME "/matching"
48
+#define FEATURES_FILE "/sys/kernel/security/" MODULE_NAME "/features"
49
#define MOUNTED_FS "/proc/mounts"
50
#define AADFA "pattern=aadfa"
53
int skip_mode_force = 0;
54
struct timespec mru_tstamp;
56
-#define FLAGS_STRING_SIZE 8192
57
-char *match_string = NULL;
58
-char *flags_string = NULL;
59
+#define FEATURES_STRING_SIZE 8192
60
+char *features_string = NULL;
61
char *cacheloc = NULL;
63
/* per-profile settings */
64
int force_complain = 0;
66
+static int load_features(const char *name);
68
/* Make sure to update BOTH the short and long_options */
69
-static const char *short_options = "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkL:O:po:";
70
+static const char *short_options = "adf:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:";
71
struct option long_options[] = {
73
{"binary", 0, 0, 'B'},
75
{"stdout", 0, 0, 'S'},
77
{"match-string", 1, 0, 'm'},
78
+ {"features-file", 1, 0, 'M'},
80
{"skip-kernel-load", 0, 0, 'Q'},
81
{"verbose", 0, 0, 'v'},
83
"-b n, --base n Set base dir and cwd\n"
84
"-I n, --Include n Add n to the search path\n"
85
"-f n, --subdomainfs n Set location of apparmor filesystem\n"
86
- "-m n, --match-string n Use only match features n\n"
87
+ "-m n, --match-string n Use only features n\n"
88
+ "-M n, --features-file n Use only features in file n\n"
89
"-n n, --namespace n Set Namespace for the profile\n"
90
"-X, --readimpliesX Map profile read permissions to mr\n"
91
"-k, --show-cache Report cache hit/miss details\n"
96
- match_string = strdup(optarg);
97
+ features_string = strdup(optarg);
100
+ if (load_features(optarg) == -1) {
101
+ fprintf(stderr, "Failed to load features from '%s'\n",
108
@@ -733,104 +743,107 @@
109
struct features_struct fst = { buffer, size, pos };
111
if (dirat_for_each(NULL, filename, &fst, features_dir_cb)) {
112
- PDEBUG("Failed evaluating .features\n");
113
+ PDEBUG("Failed evaluating %s\n", filename);
120
-/* match_string == NULL --> no match_string available
121
- match_string != NULL --> either a matching string specified on the
122
- command line, or the kernel supplied a match string */
123
-static void get_match_string(void) {
124
+static char *load_features_file(const char *name) {
130
- struct stat stat_file;
131
+ f = fopen(name, "r");
135
- /* has process_args() already assigned a match string? */
138
+ buffer = (char *) malloc(FEATURES_STRING_SIZE);
142
- if (stat(FLAGS_FILE, &stat_file) == -1)
144
+ size = fread(buffer, 1, FEATURES_STRING_SIZE - 1, f);
145
+ if (!size || ferror(f))
149
- if (S_ISDIR(stat_file.st_mode)) {
150
- /* if we have a features directory default to */
155
- flags_string = (char *) malloc(FLAGS_STRING_SIZE);
156
- handle_features_dir(FLAGS_FILE, &flags_string, FLAGS_STRING_SIZE, flags_string);
157
- if (strstr(flags_string, "network"))
158
- kernel_supports_network = 1;
160
- kernel_supports_network = 0;
161
- if (strstr(flags_string, "mount"))
162
- kernel_supports_mount = 1;
163
- if (strstr(flags_string, "dbus"))
164
- kernel_supports_dbus = 1;
176
- ms = fopen(MATCH_STRING, "r");
179
+static int load_features(const char *name)
181
+ struct stat stat_file;
183
- match_string = (char *) malloc(1000);
184
- if (!match_string) {
187
+ if (stat(name, &stat_file) == -1)
190
- if (!fgets(match_string, 1000, ms)) {
191
- free(match_string);
192
- match_string = NULL;
193
+ if (S_ISDIR(stat_file.st_mode)) {
194
+ /* if we have a features directory default to */
195
+ features_string = (char *) malloc(FEATURES_STRING_SIZE);
196
+ handle_features_dir(name, &features_string, FEATURES_STRING_SIZE, features_string);
198
+ features_string = load_features_file(name);
199
+ if (!features_string)
204
- if (match_string) {
208
+static void set_features_by_match_file(void)
210
+ FILE *ms = fopen(MATCH_FILE, "r");
212
+ char *match_string = (char *) malloc(1000);
215
+ if (!fgets(match_string, 1000, ms)) {
216
+ free(match_string);
219
if (strstr(match_string, " perms=c"))
223
- kernel_supports_network = 0;
224
+ free(match_string);
229
+ kernel_supports_network = 0;
237
-static void get_flags_string(char **flags, const char *flags_file) {
242
- /* abort if missing or already set */
243
- if (!flags || *flags)
246
- f = fopen(flags_file, "r");
249
+static void set_supported_features(void) {
251
- *flags = (char *) malloc(FLAGS_STRING_SIZE);
255
- size = fread(*flags, 1, FLAGS_STRING_SIZE - 1, f);
256
- if (!size || ferror(f))
258
- (*flags)[size] = 0;
259
+ /* has process_args() already assigned a match string? */
260
+ if (!features_string) {
261
+ if (load_features(FEATURES_FILE) == -1) {
262
+ set_features_by_match_file();
277
+ /* TODO: make this real parsing and config setting */
278
+ if (strstr(features_string, "network"))
279
+ kernel_supports_network = 1;
280
+ if (strstr(features_string, "mount"))
281
+ kernel_supports_mount = 1;
282
+ if (strstr(features_string, "dbus"))
283
+ kernel_supports_dbus = 1;
286
int process_binary(int option, const char *profilename)
287
@@ -1211,28 +1224,23 @@
288
char *cache_flags = NULL;
290
/* Get the match string to determine type of regex support needed */
291
- get_match_string();
292
- /* Get kernel features string */
293
- get_flags_string(&flags_string, FLAGS_FILE);
294
+ set_supported_features();
296
/* Gracefully handle AppArmor kernel without compatibility patch */
297
- if (!flags_string) {
298
+ if (!features_string) {
299
PERROR("Cache read/write disabled: %s interface file missing. "
300
"(Kernel needs AppArmor 2.4 compatibility patch.)\n",
306
- } else if (strstr(flags_string, "network"))
307
- kernel_supports_network = 1;
309
- kernel_supports_network = 0;
315
* Deal with cache directory versioning:
316
* - If cache/.features is missing, create it if --write-cache.
317
- * - If cache/.features exists, and does not match flags_string,
318
+ * - If cache/.features exists, and does not match features_string,
319
* force cache reading/writing off.
321
if (asprintf(&cache_features_path, "%s/.features", cacheloc) == -1) {
322
@@ -1240,16 +1248,16 @@
326
- get_flags_string(&cache_flags, cache_features_path);
327
+ cache_flags = load_features_file(cache_features_path);
329
- if (strcmp(flags_string, cache_flags) != 0) {
330
+ if (strcmp(features_string, cache_flags) != 0) {
331
if (write_cache && cond_clear_cache) {
332
if (create_cache(cacheloc, cache_features_path,
338
- PERROR("Cache read/write disabled: %s does not match %s\n", FLAGS_FILE, cache_features_path);
339
+ PERROR("Cache read/write disabled: %s does not match %s\n", FEATURES_FILE, cache_features_path);
343
@@ -1257,7 +1265,7 @@
346
} else if (write_cache) {
347
- create_cache(cacheloc, cache_features_path, flags_string);
348
+ create_cache(cacheloc, cache_features_path, features_string);
351
free(cache_features_path);
353
+++ 2.9-test/parser/tst/features_files/features.dbus
355
+dbus {mask {acquire send receive
358
+caps {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
361
+rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
364
+capability {0xffffff
366
+namespaces {pivot_root {yes
371
+network {af_mask {unspec unix local 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 can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock max
374
+file {mask {create read write exec append mmap_exec link lock
377
+domain {change_profile {yes
386
+policy {set_load {yes
390
+++ 2.9-test/parser/tst/features_files/features.mount
392
+caps {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
395
+rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
398
+capability {0xffffff
400
+namespaces {pivot_root {yes
405
+mount {mask {mount umount
408
+network {af_mask {unspec unix local 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 can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock max
411
+file {mask {create read write exec append mmap_exec link lock
414
+domain {change_profile {yes
423
+policy {set_load {yes
427
+++ 2.9-test/parser/tst/features_files/features.mount+dbus
429
+dbus {mask {acquire send receive
432
+caps {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
435
+rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
438
+capability {0xffffff
440
+namespaces {pivot_root {yes
445
+mount {mask {mount umount
448
+network {af_mask {unspec unix local 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 can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock max
451
+file {mask {create read write exec append mmap_exec link lock
454
+domain {change_profile {yes
463
+policy {set_load {yes
467
+++ 2.9-test/parser/tst/features_files/features.nopolicydb
469
+caps {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
472
+rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
475
+capability {0xffffff
477
+namespaces {pivot_root {yes
482
+network {af_mask {unspec unix local 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 can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock max
485
+file {mask {create read write exec append mmap_exec link lock
488
+domain {change_profile {yes
497
+policy {set_load {yes
500
--- 2.9-test.orig/parser/tst/minimize.sh
501
+++ 2.9-test/parser/tst/minimize.sh
503
# {a} (0x 40030/0/0/0)
505
echo -n "Minimize profiles basic perms "
506
-if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
507
+if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
512
# {9} (0x 12804a/0/2800a/0)
513
# {c} (0x 40030/0/0/0)
514
echo -n "Minimize profiles audit perms "
515
-if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
516
+if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
521
# {c} (0x 40030/0/0/0)
523
echo -n "Minimize profiles deny perms "
524
-if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
525
+if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
530
# {c} (0x 40030/0/0/0)
532
echo -n "Minimize profiles audit deny perms "
533
-if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 5 ] ; then
534
+if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 5 ] ; then
541
echo -n "Minimize profiles xtrans "
542
-if [ `echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
543
+if [ `echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
549
# same test as above + audit
550
echo -n "Minimize profiles audit xtrans "
551
-if [ `echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
552
+if [ `echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
557
# {3} (0x 0/fe17f85/0/14005)
559
echo -n "Minimize profiles deny xtrans "
560
-if [ `echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
561
+if [ `echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
566
# {3} (0x 0/fe17f85/0/0)
568
echo -n "Minimize profiles audit deny xtrans "
569
-if [ `echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 0 ] ; then
570
+if [ `echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 0 ] ; then
576
AppArmor mailing list
577
AppArmor@lists.ubuntu.com
578
Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor