aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--cooker/filter.c45
-rw-r--r--tests/unit/test_filter_build.c498
2 files changed, 261 insertions, 282 deletions
diff --git a/cooker/filter.c b/cooker/filter.c
index ef76835..77961d0 100644
--- a/cooker/filter.c
+++ b/cooker/filter.c
@@ -42,7 +42,6 @@ static void set_no_args(struct bpf_entry *entry)
static unsigned int get_number_entries(long nr)
{
struct filter_call_input *call = filter_input + nr;
-
return call->count;
}
@@ -58,9 +57,9 @@ static bool has_args(long nr)
{
struct filter_call_input *call = filter_input + nr;
- if (call-> count < 1)
+ if (call->count < 1)
return false;
- if(call-> ignore_args)
+ if (call->ignore_args)
return false;
/* Check if the first entry has some arguments */
@@ -127,7 +126,6 @@ static unsigned int get_n_args_syscall_instr(long nr)
* accept */
if (has_args(nr))
total_instr++;
-
return total_instr;
}
@@ -135,7 +133,8 @@ static unsigned int get_n_args_syscall_instr(long nr)
* filter_notify() - Start of notification request, check/flush previous one
* @nr: System call number, -1 to just flush previous request
*/
-void filter_notify(long nr) {
+void filter_notify(long nr)
+{
struct filter_call_input *call = filter_input + nr;
if (nr >= 0) {
@@ -161,9 +160,8 @@ void filter_add_arg(int index, struct bpf_arg arg)
call->ignore_args = true;
return;
}
- if(call->ignore_args)
+ if (call->ignore_args)
return;
-
call->entries[call->count] = index_entries;
memcpy(&entry->args[index], &arg, sizeof(arg));
}
@@ -200,7 +198,6 @@ static long get_syscall(unsigned int i)
return (long)table[i];
}
-
static unsigned int count_shift_right(unsigned int n)
{
unsigned int i = 0;
@@ -433,14 +430,21 @@ static unsigned int and_ne(struct sock_filter filter[], int idx,
static unsigned int insert_args(struct sock_filter filter[], long nr)
{
struct filter_call_input *call = filter_input + nr;
- unsigned int i, k, size, next_offset, n_checks = 0;
+ unsigned int next_offset, n_checks = 0;
unsigned int count = get_number_entries(nr);
struct bpf_entry *entry;
unsigned int offset = 0;
+ unsigned int size = 0;
+ unsigned int i, k;
for (i = 0; i < count; i++) {
n_checks = 0;
entry = &entries[call->entries[i]];
+ /* If there are multiple entries for the syscall @nr, then the next group
+ * of arguments to check (i.e. the next offset) is after the number of
+ * arguments of the current entry. The next_offset is used to
+ * jump to the next group if the check is false.
+ */
next_offset = get_args_for_entry(entry);
for (k = 0; k < 6; k++) {
offset = next_offset - n_checks;
@@ -477,6 +481,8 @@ static unsigned int insert_args(struct sock_filter filter[], long nr)
}
n_checks++;
}
+ /* If there were no arguments for this entry, then we don't need
+ * to add the notification */
if (n_checks > 0)
filter[size++] = (struct sock_filter)BPF_STMT(
BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF);
@@ -485,7 +491,7 @@ static unsigned int insert_args(struct sock_filter filter[], long nr)
return size;
}
-unsigned int filter_build(struct sock_filter filter[], unsigned n)
+unsigned int filter_build(struct sock_filter filter[], unsigned n)
{
unsigned int offset_left, offset_right;
unsigned int n_nodes, notify, accept;
@@ -523,11 +529,11 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n)
filter[size++] =
(struct sock_filter)JUMPA(accept - size);
} else {
- nr = get_syscall(i);
+ nr = get_syscall(nodes[i]);
offset_left = left_child(i) - i - 1;
offset_right = right_child(i) - i - 1;
filter[size++] = (struct sock_filter)JGE(
- get_syscall(i), offset_right, offset_left);
+ nr, offset_right, offset_left);
}
}
@@ -535,14 +541,17 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n)
/* Insert leaves */
for (i = 0; i < n; i++) {
nr = get_syscall(i);
- if (get_number_entries(nr) > 0)
+ if (get_number_entries(nr) > 0) {
offset = next_offset;
- else
- /* If the syscall doesn't have any arguments, then notify */
+ } else {
+ /* If the syscall doesn't have any arguments, then notify */
offset = notify - size - 1;
- filter[size++] = (struct sock_filter)EQ(nr,
- offset,
- accept - size);
+ }
+ filter[size++] =
+ (struct sock_filter)EQ(nr, offset, accept - size);
+ /* The arguments block of the next entry are after the total
+ * number of the instructions for checking the arguments of the current entry
+ */
next_offset += get_n_args_syscall_instr(nr) - 1;
}
/* Seccomp accept and notify instruction */
diff --git a/tests/unit/test_filter_build.c b/tests/unit/test_filter_build.c
index b4f1a2c..00d5180 100644
--- a/tests/unit/test_filter_build.c
+++ b/tests/unit/test_filter_build.c
@@ -100,270 +100,240 @@ START_TEST(test_single_instr_two_args)
filter_write(tfilter);
size = read_filter(result, tfilter);
- bpf_disasm_all(result, size);
ck_assert_uint_eq(size, ARRAY_SIZE(expected));
ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
}
END_TEST
-//START_TEST(test_two_instr)
-//{
-// unsigned int size;
-// struct bpf_call calls[] = {
-// { .name = "test1" },
-// { .name = "test2" },
-// };
-// struct syscall_entry table[] = {
-// { .count = 1, .nr = 42, .entry = &calls[0] },
-// { .count = 1, .nr = 49, .entry = &calls[1] },
-// };
-// struct sock_filter expected[] = {
-// /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, arch))),
-// /* l1 */
-// BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
-// /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l3 */
-// BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, nr))),
-// /* ------- level0 -------- */
-// /* l4 */ JGE(49, 1, 0),
-// /* ------- leaves -------- */
-// /* l5 */ EQ(42, 2, 1),
-// /* l6 */ EQ(49, 1, 0),
-// /* l7 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l8 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// };
-// struct sock_filter result[30];
-//
-// size = create_bfp_program(table, result,
-// sizeof(table) / sizeof(table[0]));
-// ck_assert_uint_eq(size, sizeof(expected) / sizeof(expected[0]));
-// ck_assert(filter_eq(expected, result,
-// sizeof(expected) / sizeof(expected[0])));
-//}
-//END_TEST
-//
-//START_TEST(test_multiple_instr_no_args)
-//{
-// unsigned int size;
-// struct bpf_call calls[] = {
-// { .name = "test1" }, { .name = "test2" }, { .name = "test3" },
-// { .name = "test4" }, { .name = "test5" },
-// };
-// struct syscall_entry table[] = {
-// { .count = 1, .nr = 42, .entry = &calls[0] },
-// { .count = 1, .nr = 43, .entry = &calls[1] },
-// { .count = 1, .nr = 44, .entry = &calls[2] },
-// { .count = 1, .nr = 45, .entry = &calls[3] },
-// { .count = 1, .nr = 46, .entry = &calls[4] },
-// };
-// struct sock_filter expected[] = {
-// /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, arch))),
-// /* l1 */
-// BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
-// /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l3 */
-// BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, nr))),
-// /* ------- level0 -------- */
-// /* l4 */ JGE(46, 1, 0),
-// /* ------- level1 -------- */
-// /* l5 */ JGE(45, 2, 1),
-// /* l6 */ JGE(46, 3, 2),
-// /* ------- level2 -------- */
-// /* l7 */ JGE(43, 4, 3),
-// /* l8 */ JGE(45, 5, 4),
-// /* l9 */ JGE(46, 6, 5),
-// /* l10 */ JUMPA(5),
-// /* -------- leaves ------- */
-// /* l11 */ EQ(42, 5, 4),
-// /* l12 */ EQ(43, 4, 3),
-// /* l13 */ EQ(44, 3, 2),
-// /* l14 */ EQ(45, 2, 1),
-// /* l15 */ EQ(46, 1, 0),
-// /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// };
-// struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
-//
-// size = create_bfp_program(table, result,
-// sizeof(table) / sizeof(table[0]));
-// ck_assert_uint_eq(size, sizeof(expected) / sizeof(expected[0]));
-// ck_assert(filter_eq(expected, result,
-// sizeof(expected) / sizeof(expected[0])));
-//}
-//END_TEST
-//
-//START_TEST(test_multiple_instr_with_args)
-//{
-// unsigned int size;
-// struct bpf_call calls[] = {
-// { .name = "test1",
-// .args = { [1] = { .cmp = EQ,
-// .value = { .v32 = 123 },
-// .type = BPF_U32 },
-// [2] = { .cmp = EQ,
-// .value = { .v32 = 321 },
-// .type = BPF_U32 } } },
-// { .name = "test2" },
-// { .name = "test3" },
-// { .name = "test4",
-// .args = { [1] = { .cmp = EQ,
-// .value = { .v32 = 123 },
-// .type = BPF_U32 },
-// [2] = { .cmp = EQ,
-// .value = { .v32 = 321 },
-// .type = BPF_U32 } } },
-// { .name = "test5" },
-// };
-// struct syscall_entry table[] = {
-// { .count = 1, .nr = 42, .entry = &calls[0] },
-// { .count = 1, .nr = 43, .entry = &calls[1] },
-// { .count = 1, .nr = 44, .entry = &calls[2] },
-// { .count = 1, .nr = 45, .entry = &calls[3] },
-// { .count = 1, .nr = 46, .entry = &calls[4] },
-// };
-// struct sock_filter expected[] = {
-// /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, arch))),
-// /* l1 */
-// BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
-// /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l3 */
-// BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, nr))),
-// /* ------- level0 -------- */
-// /* l4 */ JGE(46, 1, 0),
-// /* ------- level1 -------- */
-// /* l5 */ JGE(45, 2, 1),
-// /* l6 */ JGE(46, 3, 2),
-// /* ------- level2 -------- */
-// /* l7 */ JGE(43, 4, 3),
-// /* l8 */ JGE(45, 5, 4),
-// /* l9 */ JGE(46, 6, 5),
-// /* l10 */ JUMPA(5),
-// /* -------- leaves ------- */
-// /* l11 */ EQ(42, 6, 4),
-// /* l12 */ EQ(43, 4, 3),
-// /* l13 */ EQ(44, 3, 2),
-// /* l14 */ EQ(45, 9, 1),
-// /* l15 */ EQ(46, 1, 0),
-// /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* ------- args ---------- */
-// /* l18 */ LOAD(offsetof(struct seccomp_data, args[1])),
-// /* l19 */ EQ(123, 0, 2),
-// /* l20 */ LOAD(offsetof(struct seccomp_data, args[2])),
-// /* l21 */ EQ(321, 0, 1),
-// /* l22 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l23 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* ----- end call42 ------ */
-// /* l24 */ LOAD(offsetof(struct seccomp_data, args[1])),
-// /* l25 */ EQ(123, 0, 2),
-// /* l26 */ LOAD(offsetof(struct seccomp_data, args[2])),
-// /* l27 */ EQ(321, 0, 1),
-// /* l28 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l29 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* ----- end call45 ------ */
-// };
-// struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
-//
-// size = create_bfp_program(table, result,
-// sizeof(table) / sizeof(table[0]));
-// // bpf_disasm_all(result, size);
-// ck_assert_uint_eq(size, sizeof(expected) / sizeof(expected[0]));
-// ck_assert(filter_eq(expected, result,
-// sizeof(expected) / sizeof(expected[0])));
-//}
-//END_TEST
-//
-//START_TEST(test_multiple_instance_same_instr)
-//{
-// unsigned int size;
-// struct bpf_call calls[] = {
-// { .name = "test1",
-// .args = { [1] = { .cmp = EQ,
-// .value = { .v32 = 123 },
-// .type = BPF_U32 } } },
-// { .name = "test1",
-// .args = { [2] = { .cmp = EQ,
-// .value = { .v32 = 321 },
-// .type = BPF_U32 } } },
-// { .name = "test2" },
-// { .name = "test3" },
-// { .name = "test4",
-// .args = { [1] = { .cmp = EQ,
-// .value = { .v32 = 123 },
-// .type = BPF_U32 } } },
-// { .name = "test4",
-// .args = { [2] = { .cmp = EQ,
-// .value = { .v32 = 321 },
-// .type = BPF_U32 } } },
-// { .name = "test5" },
-// };
-// struct syscall_entry table[] = {
-// { .count = 2, .nr = 42, .entry = &calls[0] },
-// { .count = 1, .nr = 43, .entry = &calls[2] },
-// { .count = 1, .nr = 44, .entry = &calls[3] },
-// { .count = 2, .nr = 45, .entry = &calls[4] },
-// { .count = 1, .nr = 46, .entry = &calls[6] },
-// };
-// struct sock_filter expected[] = {
-// /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, arch))),
-// /* l1 */
-// BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
-// /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l3 */
-// BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
-// (offsetof(struct seccomp_data, nr))),
-// /* ------- level0 -------- */
-// /* l4 */ JGE(46, 1, 0),
-// /* ------- level1 -------- */
-// /* l5 */ JGE(45, 2, 1),
-// /* l6 */ JGE(46, 3, 2),
-// /* ------- level2 -------- */
-// /* l7 */ JGE(43, 4, 3),
-// /* l8 */ JGE(45, 5, 4),
-// /* l9 */ JGE(46, 6, 5),
-// /* l10 */ JUMPA(5),
-// /* -------- leaves ------- */
-// /* l11 */ EQ(42, 6, 4),
-// /* l12 */ EQ(43, 4, 3),
-// /* l13 */ EQ(44, 3, 2),
-// /* l14 */ EQ(45, 10, 1),
-// /* l15 */ EQ(46, 1, 0),
-// /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* ------- args ---------- */
-// /* l18 */ LOAD(offsetof(struct seccomp_data, args[1])),
-// /* l19 */ EQ(123, 0, 1),
-// /* l20 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l21 */ LOAD(offsetof(struct seccomp_data, args[2])),
-// /* l22 */ EQ(321, 0, 1),
-// /* l23 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l24 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* ----- end call42 ------ */
-// /* l25 */ LOAD(offsetof(struct seccomp_data, args[1])),
-// /* l26 */ EQ(123, 0, 1),
-// /* l27 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l28 */ LOAD(offsetof(struct seccomp_data, args[2])),
-// /* l29 */ EQ(321, 0, 1),
-// /* l30 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
-// /* l31 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
-// /* ----- end call44 ------ */
-// };
-// struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
-//
-// size = create_bfp_program(table, result,
-// sizeof(table) / sizeof(table[0]));
-// ck_assert_uint_eq(size, sizeof(expected) / sizeof(expected[0]));
-// ck_assert(filter_eq(expected, result,
-// sizeof(expected) / sizeof(expected[0])));
-//}
-//END_TEST
+START_TEST(test_two_instr)
+{
+ unsigned int size;
+ struct sock_filter expected[] = {
+ /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, arch))),
+ /* l1 */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
+ /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l3 */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ /* ------- level0 -------- */
+ /* l4 */ JGE(49, 1, 0),
+ /* ------- leaves -------- */
+ /* l5 */ EQ(42, 2, 1),
+ /* l6 */ EQ(49, 1, 0),
+ /* l7 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l8 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ };
+ struct sock_filter result[30];
+ filter_notify(42);
+ filter_notify(49);
+
+ filter_write(tfilter);
+ size = read_filter(result, tfilter);
+
+ ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+ ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
+}
+END_TEST
+
+START_TEST(test_multiple_instr_no_args)
+{
+ unsigned int size;
+ struct sock_filter expected[] = {
+ /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, arch))),
+ /* l1 */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
+ /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l3 */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ /* ------- level0 -------- */
+ /* l4 */ JGE(46, 1, 0),
+ /* ------- level1 -------- */
+ /* l5 */ JGE(45, 2, 1),
+ /* l6 */ JGE(46, 3, 2),
+ /* ------- level2 -------- */
+ /* l7 */ JGE(43, 4, 3),
+ /* l8 */ JGE(45, 5, 4),
+ /* l9 */ JGE(46, 6, 5),
+ /* l10 */ JUMPA(5),
+ /* -------- leaves ------- */
+ /* l11 */ EQ(42, 5, 4),
+ /* l12 */ EQ(43, 4, 3),
+ /* l13 */ EQ(44, 3, 2),
+ /* l14 */ EQ(45, 2, 1),
+ /* l15 */ EQ(46, 1, 0),
+ /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ };
+ struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
+
+ filter_notify(42);
+ filter_notify(43);
+ filter_notify(44);
+ filter_notify(45);
+ filter_notify(46);
+
+ filter_write(tfilter);
+ size = read_filter(result, tfilter);
+
+ ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+ ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
+}
+END_TEST
+
+START_TEST(test_multiple_instr_with_args)
+{
+ unsigned int size;
+ struct bpf_arg a1 = { .cmp = EQ,
+ .value = { .v32 = 0x123 },
+ .type = BPF_U32 };
+ struct bpf_arg a2 = { .cmp = EQ,
+ .value = { .v32 = 0x321 },
+ .type = BPF_U32 };
+ struct sock_filter expected[] = {
+ /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, arch))),
+ /* l1 */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
+ /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l3 */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ /* ------- level0 -------- */
+ /* l4 */ JGE(46, 1, 0),
+ /* ------- level1 -------- */
+ /* l5 */ JGE(45, 2, 1),
+ /* l6 */ JGE(46, 3, 2),
+ /* ------- level2 -------- */
+ /* l7 */ JGE(43, 4, 3),
+ /* l8 */ JGE(45, 5, 4),
+ /* l9 */ JGE(46, 6, 5),
+ /* l10 */ JUMPA(5),
+ /* -------- leaves ------- */
+ /* l11 */ EQ(42, 6, 4),
+ /* l12 */ EQ(43, 4, 3),
+ /* l13 */ EQ(44, 3, 2),
+ /* l14 */ EQ(45, 9, 1),
+ /* l15 */ EQ(46, 1, 0),
+ /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* ------- args ---------- */
+ /* l18 */ LOAD(offsetof(struct seccomp_data, args[1])),
+ /* l19 */ EQ(0x123, 0, 2),
+ /* l20 */ LOAD(offsetof(struct seccomp_data, args[2])),
+ /* l21 */ EQ(0x321, 0, 1),
+ /* l22 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l23 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* ----- end call42 ------ */
+ /* l24 */ LOAD(offsetof(struct seccomp_data, args[1])),
+ /* l25 */ EQ(0x123, 0, 2),
+ /* l26 */ LOAD(offsetof(struct seccomp_data, args[2])),
+ /* l27 */ EQ(0x321, 0, 1),
+ /* l28 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l29 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* ----- end call45 ------ */
+ };
+ struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
+ filter_notify(42);
+ filter_add_arg(1, a1);
+ filter_add_arg(2, a2);
+ filter_flush_args();
+ filter_notify(43);
+ filter_notify(44);
+ filter_notify(45);
+ filter_add_arg(1, a1);
+ filter_add_arg(2, a2);
+ filter_flush_args();
+ filter_notify(46);
+
+ filter_write(tfilter);
+ size = read_filter(result, tfilter);
+
+ ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+ ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
+}
+END_TEST
+
+START_TEST(test_multiple_instance_same_instr)
+{
+ unsigned int size;
+ struct bpf_arg a1 = { .cmp = EQ,
+ .value = { .v32 = 0x123 },
+ .type = BPF_U32 };
+ struct bpf_arg a2 = { .cmp = EQ,
+ .value = { .v32 = 0x321 },
+ .type = BPF_U32 };
+ struct sock_filter expected[] = {
+ /* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, arch))),
+ /* l1 */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 1, 0),
+ /* l2 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l3 */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ /* ------- level0 -------- */
+ /* l4 */ JGE(46, 1, 0),
+ /* ------- level1 -------- */
+ /* l5 */ JGE(45, 2, 1),
+ /* l6 */ JGE(46, 3, 2),
+ /* ------- level2 -------- */
+ /* l7 */ JGE(43, 4, 3),
+ /* l8 */ JGE(45, 5, 4),
+ /* l9 */ JGE(46, 6, 5),
+ /* l10 */ JUMPA(5),
+ /* -------- leaves ------- */
+ /* l11 */ EQ(42, 6, 4),
+ /* l12 */ EQ(43, 4, 3),
+ /* l13 */ EQ(44, 3, 2),
+ /* l14 */ EQ(45, 10, 1),
+ /* l15 */ EQ(46, 1, 0),
+ /* l16 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* l17 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* ------- args ---------- */
+ /* l18 */ LOAD(offsetof(struct seccomp_data, args[1])),
+ /* l19 */ EQ(0x123, 0, 1),
+ /* l20 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l21 */ LOAD(offsetof(struct seccomp_data, args[2])),
+ /* l22 */ EQ(0x321, 0, 1),
+ /* l23 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l24 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* ----- end call42 ------ */
+ /* l25 */ LOAD(offsetof(struct seccomp_data, args[1])),
+ /* l26 */ EQ(0x123, 0, 1),
+ /* l27 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l28 */ LOAD(offsetof(struct seccomp_data, args[2])),
+ /* l29 */ EQ(0x321, 0, 1),
+ /* l30 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+ /* l31 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* ----- end call45 ------ */
+ };
+ struct sock_filter result[sizeof(expected) / sizeof(expected[0]) + 10];
+
+ filter_notify(42);
+ filter_add_arg(1, a1);
+ filter_flush_args();
+ filter_add_arg(2, a2);
+ filter_flush_args();
+ filter_notify(43);
+ filter_notify(44);
+ filter_notify(45);
+ filter_add_arg(1, a1);
+ filter_flush_args();
+ filter_add_arg(2, a2);
+ filter_flush_args();
+ filter_notify(46);
+
+ filter_write(tfilter);
+ size = read_filter(result, tfilter);
+
+ ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+ ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
+}
+END_TEST
Suite *bpf_suite(void)
{
@@ -376,13 +346,13 @@ Suite *bpf_suite(void)
tcase_add_test(tsingle_instr, test_single_instr);
tcase_add_test(tsingle_instr, test_single_instr_two_args);
- //tcase_add_test(tmultiple_instr, test_two_instr);
- //tcase_add_test(tmultiple_instr, test_multiple_instr_no_args);
- //tcase_add_test(tmultiple_instr, test_multiple_instr_with_args);
- //tcase_add_test(tmultiple_instr, test_multiple_instance_same_instr);
+ tcase_add_test(tmultiple_instr, test_two_instr);
+ tcase_add_test(tmultiple_instr, test_multiple_instr_no_args);
+ tcase_add_test(tmultiple_instr, test_multiple_instr_with_args);
+ tcase_add_test(tmultiple_instr, test_multiple_instance_same_instr);
suite_add_tcase(s, tsingle_instr);
- //suite_add_tcase(s, tmultiple_instr);
+ suite_add_tcase(s, tmultiple_instr);
return s;
}