merge in oc-release history after reset to master
diff --git a/Android.mk b/Android.mk
index 6a63e87..ecc5e97 100644
--- a/Android.mk
+++ b/Android.mk
@@ -195,7 +195,7 @@
# Syscall filtering native unit tests for the host. Run with:
-# out/host/linux-x86/nativetest(64)/syscall_filter_unittest/syscall_filter_unittest_gtest
+# out/host/linux-x86/nativetest(64)/syscall_filter_unittest_gtest/syscall_filter_unittest_gtest
# =========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := syscall_filter_unittest_gtest
diff --git a/bpf.c b/bpf.c
index b618866..8f5a08d 100644
--- a/bpf.c
+++ b/bpf.c
@@ -267,8 +267,9 @@
}
end = begin + labels->count;
for (id = 0; begin < end; ++begin, ++id) {
- if (!strcmp(label, begin->label))
+ if (!strcmp(label, begin->label)) {
return id;
+ }
}
/* The label wasn't found. Insert it only if there's space. */
@@ -284,7 +285,6 @@
return id;
}
-/* Free label strings. */
void free_label_strings(struct bpf_labels *labels)
{
if (labels->count == 0)
diff --git a/parse_seccomp_policy.cc b/parse_seccomp_policy.cc
index c50b79e..a9daed0 100644
--- a/parse_seccomp_policy.cc
+++ b/parse_seccomp_policy.cc
@@ -32,7 +32,7 @@
}
struct sock_fprog fp;
- int res = compile_filter(f, &fp, 0);
+ int res = compile_filter(f, &fp, 0, 0);
if (res != 0) {
die("compile_filter failed");
}
diff --git a/syscall_filter.c b/syscall_filter.c
index ad84921..3318052 100644
--- a/syscall_filter.c
+++ b/syscall_filter.c
@@ -12,14 +12,13 @@
#include "util.h"
/* clang-format off */
-#define MAX_LINE_LENGTH 1024
#define MAX_POLICY_LINE_LENGTH 1024
#define ONE_INSTR 1
#define TWO_INSTRS 2
/* clang-format on */
-int seccomp_can_softfail()
+int seccomp_can_softfail(void)
{
#if defined(USE_SECCOMP_SOFTFAIL)
return 1;
@@ -51,7 +50,7 @@
return buf;
}
-struct filter_block *new_filter_block()
+struct filter_block *new_filter_block(void)
{
struct filter_block *block = calloc(1, sizeof(struct filter_block));
if (!block)
@@ -278,10 +277,10 @@
return 0;
}
-struct filter_block *compile_section(int nr, const char *policy_line,
- unsigned int entry_lbl_id,
- struct bpf_labels *labels,
- int use_ret_trap)
+struct filter_block *compile_policy_line(int nr, const char *policy_line,
+ unsigned int entry_lbl_id,
+ struct bpf_labels *labels,
+ int use_ret_trap)
{
/*
* |policy_line| should be an expression of the form:
@@ -429,17 +428,115 @@
return head;
}
-int compile_filter(FILE *policy_file, struct sock_fprog *prog, int use_ret_trap,
- int allow_logging)
+int compile_file(FILE *policy_file, struct filter_block *head,
+ struct filter_block **arg_blocks, struct bpf_labels *labels,
+ int use_ret_trap, int allow_logging)
{
- char line[MAX_LINE_LENGTH];
- int line_count = 0;
+ /*
+ * Loop through all the lines in the policy file.
+ * Build a jump table for the syscall number.
+ * If the policy line has an arg filter, build the arg filter
+ * as well.
+ * Chain the filter sections together and dump them into
+ * the final buffer at the end.
+ */
+ char *line = NULL;
+ size_t len = 0;
+ while (getline(&line, &len, policy_file) != -1) {
+ char *policy_line = line;
+ char *syscall_name = strsep(&policy_line, ":");
+ int nr = -1;
+ syscall_name = strip(syscall_name);
+
+ /* Allow comments and empty lines. */
+ if (*syscall_name == '#' || *syscall_name == '\0') {
+ /* Reuse |line| in the next getline() call. */
+ continue;
+ }
+
+ policy_line = strip(policy_line);
+ if (*policy_line == '\0') {
+ warn("compile_file: empty policy line");
+ free(line);
+ return -1;
+ }
+
+ nr = lookup_syscall(syscall_name);
+ if (nr < 0) {
+ warn("compile_file: nonexistent syscall '%s'",
+ syscall_name);
+ if (allow_logging) {
+ /*
+ * If we're logging failures, assume we're in a
+ * debugging case and continue.
+ * This is not super risky because an invalid
+ * syscall name is likely caused by a typo or by
+ * leftover lines from a different architecture.
+ * In either case, not including a policy line
+ * is equivalent to killing the process if the
+ * syscall is made, so there's no added attack
+ * surface.
+ */
+ /* Reuse |line| in the next getline() call. */
+ continue;
+ }
+ free(line);
+ return -1;
+ }
+
+ /*
+ * For each syscall, add either a simple ALLOW,
+ * or an arg filter block.
+ */
+ if (strcmp(policy_line, "1") == 0) {
+ /* Add simple ALLOW. */
+ append_allow_syscall(head, nr);
+ } else {
+ /*
+ * Create and jump to the label that will hold
+ * the arg filter block.
+ */
+ unsigned int id = bpf_label_id(labels, syscall_name);
+ struct sock_filter *nr_comp =
+ new_instr_buf(ALLOW_SYSCALL_LEN);
+ bpf_allow_syscall_args(nr_comp, nr, id);
+ append_filter_block(head, nr_comp, ALLOW_SYSCALL_LEN);
+
+ /* Build the arg filter block. */
+ struct filter_block *block = compile_policy_line(
+ nr, policy_line, id, labels, use_ret_trap);
+
+ if (!block) {
+ if (*arg_blocks) {
+ free_block_list(*arg_blocks);
+ }
+ free(line);
+ return -1;
+ }
+
+ if (*arg_blocks) {
+ extend_filter_block_list(*arg_blocks, block);
+ } else {
+ *arg_blocks = block;
+ }
+ }
+ /* Reuse |line| in the next getline() call. */
+ }
+ free(line);
+ return 0;
+}
+
+int compile_filter(FILE *initial_file, struct sock_fprog *prog,
+ int use_ret_trap, int allow_logging)
+{
struct bpf_labels labels;
labels.count = 0;
- if (!policy_file)
+ if (!initial_file) {
+ warn("compile_filter: |initial_file| is NULL");
return -1;
+ }
struct filter_block *head = new_filter_block();
struct filter_block *arg_blocks = NULL;
@@ -458,93 +555,13 @@
if (allow_logging)
allow_logging_syscalls(head);
- /*
- * Loop through all the lines in the policy file.
- * Build a jump table for the syscall number.
- * If the policy line has an arg filter, build the arg filter
- * as well.
- * Chain the filter sections together and dump them into
- * the final buffer at the end.
- */
- while (fgets(line, sizeof(line), policy_file)) {
- ++line_count;
- char *policy_line = line;
- char *syscall_name = strsep(&policy_line, ":");
- int nr = -1;
-
- syscall_name = strip(syscall_name);
-
- /* Allow comments and empty lines. */
- if (*syscall_name == '#' || *syscall_name == '\0')
- continue;
-
- if (strlen(policy_line) == 0) {
- warn("compile_filter: empty policy line");
- free_block_list(head);
- return -1;
- }
-
- nr = lookup_syscall(syscall_name);
- if (nr < 0) {
- warn("compile_filter: nonexistent syscall '%s'",
- syscall_name);
- if (allow_logging) {
- /*
- * If we're logging failures, assume we're in a
- * debugging case and continue.
- * This is not super risky because an invalid
- * syscall name is likely caused by a typo or by
- * leftover lines from a different architecture.
- * In either case, not including a policy line
- * is equivalent to killing the process if the
- * syscall is made, so there's no added attack
- * surface.
- */
- continue;
- }
- free_block_list(head);
- return -1;
- }
-
- policy_line = strip(policy_line);
-
- /*
- * For each syscall, add either a simple ALLOW,
- * or an arg filter block.
- */
- if (strcmp(policy_line, "1") == 0) {
- /* Add simple ALLOW. */
- append_allow_syscall(head, nr);
- } else {
- /*
- * Create and jump to the label that will hold
- * the arg filter block.
- */
- unsigned int id = bpf_label_id(&labels, syscall_name);
- struct sock_filter *nr_comp =
- new_instr_buf(ALLOW_SYSCALL_LEN);
- bpf_allow_syscall_args(nr_comp, nr, id);
- append_filter_block(head, nr_comp, ALLOW_SYSCALL_LEN);
-
- /* Build the arg filter block. */
- struct filter_block *block = compile_section(
- nr, policy_line, id, &labels, use_ret_trap);
-
- if (!block) {
- if (arg_blocks) {
- free_block_list(arg_blocks);
- }
- free_label_strings(&labels);
- free_block_list(head);
- return -1;
- }
-
- if (arg_blocks) {
- extend_filter_block_list(arg_blocks, block);
- } else {
- arg_blocks = block;
- }
- }
+ if (compile_file(initial_file, head, &arg_blocks, &labels, use_ret_trap,
+ allow_logging) != 0) {
+ warn("compile_filter: compile_file() failed");
+ free_block_list(head);
+ free_block_list(arg_blocks);
+ free_label_strings(&labels);
+ return -1;
}
/*
diff --git a/syscall_filter.h b/syscall_filter.h
index 4625d80..3bfbfee 100644
--- a/syscall_filter.h
+++ b/syscall_filter.h
@@ -26,18 +26,22 @@
struct bpf_labels;
-struct filter_block *compile_section(int nr, const char *policy_line,
- unsigned int label_id,
- struct bpf_labels *labels,
- int do_ret_trap);
+struct filter_block *compile_policy_line(int nr, const char *policy_line,
+ unsigned int label_id,
+ struct bpf_labels *labels,
+ int do_ret_trap);
+int compile_file(FILE *policy_file, struct filter_block *head,
+ struct filter_block **arg_blocks, struct bpf_labels *labels,
+ int use_ret_trap, int allow_logging);
int compile_filter(FILE *policy_file, struct sock_fprog *prog, int do_ret_trap,
int add_logging_syscalls);
+struct filter_block *new_filter_block(void);
int flatten_block_list(struct filter_block *head, struct sock_filter *filter,
size_t index, size_t cap);
void free_block_list(struct filter_block *head);
-int seccomp_can_softfail();
+int seccomp_can_softfail(void);
#ifdef __cplusplus
}; /* extern "C" */
diff --git a/syscall_filter_unittest.cc b/syscall_filter_unittest.cc
index 98a1835..4a80976 100644
--- a/syscall_filter_unittest.cc
+++ b/syscall_filter_unittest.cc
@@ -347,7 +347,17 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
+ ASSERT_EQ(block, nullptr);
+}
+
+TEST_F(ArgFilterTest, whitespace_atom) {
+ const char* fragment = "\t ";
+ int nr = 1;
+ unsigned int id = 0;
+
+ struct filter_block* block =
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -357,7 +367,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -367,7 +377,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -376,7 +386,7 @@
int nr = 1;
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
@@ -385,11 +395,11 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison. */
- curr_block = block->next;
+ curr_block = curr_block->next;
EXPECT_COMP(curr_block);
/* Third block is a jump and a label (end of AND group). */
@@ -417,7 +427,7 @@
int nr = 1;
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
@@ -426,11 +436,11 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison. */
- curr_block = block->next;
+ curr_block = curr_block->next;
EXPECT_COMP(curr_block);
/* Third block is a jump and a label (end of AND group). */
@@ -458,7 +468,7 @@
int nr = 1;
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
@@ -467,11 +477,11 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison. */
- curr_block = block->next;
+ curr_block = curr_block->next;
ASSERT_NE(curr_block, nullptr);
EXPECT_COMP(curr_block);
@@ -501,7 +511,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
@@ -510,11 +520,11 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison. */
- curr_block = block->next;
+ curr_block = curr_block->next;
ASSERT_NE(curr_block, nullptr);
EXPECT_COMP(curr_block);
EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
@@ -546,7 +556,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
EXPECT_EQ(block->total_len, exp_total_len);
@@ -554,7 +564,7 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison ("arg0 == 0"). */
@@ -603,7 +613,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
EXPECT_EQ(block->total_len, exp_total_len);
@@ -611,7 +621,7 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison ("arg0 == 0"). */
@@ -658,7 +668,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 2;
EXPECT_EQ(block->total_len, exp_total_len);
@@ -666,7 +676,7 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is SECCOMP_RET_ERRNO. */
@@ -688,7 +698,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -698,7 +708,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -708,7 +718,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -718,7 +728,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -728,7 +738,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -738,7 +748,7 @@
unsigned int id = 0;
struct filter_block* block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -748,7 +758,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_EQ(block, nullptr);
}
@@ -757,7 +767,7 @@
int nr = 1;
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, USE_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, USE_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
@@ -766,11 +776,11 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison. */
- curr_block = block->next;
+ curr_block = curr_block->next;
ASSERT_NE(curr_block, nullptr);
EXPECT_COMP(curr_block);
@@ -800,7 +810,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, NO_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
EXPECT_EQ(block->total_len, exp_total_len);
@@ -808,7 +818,7 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison ("arg0 == 0"). */
@@ -844,7 +854,7 @@
unsigned int id = 0;
struct filter_block *block =
- compile_section(nr, fragment, id, &labels_, USE_LOGGING);
+ compile_policy_line(nr, fragment, id, &labels_, USE_LOGGING);
ASSERT_NE(block, nullptr);
size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
EXPECT_EQ(block->total_len, exp_total_len);
@@ -852,7 +862,7 @@
/* First block is a label. */
struct filter_block *curr_block = block;
ASSERT_NE(curr_block, nullptr);
- EXPECT_EQ(block->len, 1U);
+ EXPECT_EQ(curr_block->len, 1U);
EXPECT_LBL(curr_block->instrs);
/* Second block is a comparison ("arg0 == 0"). */
@@ -920,6 +930,126 @@
return fdopen(pipefd[0], "r");
}
+class FileTest : public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ labels_.count = 0;
+ head_ = new_filter_block();
+ arg_blocks_ = NULL;
+ }
+ virtual void TearDown() {
+ free_label_strings(&labels_);
+ free_block_list(head_);
+ free_block_list(arg_blocks_);
+ }
+ struct bpf_labels labels_;
+ struct filter_block *head_;
+ struct filter_block *arg_blocks_;
+};
+
+TEST_F(FileTest, seccomp_mode1) {
+ // struct sock_fprog actual;
+ const char *policy =
+ "read: 1\n"
+ "write: 1\n"
+ "rt_sigreturn: 1\n"
+ "exit: 1\n";
+
+ FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
+ ASSERT_NE(policy_file, nullptr);
+ int res = compile_file(
+ policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING);
+ fclose(policy_file);
+
+ /*
+ * Checks return value and that the blocks only allow expected syscalls.
+ */
+ ASSERT_EQ(res, 0);
+ struct filter_block *curr_block = head_;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
+
+ EXPECT_EQ(curr_block->next, nullptr);
+}
+
+TEST_F(FileTest, seccomp_read) {
+ const char *policy =
+ "read: arg0 == 0\n"
+ "write: 1\n"
+ "rt_sigreturn: 1\n"
+ "exit: 1\n";
+
+ const int LABEL_ID = 0;
+
+ FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
+ ASSERT_NE(policy_file, nullptr);
+ int res = compile_file(
+ policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING);
+ fclose(policy_file);
+
+ /*
+ * Checks return value, that the blocks only allow expected syscalls, and that
+ * labels between |head_| and |arg_blocks_| match.
+ */
+ ASSERT_EQ(res, 0);
+ struct filter_block *curr_block = head_;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
+ __NR_read,
+ LABEL_ID,
+ JUMP_JT,
+ JUMP_JF);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
+
+ ASSERT_NE(arg_blocks_, nullptr);
+ size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
+ EXPECT_EQ(arg_blocks_->total_len, exp_total_len);
+
+ /* First block is a label. */
+ curr_block = arg_blocks_;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_EQ(curr_block->len, 1U);
+ EXPECT_ACTUAL_LBL(curr_block->instrs, LABEL_ID);
+
+ /* Second block is a comparison. */
+ curr_block = curr_block->next;
+ EXPECT_COMP(curr_block);
+
+ /* Third block is a jump and a label (end of AND group). */
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_GROUP_END(curr_block);
+
+ /* Fourth block is SECCOMP_RET_KILL. */
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_KILL(curr_block);
+
+ /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
+ curr_block = curr_block->next;
+ ASSERT_NE(curr_block, nullptr);
+ EXPECT_ALLOW(curr_block);
+
+ EXPECT_EQ(curr_block->next, nullptr);
+}
+
TEST(FilterTest, seccomp_mode1) {
struct sock_fprog actual;
const char *policy =
@@ -1047,7 +1177,19 @@
FILE* policy_file = write_policy_to_pipe(policy, strlen(policy));
ASSERT_NE(policy_file, nullptr);
- int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
+ int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
+ fclose(policy_file);
+ ASSERT_NE(res, 0);
+}
+
+TEST(FilterTest, whitespace_atom) {
+ struct sock_fprog actual;
+ const char* policy = "open:\t \n";
+
+ FILE* policy_file = write_policy_to_pipe(policy, strlen(policy));
+ ASSERT_NE(policy_file, nullptr);
+
+ int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
fclose(policy_file);
ASSERT_NE(res, 0);
}
@@ -1059,7 +1201,7 @@
FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
ASSERT_NE(policy_file, nullptr);
- int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
+ int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
fclose(policy_file);
ASSERT_NE(res, 0);
}
@@ -1071,14 +1213,14 @@
FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
ASSERT_NE(policy_file, nullptr);
- int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
+ int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
fclose(policy_file);
ASSERT_NE(res, 0);
}
TEST(FilterTest, nonexistent) {
struct sock_fprog actual;
- int res = compile_filter(NULL, &actual, 0, NO_LOGGING);
+ int res = compile_filter(NULL, &actual, USE_RET_KILL, NO_LOGGING);
ASSERT_NE(res, 0);
}
diff --git a/syscall_filter_unittest_macros.h b/syscall_filter_unittest_macros.h
index 81ec67c..02bac89 100644
--- a/syscall_filter_unittest_macros.h
+++ b/syscall_filter_unittest_macros.h
@@ -44,6 +44,14 @@
EXPECT_TRUE((_block)->jf == LABEL_JF); \
} while (0)
+#define EXPECT_ACTUAL_LBL(_block, _id) \
+do { \
+ EXPECT_TRUE((_block)->code == (BPF_JMP+BPF_JA)); \
+ EXPECT_TRUE((_block)->k == (_id)); \
+ EXPECT_TRUE((_block)->jt == LABEL_JT); \
+ EXPECT_TRUE((_block)->jf == LABEL_JF); \
+} while (0)
+
#define EXPECT_JUMP_LBL(_block) \
do { \
EXPECT_EQ((_block)->code, BPF_JMP+BPF_JA); \