diff options
-rw-r--r-- | cooker/filter.c | 126 | ||||
-rw-r--r-- | cooker/filter.h | 31 |
2 files changed, 65 insertions, 92 deletions
diff --git a/cooker/filter.c b/cooker/filter.c index bffdfe4..c7e0ee4 100644 --- a/cooker/filter.c +++ b/cooker/filter.c @@ -324,15 +324,14 @@ static unsigned int eq(struct sock_filter filter[], case BPF_U64: hi = get_hi(field->value.v64); lo = get_lo(field->value.v64); - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)EQ(lo, 0, jfalse); - filter[size++] = (struct sock_filter)LOAD(HI_ARG(field->arg)); - filter[size++] = (struct sock_filter)EQ(hi, jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = EQ(lo, 0, jfalse); + filter[size++] = LOAD(HI_ARG(field->arg)); + filter[size++] = EQ(hi, jtrue, jfalse); break; case BPF_U32: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)EQ( - field->value.v32, jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = EQ(field->value.v32, jtrue, jfalse); break; } @@ -350,15 +349,14 @@ static unsigned int gt(struct sock_filter filter[], case BPF_U64: hi = get_hi(field->value.v64); lo = get_lo(field->value.v64); - filter[size++] = (struct sock_filter)LOAD(HI_ARG(field->arg)); - filter[size++] = (struct sock_filter)GT(hi, jtrue + 2, 0); - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)GT(lo, jtrue, jfalse); + filter[size++] = LOAD(HI_ARG(field->arg)); + filter[size++] = GT(hi, jtrue + 2, 0); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = GT(lo, jtrue, jfalse); break; case BPF_U32: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)GT( - field->value.v32, jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = GT(field->value.v32, jtrue, jfalse); break; } @@ -376,15 +374,14 @@ static unsigned int lt(struct sock_filter filter[], case BPF_U64: hi = get_hi(field->value.v64); lo = get_lo(field->value.v64); - filter[size++] = (struct sock_filter)LOAD(HI_ARG(field->arg)); - filter[size++] = (struct sock_filter)LT(hi, jtrue + 2, jfalse); - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)LT(lo, jtrue, jfalse); + filter[size++] = LOAD(HI_ARG(field->arg)); + filter[size++] = LT(hi, jtrue + 2, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = LT(lo, jtrue, jfalse); break; case BPF_U32: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)LT( - field->value.v32, jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = LT(field->value.v32, jtrue, jfalse); break; } @@ -420,23 +417,17 @@ static unsigned int and_eq(struct sock_filter filter[], switch (field->type) { case BPF_U64: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)AND( - get_lo(field->op2.v64)); - filter[size++] = (struct sock_filter)EQ( - get_lo(field->value.v64), 0, jfalse); - filter[size++] = (struct sock_filter)LOAD(HI_ARG(field->arg)); - filter[size++] = (struct sock_filter)AND( - get_hi(field->op2.v64)); - filter[size++] = (struct sock_filter)EQ( - get_hi(field->value.v64), jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = AND(get_lo(field->op2.v64)); + filter[size++] = EQ(get_lo(field->value.v64), 0, jfalse); + filter[size++] = LOAD(HI_ARG(field->arg)); + filter[size++] = AND(get_hi(field->op2.v64)); + filter[size++] = EQ(get_hi(field->value.v64), jtrue, jfalse); break; case BPF_U32: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = - (struct sock_filter)AND(field->op2.v32); - filter[size++] = (struct sock_filter)EQ( - field->value.v32, jtrue, jfalse); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = AND(field->op2.v32); + filter[size++] = EQ(field->value.v32, jtrue, jfalse); break; } @@ -451,23 +442,17 @@ static unsigned int and_ne(struct sock_filter filter[], switch (field->type) { case BPF_U64: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = (struct sock_filter)AND( - get_lo(field->op2.v64)); - filter[size++] = (struct sock_filter)EQ( - get_lo(field->value.v64), 0, jtrue + 3); - filter[size++] = (struct sock_filter)LOAD(HI_ARG(field->arg)); - filter[size++] = (struct sock_filter)AND( - get_hi(field->op2.v64)); - filter[size++] = (struct sock_filter)EQ( - get_hi(field->value.v64), jfalse, jtrue); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = AND(get_lo(field->op2.v64)); + filter[size++] = EQ(get_lo(field->value.v64), 0, jtrue + 3); + filter[size++] = LOAD(HI_ARG(field->arg)); + filter[size++] = AND(get_hi(field->op2.v64)); + filter[size++] = EQ(get_hi(field->value.v64), jfalse, jtrue); break; case BPF_U32: - filter[size++] = (struct sock_filter)LOAD(LO_ARG(field->arg)); - filter[size++] = - (struct sock_filter)AND(field->op2.v32); - filter[size++] = (struct sock_filter)EQ( - field->value.v32, jfalse, jtrue); + filter[size++] = LOAD(LO_ARG(field->arg)); + filter[size++] = AND(field->op2.v32); + filter[size++] = EQ(field->value.v32, jfalse, jtrue); break; } @@ -530,8 +515,8 @@ static unsigned int insert_args(struct sock_filter filter[], long nr) /* 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_ALLOW); + filter[size++] = STMT(BPF_RET | BPF_K, + SECCOMP_RET_ALLOW); } return size; @@ -556,16 +541,14 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n) /* Pre */ /* cppcheck-suppress badBitmaskCheck */ - filter[size++] = (struct sock_filter)BPF_STMT( - BPF_LD | BPF_W | BPF_ABS, - (offsetof(struct seccomp_data, arch))); - 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); + filter[size++] = STMT(BPF_LD | BPF_W | BPF_ABS, + offsetof(struct seccomp_data, arch)); + filter[size++] = JUMP(BPF_JMP | BPF_JEQ | BPF_K, + SEITAN_AUDIT_ARCH, 1, 0); + filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW); /* cppcheck-suppress badBitmaskCheck */ - filter[size++] = (struct sock_filter)BPF_STMT( - BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))); + filter[size++] = 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; @@ -574,14 +557,12 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n) /* Insert nodes */ for (i = 0; i < n_nodes; i++) { if (nodes[i] == EMPTY) { - filter[size++] = - (struct sock_filter)JUMPA(accept - size); + filter[size++] = JUMPA(accept - size); } else { 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( - nr, offset_right, offset_left); + filter[size++] = JGE(nr, offset_right, offset_left); } } @@ -595,19 +576,16 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n) /* 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++] = 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 */ - filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K, - SECCOMP_RET_ALLOW); + filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW); if (!call_entry_count(nr)) - filter[size++] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K, - SECCOMP_RET_USER_NOTIF); + filter[size++] = STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF); /* @@ -618,8 +596,8 @@ unsigned int filter_build(struct sock_filter filter[], unsigned n) for (i = 0; i < n; i++) { size += insert_args(&filter[size], nr); if (call_entry_count(nr)) - filter[size++] = (struct sock_filter)BPF_STMT( - BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF); + filter[size++] = STMT(BPF_RET | BPF_K, + SECCOMP_RET_USER_NOTIF); } debug(" BPF: filter with %i call%s has %i instructions", diff --git a/cooker/filter.h b/cooker/filter.h index 5257f69..8efdc47 100644 --- a/cooker/filter.h +++ b/cooker/filter.h @@ -29,26 +29,25 @@ #error "Unknown endianness" #endif +#define JUMP(...) ((struct sock_filter)BPF_JUMP(__VA_ARGS__)) +#define STMT(...) ((struct sock_filter)BPF_STMT(__VA_ARGS__)) + #define JGE(nr, right, left) \ - BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, (nr), (right), (left)) -#define JUMPA(jump) BPF_JUMP(BPF_JMP | BPF_JA, (jump), 0, 0) -#define EQ(x, a1, a2) BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (x), (a1), (a2)) + JUMP(BPF_JMP | BPF_JGE | BPF_K, (nr), (right), (left)) +#define JUMPA(jump) JUMP(BPF_JMP | BPF_JA, (jump), 0, 0) +#define EQ(x, a1, a2) JUMP(BPF_JMP | BPF_JEQ | BPF_K, (x), (a1), (a2)) #define NEQ(x, a1, a2) EQ((x), (a2), (a1)) -#define GT(x, a1, a2) BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, (x), (a1), (a2)) -#define GE(x, a1, a2) BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, (x), (a1), (a2)) +#define GT(x, a1, a2) JUMP(BPF_JMP + BPF_JGT + BPF_K, (x), (a1), (a2)) +#define GE(x, a1, a2) JUMP(BPF_JMP + BPF_JGE + BPF_K, (x), (a1), (a2)) #define LT(x, a1, a2) GE((x), (a2), (a1)) #define LE(x, a1, a2) GT((x), (a2), (a1)) -#define LOAD(x) BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (x)) -#define AND(x) BPF_STMT(BPF_ALU | BPF_AND | BPF_IMM, (x)) +#define LOAD(x) STMT(BPF_LD | BPF_W | BPF_ABS, (x)) +#define AND(x) STMT(BPF_ALU | BPF_AND | BPF_IMM, (x)) #define MAX_FILTER 1024 #define MAX_JUMPS 128 #define EMPTY -1 -#define N_SYSCALL 512 -#define MAX_ENTRIES_SYSCALL 16 -#define MAX_ENTRIES N_SYSCALL * MAX_ENTRIES_SYSCALL - enum bpf_type { BPF_U32, BPF_U64 }; union bpf_value { @@ -59,21 +58,17 @@ union bpf_value { extern const char *bpf_cmp_str[]; enum bpf_cmp { NO_CHECK = 0, EQ, NE, LE, LT, GE, GT, AND_EQ, AND_NE }; -struct bpf_arg { +struct bpf_field { + int arg; union bpf_value value; enum bpf_type type; enum bpf_cmp cmp; union bpf_value op2; }; -struct bpf_entry { - struct bpf_arg args[6]; -}; - void filter_notify(long nr); void filter_needs_deref(void); -void filter_add_arg(int index, struct bpf_arg arg); +void filter_add_check(struct bpf_field *field); void filter_write(const char *path); -void filter_flush_args(); #endif |