From 876a52e95a9d24a4b9fa37325d83bcb7d3c7b160 Mon Sep 17 00:00:00 2001
From: Alice Frosi <afrosi@redhat.com>
Date: Fri, 30 Jun 2023 11:22:52 +0200
Subject: test: fix filter-build test and bugs

The tests for checking the filter build recompile and are successfull.

Changes:
  - spotted a couple of bugs for adding the arguments in the filter
  - readded function `filter_flush_args` to flush_args; this is needed
    to distinguish when the arguments belong to the same block or are different
    entries to the same syscall
  - build the filter in a way that CMP_EQ corresponds to BPF_JEQ and we
    don't need to awkwardly negate the operations (still TODO for AND_EQ)
---
 common/gluten.h                |   1 -
 cooker/emit.c                  |   2 -
 cooker/filter.c                |  76 ++++++++++----------------
 cooker/filter.h                |   2 +-
 cooker/match.c                 |   1 +
 tests/unit/Makefile            |  23 ++++----
 tests/unit/test_filter_build.c | 121 +++++++++++++++++++++--------------------
 tests/unit/testutil.h          |   4 +-
 tests/unit/util.c              |  19 ++++++-
 9 files changed, 125 insertions(+), 124 deletions(-)

diff --git a/common/gluten.h b/common/gluten.h
index f3ef47d..83cfbc3 100644
--- a/common/gluten.h
+++ b/common/gluten.h
@@ -34,7 +34,6 @@ extern struct seccomp_data anonymous_seccomp_data;
 #define OP_EMPTY { .block = { -1 } }
 #define NO_FIELD block
 
-#define NS_NUM sizeof(enum ns_type)
 #define GET_BIT(x, i) (((x) & (1UL << (i))) != 0)
 
 enum gluten_offset_type {
diff --git a/cooker/emit.c b/cooker/emit.c
index ee52b17..28afd29 100644
--- a/cooker/emit.c
+++ b/cooker/emit.c
@@ -559,8 +559,6 @@ void emit_bpf_arg(int index, enum type type, union value v, union value mask,
 	 */
 	if (mask.v_num)
 		bpf.cmp = (cmp == CMP_EQ) ? AND_NE : AND_EQ;
-	else
-		bpf.cmp = (cmp == CMP_EQ) ? NE : EQ;
 
 	bpf.arg = index;
 
diff --git a/cooker/filter.c b/cooker/filter.c
index c7e0ee4..4a06111 100644
--- a/cooker/filter.c
+++ b/cooker/filter.c
@@ -13,7 +13,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <util.h>
+#include "util.h"
 
 #include "filter.h"
 
@@ -37,29 +37,12 @@ struct bpf_entry {
 struct filter_call_input {
 	bool notify;
 	bool ignore_args;
+	unsigned int count;
 	struct bpf_entry entry[MAX_ENTRIES_PER_SYSCALL];
 } filter_input[N_SYSCALL] = { 0 };
 
 static long current_nr;
 
-/**
- * entry_has_check() - Input stage: does the syscall entry need argument checks?
- * @entry:	syscall entry with field checks
- *
- * Return: true if at least one argument comparison is requested
- */
-static bool entry_has_check(const struct bpf_entry *entry)
-{
-	unsigned i;
-
-	for (i = 0; i < MAX_FIELDS_PER_SYSCALL; i++) {
-		if (entry->field[i].cmp != NO_CHECK)
-			return true;
-	}
-
-	return false;
-}
-
 /**
  * call_entry_count() - Input stage: count of entries for the same syscall
  * @nr:		syscall number
@@ -69,19 +52,8 @@ static bool entry_has_check(const struct bpf_entry *entry)
 static unsigned int call_entry_count(long nr)
 {
 	struct filter_call_input *call = filter_input + nr;
-	unsigned i, count = 0;
-
-	if (!call->notify || call->ignore_args)
-		return 0;
-
-	for (i = 0; i < MAX_ENTRIES_PER_SYSCALL; i++) {
-		if (entry_has_check(&call->entry[i]))
-			count++;
-		else
-			break;
-	}
 
-	return count;
+	return call->count;
 }
 
 /**
@@ -170,6 +142,17 @@ void filter_needs_deref(void)
 	call->ignore_args = true;
 }
 
+void filter_flush_args(long nr)
+{
+	struct filter_call_input *call = filter_input + nr;
+	struct bpf_entry *entry = &call->entry[(call->count)];
+
+	if (entry_check_count(entry) > 0)
+		call->count++;
+	if (call->count > MAX_FIELDS_PER_SYSCALL)
+		call->ignore_args = true;
+}
+
 /* Calculate how many instruction for the syscall */
 static unsigned int get_n_args_syscall_instr(long nr)
 {
@@ -469,6 +452,9 @@ static unsigned int insert_args(struct sock_filter filter[], long nr)
 	unsigned int size = 0;
 	unsigned int i, j;
 
+	/* No entries, hence no arguments for the @nr syscall */
+	if (count <= 0)
+		return 0;
 	for (i = 0; i < count; i++) {
 		n_checks = 0;
 		entry = &call->entry[i];
@@ -478,10 +464,14 @@ static unsigned int insert_args(struct sock_filter filter[], long nr)
 		 * jump to the next group if the check is false.
 		 */
 		next_offset = entry_check_count(entry);
-		for (j = 0; j < entry_check_count(entry); j++) {
+		for (j = 0; j <= entry_check_count(entry); j++) {
 			struct bpf_field *field = &entry->field[j];
-
+			/* If the current argument isn't the last argument (offset = 1),
+			 * add an additional jump as there is seccomp notify instruction
+			 * before the allow one.
+			 */
 			offset = next_offset - n_checks;
+			offset += (offset > 1) ? 1 : 0;
 			switch (field->cmp) {
 			case NO_CHECK:
 				continue;
@@ -512,12 +502,10 @@ 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++] = STMT(BPF_RET | BPF_K,
-					      SECCOMP_RET_ALLOW);
+			filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF);
 	}
+	filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW);
 
 	return size;
 }
@@ -571,7 +559,7 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n)
 	for (i = 0; i < n; i++) {
 		nr = get_syscall(i);
 		if (call_entry_count(nr) > 0) {
-			offset = next_offset - 1;
+			offset = next_offset;
 		} else {
 			/* If the syscall doesn't have any arguments, then notify */
 			offset = notify - size - 1;
@@ -584,21 +572,15 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n)
 	}
 	/* Seccomp accept and notify instruction */
 	filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW);
-	if (!call_entry_count(nr))
-		filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF);
-
+	filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF);
 
 	/*
 	 * Insert args. It sequentially checks all the arguments for a syscall
 	 * entry. If a check on the argument isn't equal then it jumps to
 	 * check the following entry of the syscall and its arguments.
 	 */
