aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--cooker/filter.c141
-rw-r--r--cooker/filter.h5
-rw-r--r--tests/unit/Makefile5
-rw-r--r--tests/unit/test_filter.c10
4 files changed, 122 insertions, 39 deletions
diff --git a/cooker/filter.c b/cooker/filter.c
index 9a2c9f1..a46e8ce 100644
--- a/cooker/filter.c
+++ b/cooker/filter.c
@@ -259,19 +259,106 @@ unsigned int create_bpf_program_log(struct sock_filter filter[])
return 4;
}
-static unsigned int eq_u64_filter(struct sock_filter filter[], int idx,
- uint64_t v, unsigned int jtrue,
- unsigned int jfalse)
+static unsigned int eq(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
{
- uint32_t hi = get_hi(v);
- uint32_t lo = get_lo(v);
+ unsigned int size = 0;
+ uint32_t hi, lo;
+
+ switch (entry->args[idx].type) {
+ case U64:
+ hi = get_hi((entry->args[idx]).value.v64);
+ lo = get_lo((entry->args[idx]).value.v64);
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)EQ(lo, 0, jfalse);
+ filter[size++] = (struct sock_filter)LOAD(HI_ARG(idx));
+ filter[size++] = (struct sock_filter)EQ(hi, jtrue, jfalse);
+ break;
+ case U32:
+
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)EQ(
+ entry->args[idx].value.v32, jtrue, jfalse);
+ break;
+ }
- filter[0] = (struct sock_filter)LOAD(LO_ARG(idx));
- filter[1] = (struct sock_filter)EQ(lo, 0, jfalse);
- filter[2] = (struct sock_filter)LOAD(HI_ARG(idx));
- filter[3] = (struct sock_filter)EQ(hi, jtrue, jfalse);
+ return size;
+}
- return 4;
+static unsigned int gt(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
+{
+ unsigned int size = 0;
+ uint32_t hi, lo;
+
+ switch (entry->args[idx].type) {
+ case U64:
+ hi = get_hi((entry->args[idx]).value.v64);
+ lo = get_lo((entry->args[idx]).value.v64);
+ filter[size++] = (struct sock_filter)LOAD(HI_ARG(idx));
+ filter[size++] = (struct sock_filter)GT(hi, jtrue, jfalse);
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)GT(lo, jtrue, jfalse);
+ break;
+ case U32:
+
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)GT(
+ entry->args[idx].value.v32, jtrue, jfalse);
+ break;
+ }
+
+ return size;
+}
+
+static unsigned int lt(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
+{
+ unsigned int size = 0;
+ uint32_t hi, lo;
+
+ switch (entry->args[idx].type) {
+ case U64:
+ hi = get_hi((entry->args[idx]).value.v64);
+ lo = get_lo((entry->args[idx]).value.v64);
+ filter[size++] = (struct sock_filter)LOAD(HI_ARG(idx));
+ filter[size++] = (struct sock_filter)LT(hi, jtrue, jfalse);
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)LT(lo, jtrue, jfalse);
+ break;
+ case U32:
+
+ filter[size++] = (struct sock_filter)LOAD(LO_ARG(idx));
+ filter[size++] = (struct sock_filter)LT(
+ entry->args[idx].value.v32, jtrue, jfalse);
+ break;
+ }
+
+ return size;
+}
+
+static unsigned int neq(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
+{
+ return eq(filter, idx, entry, jfalse, jtrue);
+}
+
+static unsigned int ge(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
+{
+ return lt(filter, idx, entry, jfalse, jtrue);
+}
+
+static unsigned int le(struct sock_filter filter[], int idx,
+ const struct bpf_call *entry, unsigned int jtrue,
+ unsigned int jfalse)
+{
+ return gt(filter, idx, entry, jfalse, jtrue);
}
unsigned int create_bfp_program(struct syscall_entry table[],
@@ -284,7 +371,6 @@ unsigned int create_bfp_program(struct syscall_entry table[],
unsigned int notify, accept;
unsigned int i, j, k, size;
unsigned int next_offset, offset;
- unsigned int next_args_off;
int nodes[MAX_JUMPS];
create_lookup_nodes(nodes, n_syscall);
@@ -349,36 +435,21 @@ unsigned int create_bfp_program(struct syscall_entry table[],
for (j = 0; j < (table[i]).count; j++) {
unsigned n_checks = 0;
entry = table[i].entry + j;
- next_args_off = get_n_args_syscall_entry(entry);
for (k = 0; k < 6; k++) {
- if (entry->args[k].cmp == NO_CHECK)
+ switch (entry->args[k].cmp) {
+ case NO_CHECK:
continue;
- offset = next_args_off - n_checks;
- switch (entry->args[k].type) {
- case U64:
- size += eq_u64_filter(
- &filter[size], k,
- entry->args[k].value.v64, 0,
- offset);
- n_checks++;
- has_arg = true;
- break;
- case U32:
- filter[size++] = (struct sock_filter)
- LOAD((offsetof(
- struct seccomp_data,
- args[k])));
- filter[size++] = (struct sock_filter)EQ(
- entry->args[k].value.v32, 0,
- offset);
- n_checks++;
- has_arg = true;
+ case EQ:
+ size += eq(&filter[size], k, entry, 0,
+ offset);
break;
default:
fprintf(stderr,
- "value for args not recognized\n");
- return -1;
+ "operation not recognized\n");
+ continue;
}
+ n_checks++;
+ has_arg = true;
}
if (check_args_syscall_entry(table[i].entry))
filter[size++] = (struct sock_filter)JUMPA(
diff --git a/cooker/filter.h b/cooker/filter.h
index afdd0b9..2729669 100644
--- a/cooker/filter.h
+++ b/cooker/filter.h
@@ -27,6 +27,11 @@
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))
+#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 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 MAX_FILTER 1024
diff --git a/tests/unit/Makefile b/tests/unit/Makefile
index fac3f68..ae9631b 100644
--- a/tests/unit/Makefile
+++ b/tests/unit/Makefile
@@ -38,7 +38,7 @@ CFLAGS += -DSEITAN_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH) -DTMP_DATA_SIZE=1000
test: test-filter test-operations test-op-call
-build-filter-build: test_filter_build.c $(SRCS_FILTER_BUILD) $(HEADERS_FILTER_BUILD)
+build-filter-build: test_filter_build.c $ (SRCS_FILTER_BUILD) $(HEADERS_FILTER_BUILD)
$(CC) $(CFLAGS) -o filter-build $(SRCS_FILTER) \
test_filter_build.c
@@ -65,3 +65,6 @@ build-operations: test_operations.c $(SRCS_OP) $(HEADERS_OP)
test-operations: build-operations
./operations
+
+clean:
+ rm -f operations op-call filter filter-build
diff --git a/tests/unit/test_filter.c b/tests/unit/test_filter.c
index 90ffa2b..5745ba2 100644
--- a/tests/unit/test_filter.c
+++ b/tests/unit/test_filter.c
@@ -35,6 +35,7 @@ static int generate_install_filter(struct args_target *at)
calls[0].args[i].cmp = NO_CHECK;
continue;
}
+ calls[0].args[i].cmp = at->cmp[i];
switch (at->type[i]) {
case U32:
calls[0].args[i].value.v32 = (uint32_t)at->args[i];
@@ -73,6 +74,7 @@ START_TEST(with_getsid)
set_args_no_check(at);
at->args[0] = &id;
at->type[0] = U32;
+ at->cmp[0] = EQ;
at->install_filter = generate_install_filter;
setup();
mock_syscall_target();
@@ -90,8 +92,10 @@ START_TEST(with_getpriority)
set_args_no_check(at);
at->args[0] = &which;
at->type[0] = U32;
+ at->cmp[0] = EQ;
at->args[1] = &who;
- at->type[0] = U32;
+ at->type[1] = U32;
+ at->cmp[1] = EQ;
at->install_filter = generate_install_filter;
setup();
mock_syscall_target();
@@ -104,7 +108,7 @@ static int target_lseek()
/* Open the device on the target, but the arg0 isn't in the filter */
ck_assert_int_ge(fd, 0);
- at->args[0] = fd;
+ at->args[0] = (void *)(long)fd;
return target();
}
@@ -116,7 +120,7 @@ static void test_lseek(off_t offset)
at->nr = __NR_lseek;
at->target = target_lseek;
set_args_no_check(at);
- at->args[1] = offset;
+ at->args[1] = (void *)offset;
at->type[1] = U64;
at->install_filter = generate_install_filter;
setup();