From 4d16cdb88553e37d77d1766b4f30d59e0149b2a8 Mon Sep 17 00:00:00 2001
From: Alice Frosi <afrosi@redhat.com>
Date: Tue, 18 Apr 2023 14:11:15 +0200
Subject: filter: remove superfluous jumps

---
 cooker/filter.c | 50 +++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

(limited to 'cooker')

diff --git a/cooker/filter.c b/cooker/filter.c
index 15d80ed..9cc9595 100644
--- a/cooker/filter.c
+++ b/cooker/filter.c
@@ -443,7 +443,8 @@ unsigned int create_bfp_program(struct syscall_entry table[],
 	const struct bpf_call *entry;
 	unsigned int n_args, n_nodes;
 	unsigned int notify, accept;
-	unsigned int i, j, k, size;
+	unsigned int i, j, k;
+	unsigned int size = 0;
 	unsigned int next_offset, offset;
 	unsigned int next_args_off;
 	unsigned n_checks;
@@ -451,28 +452,28 @@ unsigned int create_bfp_program(struct syscall_entry table[],
 
 	create_lookup_nodes(nodes, n_syscall);
 
-	/* First 3 checks */
-	size = 3;
 	/* No nodes if there is a single syscall */
 	n_nodes = (1 << count_shift_right(n_syscall - 1)) - 1;
 
 	n_args = get_total_args_instr(table, n_syscall);
 
-	/* pre-check instruction + load syscall number (4 instructions) */
-	accept = 3 + n_nodes + n_syscall + n_args;
-	notify = accept + 1;
-
 	/* Pre */
 	/* cppcheck-suppress badBitmaskCheck */
-	filter[0] = (struct sock_filter)BPF_STMT(
+	filter[size++] = (struct sock_filter)BPF_STMT(
 		BPF_LD | BPF_W | BPF_ABS,
 		(offsetof(struct seccomp_data, arch)));
-	filter[1] = (struct sock_filter)BPF_JUMP(
-		BPF_JMP | BPF_JEQ | BPF_K, SEITAN_AUDIT_ARCH, 0, accept - 2);
+	filter[size++] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
+						      SEITAN_AUDIT_ARCH, 1, 0);
+	filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K,
+						      SECCOMP_RET_ALLOW);
 	/* cppcheck-suppress badBitmaskCheck */
-	filter[2] = (struct sock_filter)BPF_STMT(
+	filter[size++] = (struct sock_filter)BPF_STMT(
 		BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr)));
 
+	/* pre-check instruction + load syscall number (4 instructions) */
+	accept = size + n_nodes + n_syscall;
+	notify = accept + 1;
+
 	/* Insert nodes */
 	for (i = 0; i < n_nodes; i++) {
 		if (nodes[i] == EMPTY) {
@@ -486,20 +487,23 @@ unsigned int create_bfp_program(struct syscall_entry table[],
 		}
 	}
 
-	next_offset = n_syscall - 1;
+	next_offset = n_syscall + 1;
 	/* Insert leaves */
 	for (i = 0; i < n_syscall; i++) {
-		/* If the syscall doesn't have any arguments, jump directly to
-		 * the notification
-		 */
+		/* If the syscall doesn't have any arguments, then notify */
 		if (check_args_syscall(&table[i]))
 			offset = next_offset;
 		else
 			offset = notify - size - 1;
 		filter[size++] = (struct sock_filter)EQ(table[i].nr, offset,
 							accept - size);
-		next_offset += get_n_args_syscall(&table[i]);
+		next_offset += get_n_args_syscall_instr(&table[i]) - 1;
 	}
+	/* Seccomp accept and notify instruction */
+	filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K,
+						      SECCOMP_RET_ALLOW);
+	filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K,
+						      SECCOMP_RET_USER_NOTIF);
 
 	/*
 	 * Insert args. It sequentially checks all the arguments for a syscall
@@ -555,22 +559,18 @@ unsigned int create_bfp_program(struct syscall_entry table[],
 				has_arg = true;
 			}
 			if (check_args_syscall_entry(table[i].entry))
-				filter[size++] = (struct sock_filter)JUMPA(
-					notify - size);
+				filter[size++] = (struct sock_filter)BPF_STMT(
+					BPF_RET | BPF_K,
+					SECCOMP_RET_USER_NOTIF);
 		}
 		/* At this point none of the checks was positive, it jumps to
 		 * the default behavior
 		 */
 		if (has_arg)
-			filter[size++] =
-				(struct sock_filter)JUMPA(accept - size);
+			filter[size++] = (struct sock_filter)BPF_STMT(
+				BPF_RET | BPF_K, SECCOMP_RET_ALLOW);
 	}
 
-	/* Seccomp accept and notify instruction */
-	filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K,
-						      SECCOMP_RET_ALLOW);
-	filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K,
-						      SECCOMP_RET_USER_NOTIF);
 	return size;
 }
 
-- 
cgit v1.2.3