-	for (i = 0; i < n; i++) {
-		size += insert_args(&filter[size], nr);
-		if (call_entry_count(nr))
-			filter[size++] = STMT(BPF_RET | BPF_K,
-					      SECCOMP_RET_USER_NOTIF);
-	}
+	for (i = 0; i < n; i++)
+		size += insert_args(&filter[size], get_syscall(i));
 
 	debug("  BPF: filter with %i call%s has %i instructions",
 	      n, n != 1 ? "s" : "", size);
diff --git a/cooker/filter.h b/cooker/filter.h
index 8efdc47..c152b2e 100644
--- a/cooker/filter.h
+++ b/cooker/filter.h
@@ -70,5 +70,5 @@ void filter_notify(long nr);
 void filter_needs_deref(void);
 void filter_add_check(struct bpf_field *field);
 void filter_write(const char *path);
-
+void filter_flush_args(long nr);
 #endif
diff --git a/cooker/match.c b/cooker/match.c
index c1f5fa8..c83f9fe 100644
--- a/cooker/match.c
+++ b/cooker/match.c
@@ -381,6 +381,7 @@ void handle_matches(struct gluten_ctx *g, JSON_Value *value)
 
 				filter_notify(call->number);
 				parse_match(g, args, call->args);
+				filter_flush_args(call->number);
 
 				break;
 			}
diff --git a/tests/unit/Makefile b/tests/unit/Makefile
index 1a7f70a..76f815e 100644
--- a/tests/unit/Makefile
+++ b/tests/unit/Makefile
@@ -4,29 +4,30 @@
 
 MAIN_DIR := ../../
 COMMON_DIR := ../../common
-OP_DIR := ../../
 COOKER_DIR := ../../cooker
 DBG_DIR := ../../debug
 
