Merge lp:~jdstrand/snap-confine/security-review-fixes into lp:~snappy-dev/snap-confine/trunk

Proposed by Jamie Strandboge
Status: Merged
Merged at revision: 110
Proposed branch: lp:~jdstrand/snap-confine/security-review-fixes
Merge into: lp:~snappy-dev/snap-confine/trunk
Diff against target: 492 lines (+150/-110)
8 files modified
debian/changelog (+3/-0)
src/main.c (+25/-25)
src/seccomp.c (+46/-33)
src/utils.c (+2/-1)
tests/test_bad_seccomp_filter_length (+20/-0)
tests/test_bad_seccomp_filter_missing_trailing_newline (+17/-0)
tests/test_create_user_data (+7/-51)
tests/test_unrestricted_missed (+30/-0)
To merge this branch: bzr merge lp:~jdstrand/snap-confine/security-review-fixes
Reviewer Review Type Date Requested Status
Tyler Hicks (community) Needs Fixing
Snappy Developers Pending
Review via email: mp+290156@code.launchpad.net

Description of the change

Various fixes to address Seth's feedback:
- cleaned up 'out' handling and die instead
- fixed the typo
- verify snprint() >= 512 (I increased this length) and added tests
- add test for filter missing trailing newline (I didn't change the line-too-long handling, but did add tests and verify we must end with trailing newline
- use strcmp() with "@unrestricted". add @unrestricted near miss tests
- use getresuid() instead of UBUNTU_CORE_LAUNCHER_NO_ROOT
- replace getenv() with secure_getenv() everywhere we can
- check return code of fork()
- verify return code of fclose()
- simplified final execv()

In addition:
- don't support obsoleted SNAP_APP_TMPDIR and SNAP_APP_USER_DATA_PATH
- use uid_t and gid_t instead of unsigned
- check return codes of other (f)close()s to help futureproof

To post a comment you must log in.
122. By Jamie Strandboge

merge from trunk

123. By Jamie Strandboge

rename recently add tests

124. By Jamie Strandboge

merge from trunk

125. By Jamie Strandboge

fix debian/changelog which had improper syntax

126. By Jamie Strandboge

merge from trunk

127. By Jamie Strandboge

merge from trunk

128. By Jamie Strandboge

merge from trunk

129. By Jamie Strandboge

merge from trunk

Revision history for this message
Tyler Hicks (tyhicks) wrote :

I've completed a partial review. I still haven't gotten through all of the seccomp and test related changes. I'll complete that later this afternoon.

review: Needs Fixing
Revision history for this message
Tyler Hicks (tyhicks) wrote :

The seccomp_load_filters() error handling is still very confusing since there are a mix of die()'s and non-zero return values which ultimately end in a die(). If seccomp_load_filters() is going to internally call die() upon error in some conditions, it should be changed to have a void return and simply call die() in all error conditions. I believe that was what Seth was suggesting, as well.

review: Needs Fixing
130. By Jamie Strandboge

update a few comments based on tyhicks feedback

Revision history for this message
Tyler Hicks (tyhicks) wrote :

I've completed my review now. I only had one additional comment regarding another fclose() error check.

131. By Jamie Strandboge

simplify seccomp_load_filters() and always die() on error instead of trying to
return non-zero sometimes

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

Thanks for the review! Yes, the error checking on the (f)close()s are not needed since they are read only, but I added them to help futureproof the codebase. Leaving those in.

I cleaned up seccomp_load_filters() error handling in r131.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2016-03-30 12:46:25 +0000
+++ debian/changelog 2016-03-31 19:41:16 +0000
@@ -2,6 +2,9 @@
22
3 * update README for recent commits3 * update README for recent commits
4 * add README.syscalls4 * add README.syscalls
5 * src/seccomp.c: various cleanups from security team audit (also add
6 additional tests)
7 * don't support obsoleted SNAP_APP_TMPDIR and SNAP_APP_USER_DATA_PATH
58
6 -- Jamie Strandboge <jamie@ubuntu.com> Tue, 29 Mar 2016 16:07:13 -05009 -- Jamie Strandboge <jamie@ubuntu.com> Tue, 29 Mar 2016 16:07:13 -0500
710
811
=== modified file 'src/main.c'
--- src/main.c 2016-03-22 19:42:30 +0000
+++ src/main.c 2016-03-31 19:41:16 +0000
@@ -67,6 +67,9 @@
6767
68 int status = 0;68 int status = 0;
69 pid_t pid = fork();69 pid_t pid = fork();
70 if (pid < 0) {
71 die("could not fork");
72 }
70 if (pid == 0) {73 if (pid == 0) {
71 char buf[64];74 char buf[64];
72 unsigned major = MAJOR(devnum);75 unsigned major = MAJOR(devnum);
@@ -198,7 +201,8 @@
198 if (fd < 0)201 if (fd < 0)
199 return false;202 return false;
200 int n = read(fd, content, sizeof(content));203 int n = read(fd, content, sizeof(content));
201 close(fd);204 if (close(fd) != 0)
205 die("could not close override");
202 if (n < sizeof(content))206 if (n < sizeof(content))
203 return false;207 return false;
204208
@@ -259,7 +263,7 @@
259 die("unable to chown tmpdir");263 die("unable to chown tmpdir");
260 }264 }
261 // ensure we set the various TMPDIRs to our newly created tmpdir265 // ensure we set the various TMPDIRs to our newly created tmpdir
262 const char *tmpd[] = { "TMPDIR", "TEMPDIR", "SNAP_APP_TMPDIR", NULL };266 const char *tmpd[] = { "TMPDIR", "TEMPDIR", NULL };
263 int i;267 int i;
264 for (i = 0; tmpd[i] != NULL; i++) {268 for (i = 0; tmpd[i] != NULL; i++) {
265 if (setenv(tmpd[i], "/tmp", 1) != 0) {269 if (setenv(tmpd[i], "/tmp", 1) != 0) {
@@ -395,7 +399,7 @@
395 // Try to create the directory. It's okay if it already399 // Try to create the directory. It's okay if it already
396 // existed, but any other error is fatal.400 // existed, but any other error is fatal.
397 if (mkdirat(fd, path_segment, 0755) < 0 && errno != EEXIST) {401 if (mkdirat(fd, path_segment, 0755) < 0 && errno != EEXIST) {
398 close(fd);402 close(fd); // we die regardless of return code
399 free(path_copy);403 free(path_copy);
400 die("failed to create user data directory");404 die("failed to create user data directory");
401 }405 }
@@ -403,7 +407,10 @@
403 // previous one) so we can continue down the path.407 // previous one) so we can continue down the path.
404 int previous_fd = fd;408 int previous_fd = fd;
405 fd = openat(fd, path_segment, open_flags);409 fd = openat(fd, path_segment, open_flags);
406 close(previous_fd);410 if (close(previous_fd) != 0) {
411 free(path_copy);
412 die("could not close path segment");
413 }
407 if (fd < 0) {414 if (fd < 0) {
408 free(path_copy);415 free(path_copy);
409 die("failed to create user data directory");416 die("failed to create user data directory");
@@ -413,7 +420,10 @@
413 }420 }
414421
415 // Close the descriptor for the final directory in the path.422 // Close the descriptor for the final directory in the path.
416 close(fd);423 if (close(fd) != 0) {
424 free(path_copy);
425 die("could not close final directory");
426 }
417427
418 free(path_copy);428 free(path_copy);
419}429}
@@ -422,16 +432,8 @@
422{432{
423 const char *user_data = getenv("SNAP_USER_DATA");433 const char *user_data = getenv("SNAP_USER_DATA");
424434
425 // If $SNAP_USER_DATA wasn't defined, check the deprecated435 if (user_data == NULL)
426 // $SNAP_APP_USER_DATA_PATH.436 return;
427 if (user_data == NULL) {
428 user_data = getenv("SNAP_APP_USER_DATA_PATH");
429 // If it's still not defined, there's nothing to do. No need to
430 // die, there's simply no directory to create.
431 if (user_data == NULL) {
432 return;
433 }
434 }
435 // Only support absolute paths.437 // Only support absolute paths.
436 if (user_data[0] != '/') {438 if (user_data[0] != '/') {
437 die("user data directory must be an absolute path");439 die("user data directory must be an absolute path");
@@ -449,15 +451,16 @@
449 const char *appname = argv[1];451 const char *appname = argv[1];
450 const char *aa_profile = argv[2];452 const char *aa_profile = argv[2];
451 const char *binary = argv[3];453 const char *binary = argv[3];
452 unsigned real_uid = getuid();454 uid_t real_uid = getuid();
453 unsigned real_gid = getgid();455 gid_t real_gid = getgid();
454456
455 if (!verify_appname(appname))457 if (!verify_appname(appname))
456 die("appname %s not allowed", appname);458 die("appname %s not allowed", appname);
457459
458 // this code always needs to run as root for the cgroup/udev setup,460 // this code always needs to run as root for the cgroup/udev setup,
459 // however for the tests we allow it to run as non-root461 // however for the tests we allow it to run as non-root
460 if (geteuid() != 0 && getenv("UBUNTU_CORE_LAUNCHER_NO_ROOT") == NULL) {462 if (geteuid() != 0
463 && secure_getenv("UBUNTU_CORE_LAUNCHER_NO_ROOT") == NULL) {
461 die("need to run as root or suid");464 die("need to run as root or suid");
462 }465 }
463466
@@ -511,13 +514,11 @@
511 // set apparmor rules514 // set apparmor rules
512 rc = aa_change_onexec(aa_profile);515 rc = aa_change_onexec(aa_profile);
513 if (rc != 0) {516 if (rc != 0) {
514 if (getenv("SNAPPY_LAUNCHER_INSIDE_TESTS") == NULL)517 if (secure_getenv("SNAPPY_LAUNCHER_INSIDE_TESTS") == NULL)
515 die("aa_change_onexec failed with %i", rc);518 die("aa_change_onexec failed with %i", rc);
516 }519 }
517 // set seccomp520 // set seccomp (note: seccomp_load_filters die()s on all failures)
518 rc = seccomp_load_filters(aa_profile);521 seccomp_load_filters(aa_profile);
519 if (rc != 0)
520 die("seccomp_load_filters failed with %i", rc);
521522
522 // Permanently drop if not root523 // Permanently drop if not root
523 if (geteuid() == 0) {524 if (geteuid() == 0) {
@@ -534,8 +535,7 @@
534 die("permanently dropping privs did not work");535 die("permanently dropping privs did not work");
535 }536 }
536 // and exec the new binary537 // and exec the new binary
537 argv[NR_ARGS] = (char *)binary,538 execv(binary, (char *const *)&argv[NR_ARGS]);
538 execv(binary, (char *const *)&argv[NR_ARGS]);
539 perror("execv failed");539 perror("execv failed");
540 return 1;540 return 1;
541}541}
542542
=== modified file 'src/seccomp.c'
--- src/seccomp.c 2016-03-22 19:42:30 +0000
+++ src/seccomp.c 2016-03-31 19:41:16 +0000
@@ -14,6 +14,10 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 */16 */
17#ifndef _GNU_SOURCE
18#define _GNU_SOURCE
19#endif
20
17#include <errno.h>21#include <errno.h>
18#include <stdio.h>22#include <stdio.h>
19#include <unistd.h>23#include <unistd.h>
@@ -37,7 +41,7 @@
37 return slen;41 return slen;
38}42}
3943
40int seccomp_load_filters(const char *filter_profile)44void seccomp_load_filters(const char *filter_profile)
41{45{
42 debug("seccomp_load_filters %s", filter_profile);46 debug("seccomp_load_filters %s", filter_profile);
43 int rc = 0;47 int rc = 0;
@@ -45,45 +49,51 @@
45 scmp_filter_ctx ctx = NULL;49 scmp_filter_ctx ctx = NULL;
46 FILE *f = NULL;50 FILE *f = NULL;
47 size_t lineno = 0;51 size_t lineno = 0;
52 uid_t real_uid, effective_uid, saved_uid;
4853
49 ctx = seccomp_init(SCMP_ACT_KILL);54 ctx = seccomp_init(SCMP_ACT_KILL);
50 if (ctx == NULL)55 if (ctx == NULL) {
51 return ENOMEM;56 errno = ENOMEM;
5257 die("seccomp_init() failed");
58 }
53 // Disable NO_NEW_PRIVS because it interferes with exec transitions in59 // Disable NO_NEW_PRIVS because it interferes with exec transitions in
54 // AppArmor. Unfortunately this means that security policies must be60 // AppArmor. Unfortunately this means that security policies must be
55 // very careful to not allow the following otherwise apps can escape61 // very careful to not allow the following otherwise apps can escape
56 // the snadbox:62 // the sandbox:
57 // - seccomp syscall63 // - seccomp syscall
58 // - prctl with PR_SET_SECCOMP64 // - prctl with PR_SET_SECCOMP
59 // - ptrace (trace) in AppArmor65 // - ptrace (trace) in AppArmor
60 // - capability sys_admin in AppArmor66 // - capability sys_admin in AppArmor
61 // Note that with NO_NEW_PRIVS disabled, CAP_SYS_ADMIN is required to67 // Note that with NO_NEW_PRIVS disabled, CAP_SYS_ADMIN is required to
62 // change the seccomp sandbox.68 // change the seccomp sandbox.
63 if (getenv("UBUNTU_CORE_LAUNCHER_NO_ROOT") == NULL) {69
64 rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0);70 if (getresuid(&real_uid, &effective_uid, &saved_uid) != 0)
65 if (rc != 0) {71 die("could not find user IDs");
66 fprintf(stderr, "Cannot disable nnp\n");72
67 return -1;73 // If running privileged or capable of raising, disable nnp
68 }74 if (real_uid == 0 || effective_uid == 0 || saved_uid == 0)
69 }75 if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0) != 0)
7076 die("Cannot disable nnp");
71 if (getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR") != NULL)77
78 // Note that secure_gettenv will always return NULL when suid, so
79 // SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR can't be (ab)used in that case.
80 if (secure_getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR") != NULL)
72 filter_profile_dir =81 filter_profile_dir =
73 getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR");82 secure_getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR");
7483
75 char profile_path[128];84 char profile_path[512]; // arbitrary path name limit
76 if (snprintf85 int snprintf_rc = snprintf(profile_path, sizeof(profile_path), "%s/%s",
77 (profile_path, sizeof(profile_path), "%s/%s", filter_profile_dir,86 filter_profile_dir, filter_profile);
78 filter_profile) < 0) {87 if (snprintf_rc < 0 || snprintf_rc >= 512) {
79 goto out;88 errno = 0;
89 die("snprintf returned unexpected value");
80 }90 }
8191
82 f = fopen(profile_path, "r");92 f = fopen(profile_path, "r");
83 if (f == NULL) {93 if (f == NULL) {
84 fprintf(stderr, "Can not open %s (%s)\n", profile_path,94 fprintf(stderr, "Can not open %s (%s)\n", profile_path,
85 strerror(errno));95 strerror(errno));
86 return -1;96 die("aborting");
87 }97 }
88 // 80 characters + '\n' + '\0'98 // 80 characters + '\n' + '\0'
89 char buf[82];99 char buf[82];
@@ -104,16 +114,17 @@
104 fprintf(stderr,114 fprintf(stderr,
105 "seccomp filter line %zu was too long (%zu characters max)\n",115 "seccomp filter line %zu was too long (%zu characters max)\n",
106 lineno, sizeof(buf) - 2);116 lineno, sizeof(buf) - 2);
107 rc = -1;117 errno = 0;
108 goto out;118 die("aborting");
109 }119 }
110 // kill final newline120 // kill final newline
111 len = trim_right(buf, len);121 len = trim_right(buf, len);
112 if (len == 0)122 if (len == 0)
113 continue;123 continue;
114124
115 // check for special "@unrestricted" command125 // check for special "@unrestricted" rule which short-circuits
116 if (strncmp(buf, "@unrestricted", sizeof(buf)) == 0)126 // seccomp sandbox
127 if (strcmp(buf, "@unrestricted") == 0)
117 goto out;128 goto out;
118129
119 // syscall not available on this arch/kernel130 // syscall not available on this arch/kernel
@@ -132,13 +143,15 @@
132 fprintf(stderr,143 fprintf(stderr,
133 "seccomp_rule_add failed with %i for '%s'\n",144 "seccomp_rule_add failed with %i for '%s'\n",
134 rc, buf);145 rc, buf);
135 goto out;146 errno = 0;
147 die("aborting");
136 }148 }
137 }149 }
138 }150 }
139151
140 // raise privileges to load seccomp policy since we don't have nnp152 // If not root but can raise, then raise privileges to load seccomp
141 if (getenv("UBUNTU_CORE_LAUNCHER_NO_ROOT") == NULL) {153 // policy since we don't have nnp
154 if (effective_uid != 0 && saved_uid == 0) {
142 if (seteuid(0) != 0)155 if (seteuid(0) != 0)
143 die("seteuid failed");156 die("seteuid failed");
144 if (geteuid() != 0)157 if (geteuid() != 0)
@@ -149,10 +162,8 @@
149162
150 if (rc != 0) {163 if (rc != 0) {
151 fprintf(stderr, "seccomp_load failed with %i\n", rc);164 fprintf(stderr, "seccomp_load failed with %i\n", rc);
152 goto out;165 die("aborting");
153 }166 }
154
155 out:
156 // drop privileges again167 // drop privileges again
157 if (geteuid() == 0) {168 if (geteuid() == 0) {
158 unsigned real_uid = getuid();169 unsigned real_uid = getuid();
@@ -162,9 +173,11 @@
162 die("dropping privs after seccomp_load did not work");173 die("dropping privs after seccomp_load did not work");
163 }174 }
164175
176 out:
165 if (f != NULL) {177 if (f != NULL) {
166 fclose(f);178 if (fclose(f) != 0)
179 die("could not close seccomp file");
167 }180 }
168 seccomp_release(ctx);181 seccomp_release(ctx);
169 return rc;182 return;
170}183}
171184
=== modified file 'src/utils.c'
--- src/utils.c 2016-03-22 12:17:03 +0000
+++ src/utils.c 2016-03-31 19:41:16 +0000
@@ -70,7 +70,8 @@
70 die("fwrite failed");70 die("fwrite failed");
71 if (fflush(f) != 0)71 if (fflush(f) != 0)
72 die("fflush failed");72 die("fflush failed");
73 fclose(f);73 if (fclose(f) != 0)
74 die("fclose failed");
74}75}
7576
76int must_snprintf(char *str, size_t size, const char *format, ...)77int must_snprintf(char *str, size_t size, const char *format, ...)
7778
=== added file 'tests/test_bad_seccomp_filter_length'
--- tests/test_bad_seccomp_filter_length 1970-01-01 00:00:00 +0000
+++ tests/test_bad_seccomp_filter_length 2016-03-31 19:41:16 +0000
@@ -0,0 +1,20 @@
1#!/bin/sh
2
3set -e
4
5. $(pwd)/common.sh
6
7printf "Test seccomp filter (bad - too long)"
8
9cat >$TMP/aaprofile <<EOF
10# some comment
11baddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
12EOF
13
14if $L appname aaprofile /bin/true 2>/dev/null; then
15 # true returned successfully, length test failed
16 FAIL
17fi
18
19# all good
20PASS
021
=== added file 'tests/test_bad_seccomp_filter_missing_trailing_newline'
--- tests/test_bad_seccomp_filter_missing_trailing_newline 1970-01-01 00:00:00 +0000
+++ tests/test_bad_seccomp_filter_missing_trailing_newline 2016-03-31 19:41:16 +0000
@@ -0,0 +1,17 @@
1#!/bin/sh
2
3set -e
4
5. $(pwd)/common.sh
6
7printf "Test seccomp filter (bad - no trailing newline)"
8
9echo -n "missingnewline" > $TMP/aaprofile
10
11if $L appname aaprofile /bin/true 2>/dev/null; then
12 # true returned successfully, length test failed
13 FAIL
14fi
15
16# all good
17PASS
018
=== modified file 'tests/test_create_user_data'
--- tests/test_create_user_data 2016-03-19 02:32:43 +0000
+++ tests/test_create_user_data 2016-03-31 19:41:16 +0000
@@ -82,56 +82,28 @@
82 return $pass82 return $pass
83}83}
8484
85# $1 = $SNAP_APP_USER_DATA_PATH definition
86# $2 = Profile name
87# $3 = True if success is expected, false otherwise
88run_deprecated() {
89 export SNAP_APP_USER_DATA_PATH=$1
90 run_launcher $1 $2 $3
91 pass=$?
92 unset SNAP_APP_USER_DATA_PATH
93
94 return $pass
95}
96
97# $1 = User data path
98# $2 = Profile name
99# $3 = True if success is expected, false otherwise
100run_both() {
101 run_current $1 $2 $3
102 current_pass=$?
103 run_deprecated $1 $2 $3
104 deprecated_pass=$?
105
106 if [ $current_pass -a $deprecated_pass ]; then
107 PASS
108 else
109 FAIL
110 fi
111}
112
113printf "Test that an unrestricted launcher creates user data"85printf "Test that an unrestricted launcher creates user data"
114run_both $TMP/user_data unrestricted true86run_current $TMP/user_data unrestricted true
11587
116printf "Test that a restricted launcher creates user data"88printf "Test that a restricted launcher creates user data"
117run_both $TMP/user_data restricted true89run_current $TMP/user_data restricted true
11890
119printf "Test that an unrestricted launcher creates user data with parent directory"91printf "Test that an unrestricted launcher creates user data with parent directory"
120run_both $TMP/parent/user_data unrestricted true92run_current $TMP/parent/user_data unrestricted true
12193
122printf "Test that a restricted launcher creates user data with parent directory"94printf "Test that a restricted launcher creates user data with parent directory"
123run_both $TMP/parent/user_data restricted true95run_current $TMP/parent/user_data restricted true
12496
125printf "Test that user data can contain multiple path separators"97printf "Test that user data can contain multiple path separators"
126run_both $TMP//user_data unrestricted true98run_current $TMP//user_data unrestricted true
12799
128printf "Test that user data must be absolute"100printf "Test that user data must be absolute"
129run_both "../foo" unrestricted false101run_current "../foo" unrestricted false
130102
131printf "Testing that user data cannot be contained within a symlink"103printf "Testing that user data cannot be contained within a symlink"
132mkdir $TMP/nefarious_parent104mkdir $TMP/nefarious_parent
133ln -s $TMP/nefarious_parent $TMP/parent105ln -s $TMP/nefarious_parent $TMP/parent
134run_both $TMP/parent/user_data unrestricted, false106run_current $TMP/parent/user_data unrestricted, false
135107
136printf "Test that an unrestricted launcher works when user data exists (current)"108printf "Test that an unrestricted launcher works when user data exists (current)"
137mkdir $TMP/user_data109mkdir $TMP/user_data
@@ -148,19 +120,3 @@
148else120else
149 FAIL121 FAIL
150fi122fi
151
152printf "Test that an unrestricted launcher works when user data exists (deprecated)"
153mkdir $TMP/user_data
154if run_deprecated $TMP/user_data unrestricted true; then
155 PASS
156else
157 FAIL
158fi
159
160printf "Test that an restricted launcher works when user data exists (deprecated)"
161mkdir $TMP/user_data
162if run_deprecated $TMP/user_data restricted true; then
163 PASS
164else
165 FAIL
166fi
167123
=== added file 'tests/test_unrestricted_missed'
--- tests/test_unrestricted_missed 1970-01-01 00:00:00 +0000
+++ tests/test_unrestricted_missed 2016-03-31 19:41:16 +0000
@@ -0,0 +1,30 @@
1#!/bin/sh
2
3set -e
4
5. $(pwd)/common.sh
6
7cat >$TMP/myprofile <<EOF
8# super strict filter
9@unrestricte
10@unrestrictes
11@nrestricted
12@UNRESTRICTED
13unrestricted
14EOF
15
16# ensure that the command "true" can not run due to impossible
17# filtering
18
19printf "Test that near misses of unrestricted fail"
20if $L appid myprofile /bin/true 2>/dev/null; then
21 # true returned successfully, our filtering is broken!
22 FAIL
23else
24 # true returend a error code, check dmesg
25 if dmesg|tail -n1|grep -q "audit"; then
26 PASS
27 else
28 FAIL
29 fi
30fi

Subscribers

People subscribed via source and target branches