-SRCS_FILTER_BUILD := $(COOKER_DIR)/filter.c $(DBG_DIR)/disasm.c $(COMMON_DIR)/common.c
-HEADERS_FILTER_BUILD := $(COOKER_DIR)/filter.h $(DBG_DIR)/disasm.h $(COMMON_DIR)/common.h
+SRCS_FILTER_BUILD := $(COOKER_DIR)/filter.c $(DBG_DIR)/disasm.c $(COMMON_DIR)/common.c \
+		     $(COMMON_DIR)/util.c
+HEADERS_FILTER_BUILD := $(COOKER_DIR)/filter.h $(DBG_DIR)/disasm.h $(COMMON_DIR)/common.h \
+			$(COMMON_DIR)/util.h
 
 SRCS_FILTER := $(COOKER_DIR)/filter.c $(COMMON_DIR)/common.c util.c \
 	       $(DBG_DIR)/disasm.c
-HEADERS_FILTER := $(COOKER_DIR)/filter.h $(COMMON_DIR)/common.h \
+HEADERS_FILTER := $(COOKER_DIR)/filter.h $(COMMON_DIR)/common.h $(COMMON_DIR)/util.h \
 		  $(DBG_DIR)/disasm.h testutil.h
 
-HEADERS_OP_CALL := testutil.h $(COMMON_DIR)/gluten.h  $(OP_DIR)/operations.h \
+HEADERS_OP_CALL := testutil.h $(COMMON_DIR)/gluten.h  $(MAIN_DIR)/operations.h \
                    $(COMMON_DIR)/common.h $(COMMON_DIR)/util.h
-SRCS_OP_CALL := $(COMMON_DIR)/common.c $(OP_DIR)/operations.c util.c $(COMMON_DIR)/util.c
+SRCS_OP_CALL := $(COMMON_DIR)/common.c $(MAIN_DIR)/operations.c util.c $(COMMON_DIR)/util.c
 
-HEADERS_OP := $(COMMON_DIR)/gluten.h  $(OP_DIR)/operations.h \
+HEADERS_OP := $(COMMON_DIR)/gluten.h  $(MAIN_DIR)/operations.h \
 		   $(COMMON_DIR)/common.h testutil.h $(COMMON_DIR)/util.h
-SRCS_OP := $(COMMON_DIR)/common.c $(OP_DIR)/operations.c util.c $(COMMON_DIR)/util.c
+SRCS_OP := $(COMMON_DIR)/common.c $(MAIN_DIR)/operations.c util.c $(COMMON_DIR)/util.c
 
-HEADERS_ERROR := $(COMMON_DIR)/gluten.h  $(OP_DIR)/operations.h \
+HEADERS_ERROR := $(COMMON_DIR)/gluten.h  $(MAIN_DIR)/operations.h \
 		   $(COMMON_DIR)/common.h testutil.h $(COMMON_DIR)/util.h
-SRCS_ERROR := $(COMMON_DIR)/common.c $(OP_DIR)/operations.c util.c $(COMMON_DIR)/util.c
+SRCS_ERROR := $(COMMON_DIR)/common.c $(MAIN_DIR)/operations.c util.c $(COMMON_DIR)/util.c
 
 TARGET := $(shell $(CC) -dumpmachine)
 TARGET_ARCH := $(shell echo $(TARGET) | cut -f1 -d- | tr [A-Z] [a-z])
@@ -38,7 +39,7 @@ AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPC64/PPC/')
 AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPCLE/PPC64LE/')
 
 CFLAGS += -Wall -Wextra -pedantic
-CFLAGS += -I$(MAIN_DIR) -I$(OP_DIR)  -I$(DBG_DIR)
+CFLAGS += -I$(MAIN_DIR)  -I$(DBG_DIR) -I$(COMMON_DIR) -I$(COOKER_DIR)
 CFLAGS += -lcheck
 CFLAGS += -DSEITAN_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH)
 
diff --git a/tests/unit/test_filter_build.c b/tests/unit/test_filter_build.c
index f6d9ba5..52c1a82 100644
--- a/tests/unit/test_filter_build.c
+++ b/tests/unit/test_filter_build.c
@@ -35,7 +35,7 @@ static bool filter_eq(struct sock_filter *f1, struct sock_filter *f2,
 
 START_TEST(test_single_instr)
 {
-	struct sock_filter filter[10];
+	struct sock_filter result[10];
 	unsigned int size;
 	long nr = 42;
 	struct sock_filter expected[] = {
@@ -53,11 +53,13 @@ START_TEST(test_single_instr)
 	};
 
 	filter_notify(nr);
+	filter_flush_args(nr);
 
 	filter_write(tfilter);
-	size = read_filter(filter, tfilter);
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
-	ck_assert(filter_eq(expected, filter, ARRAY_SIZE(expected)));
+	size = read_filter(result, tfilter);
+
+	bpf_disasm_all(result, size);
+	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
 
@@ -65,12 +67,12 @@ START_TEST(test_single_instr_two_args)
 {
 	unsigned int size;
 	long nr = 42;
-	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 bpf_field a1 = {
+		.arg = 1, .cmp = EQ, .value = { .v32 = 0x123 }, .type = BPF_U32
+	};
+	struct bpf_field a2 = {
+		.arg = 2, .cmp = EQ, .value = { .v32 = 0x321 }, .type = BPF_U32
+	};
 	struct sock_filter result[20];
 	struct sock_filter expected[] = {
 		/* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
@@ -85,7 +87,7 @@ START_TEST(test_single_instr_two_args)
 		/* l5 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
 		/* l6 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
 		/* l7 */ LOAD(offsetof(struct seccomp_data, args[1])),
-		/* l8 */ EQ(0x123, 0, 2),
+		/* l8 */ EQ(0x123, 0, 3),
 		/* l9 */ LOAD(offsetof(struct seccomp_data, args[2])),
 		/* l10 */ EQ(0x321, 0, 1),
 		/* l11 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
@@ -93,14 +95,14 @@ START_TEST(test_single_instr_two_args)
 	};
 
 	filter_notify(nr);
-	filter_add_arg(1, a1);
-	filter_add_arg(2, a2);
-	filter_flush_args();
+	filter_add_check(&a1);
+	filter_add_check(&a2);
+	filter_flush_args(nr);
 
 	filter_write(tfilter);
 	size = read_filter(result, tfilter);
 
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+	bpf_disasm_all(result, size);
 	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
@@ -127,18 +129,21 @@ START_TEST(test_two_instr)
 	};
 	struct sock_filter result[30];
 	filter_notify(42);
+	filter_flush_args(42);
 	filter_notify(49);
+	filter_flush_args(49);
 
 	filter_write(tfilter);
 	size = read_filter(result, tfilter);
 
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+	bpf_disasm_all(result, size);
 	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
 
 START_TEST(test_multiple_instr_no_args)
 {
+	unsigned long nrs[] = { 42, 43, 44, 45, 46 };
 	unsigned int size;
 	struct sock_filter expected[] = {
 		/* l0 */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
@@ -170,16 +175,14 @@ START_TEST(test_multiple_instr_no_args)
 	};
 	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);
-
+	for(unsigned int i = 0; i < ARRAY_SIZE(nrs); i++) {
+		filter_notify(nrs[i]);
+		filter_flush_args(nrs[i]);
+	}
 	filter_write(tfilter);
 	size = read_filter(result, tfilter);
 
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+	bpf_disasm_all(result, size);
 	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
@@ -187,12 +190,12 @@ 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 bpf_field a1 = {
+		.arg = 1, .cmp = EQ, .value = { .v32 = 0x123 }, .type = BPF_U32
+	};
+	struct bpf_field a2 = {
+		.arg = 2, .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))),
@@ -222,14 +225,14 @@ START_TEST(test_multiple_instr_with_args)
 		/* 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),
+		/* l19 */ EQ(0x123, 0, 3),
 		/* 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),
+		/* l25 */ EQ(0x123, 0, 3),
 		/* l26 */ LOAD(offsetof(struct seccomp_data, args[2])),
 		/* l27 */ EQ(0x321, 0, 1),
 		/* l28 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
@@ -238,21 +241,21 @@ START_TEST(test_multiple_instr_with_args)
 	};
 	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_add_check(&a1);
+	filter_add_check(&a2);
+	filter_flush_args(42);
 	filter_notify(43);
 	filter_notify(44);
 	filter_notify(45);
-	filter_add_arg(1, a1);
-	filter_add_arg(2, a2);
-	filter_flush_args();
+	filter_add_check(&a1);
+	filter_add_check(&a2);
+	filter_flush_args(45);
 	filter_notify(46);
 
 	filter_write(tfilter);
 	size = read_filter(result, tfilter);
 
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+	bpf_disasm_all(result, size);
 	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
@@ -260,12 +263,12 @@ 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 bpf_field a1 = {
+		.arg = 1, .cmp = EQ, .value = { .v32 = 0x123 }, .type = BPF_U32
+	};
+	struct bpf_field a2 = {
+		.arg = 2, .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))),
@@ -299,38 +302,40 @@ START_TEST(test_multiple_instance_same_instr)
 		/* 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),
+		/* l24 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+		/* l23 */ 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),
+		/* l24 */ 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),
+		/* l31 */ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
+		/* l30 */ 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_add_check(&a1);
+	filter_flush_args(42);
+	filter_notify(42);
+	filter_add_check(&a2);
+	filter_flush_args(42);
 	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_add_check(&a1);
+	filter_flush_args(45);
+	filter_notify(45);
+	filter_add_check(&a2);
+	filter_flush_args(45);
 	filter_notify(46);
 
 	filter_write(tfilter);
 	size = read_filter(result, tfilter);
 
-	ck_assert_uint_eq(size, ARRAY_SIZE(expected));
+	bpf_disasm_all(result, size);
 	ck_assert(filter_eq(expected, result, ARRAY_SIZE(expected)));
 }
 END_TEST
diff --git a/tests/unit/testutil.h b/tests/unit/testutil.h
index a0fa0b8..caccd44 100644
--- a/tests/unit/testutil.h
+++ b/tests/unit/testutil.h
@@ -58,7 +58,7 @@ static inline void *test_gluten_write_ptr(struct gluten *g,
 		ck_assert_ptr_nonnull(p);                        \
 		memcpy(&ref, p, sizeof(ref));                    \
 	} while (0)
-
+#define NS_NUM CONTEXT_TYPE_MAX - 3
 struct args_target {
         long ret;
         int err;
@@ -67,7 +67,7 @@ struct args_target {
         int fd;
         int nr;
 	bool filter_args[6];
-	struct bpf_arg args[6];
+	struct bpf_field bpf_fields[6];
 	void *targs[6];
 	void *tclone;
 	bool ns[NS_NUM];
diff --git a/tests/unit/util.c b/tests/unit/util.c
index 96d6663..26f13e0 100644
--- a/tests/unit/util.c
+++ b/tests/unit/util.c
@@ -13,6 +13,7 @@
 #include <signal.h>
 #include <limits.h>
 #include <fcntl.h>
+#include <stdarg.h>
 #include <errno.h>
 #include <sys/prctl.h>
 #include <sys/syscall.h>
@@ -38,6 +39,19 @@ struct gluten gluten;
 char stderr_buff[BUFSIZ];
 char stdout_buff[BUFSIZ];
 
+#define logfn(name)                                                     \
+void name(const char *format, ...) {                                    \
+        va_list args;                                                   \
+                                                                        \
+        va_start(args, format);                                         \
+        (void)vfprintf(stderr, format, args);                           \
+        va_end(args);                                                   \
+        if (format[strlen(format)] != '\n')                             \
+                fprintf(stderr, "\n");                                  \
+}
+
+logfn(debug)
+
 int install_single_syscall(long nr)
 {
 	/* filter a single syscall for the tests */
@@ -209,7 +223,7 @@ void mock_syscall_target()
 void set_args_no_check(struct args_target *at)
 {
 	for (unsigned int i = 0; i < 6; i++)
-		at->args[i].cmp = NO_CHECK;
+		at->bpf_fields[i].cmp = NO_CHECK;
 }
 
 static int set_ns_flags(bool ns[], int flags)
@@ -217,8 +231,9 @@ static int set_ns_flags(bool ns[], int flags)
 	unsigned int i;
 
 	for (i = 0; i < NS_NUM; i++) {
-		if (!ns[i] || i == NS_NONE)
+		if (!ns[i])
 			continue;
+
 		switch (i) {
 		case NS_CGROUP:
 			flags |= CLONE_NEWCGROUP;
-- 
cgit v1.2.3