From d4757b140364cd277f7f7f373475eb427003cb42 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 9 Jun 2023 18:52:16 +0200 Subject: cooker: Pass arguments to filter Signed-off-by: Stefano Brivio --- cooker/cooker.h | 6 ++++++ cooker/emit.c | 27 +++++++++++++++++++++++++++ cooker/emit.h | 2 ++ cooker/filter.c | 30 +++++++++++++++++++++++------- cooker/filter.h | 1 + cooker/match.c | 19 +++++++++++++++---- seitan-run | 2 ++ 7 files changed, 76 insertions(+), 11 deletions(-) diff --git a/cooker/cooker.h b/cooker/cooker.h index 24d8f7f..cd804d3 100644 --- a/cooker/cooker.h +++ b/cooker/cooker.h @@ -59,6 +59,8 @@ union value { const char *v_str; }; +#define NO_VALUE ((union value){ .v_num = 0 }) + /** * enum type - Types of values for arguments and fields within arguments */ @@ -116,6 +118,10 @@ enum flags { ((t) == USHORT || (t) == INT || (t) == U32 || \ (t) == U64 || (t) == LONG || \ (t) == GNU_DEV_MAJOR || (t) == GNU_DEV_MINOR) +#define TYPE_IS_64BIT(t) \ + ((t) == U64 || (t) == LONG || \ + (t) == GNU_DEV_MAJOR || (t) == GNU_DEV_MINOR) + /** * struct num - A numeric value and its label diff --git a/cooker/emit.c b/cooker/emit.c index 41b64a6..57533a1 100644 --- a/cooker/emit.c +++ b/cooker/emit.c @@ -11,6 +11,7 @@ #include "cooker.h" #include "gluten.h" +#include "filter.h" #include "util.h" #include "emit.h" @@ -536,6 +537,32 @@ static void gluten_link(struct gluten_ctx *g, enum jump_type type, } } +void emit_bpf_arg(int index, enum type type, union value v, union value mask, + enum op_cmp_type cmp) +{ + struct bpf_arg bpf; + + /* gluten uses the comparison to skip to the next match, the BPF filter + * uses it to notify instead. + */ + if (mask.v_num) + bpf.cmp = (cmp == CMP_EQ) ? AND_NE : AND_EQ; + else + bpf.cmp = (cmp == CMP_EQ) ? NE : EQ; + + if (TYPE_IS_64BIT(type)) { + bpf.value.v64 = v.v_num; + bpf.op2.v64 = mask.v_num; + bpf.type = BPF_U64; + } else { + bpf.value.v32 = v.v_num; + bpf.op2.v32 = mask.v_num; + bpf.type = BPF_U32; + } + + filter_add_arg(index, bpf); +} + void link_block(struct gluten_ctx *g) { debug(" Linking block..."); diff --git a/cooker/emit.h b/cooker/emit.h index b9d326f..1cdadb9 100644 --- a/cooker/emit.h +++ b/cooker/emit.h @@ -43,6 +43,8 @@ struct gluten_offset emit_data_at(struct gluten_ctx *g, struct gluten_offset emit_data_or(struct gluten_ctx *g, struct gluten_offset offset, enum type type, union value *value); +void emit_bpf_arg(int index, enum type type, union value v, union value mask, + enum op_cmp_type cmp); void link_block(struct gluten_ctx *g); void link_match(struct gluten_ctx *g); void link_matches(struct gluten_ctx *g); diff --git a/cooker/filter.c b/cooker/filter.c index 8754da0..69b8523 100644 --- a/cooker/filter.c +++ b/cooker/filter.c @@ -13,11 +13,16 @@ #include #include +#include + #include "filter.h" struct bpf_entry entries[MAX_ENTRIES]; static unsigned int index_entries = 0; +const char *bpf_cmp_str[] = { "no check", "==", "!=", "<=", "<", ">=", ">", + "==", "!=" }; + /** * struct filter_call_input - First input stage for cooker notification requests * @notify: Notify on this system call @@ -33,12 +38,6 @@ struct filter_call_input { static long current_nr; -static void set_no_args(struct bpf_entry *entry) -{ - for (int i = 0; i < 6; i++) - entry->args[i].cmp = NO_CHECK; -} - static unsigned int get_number_entries(long nr) { struct filter_call_input *call = filter_input + nr; @@ -137,7 +136,8 @@ void filter_notify(long nr) { struct filter_call_input *call = filter_input + nr; - if (nr >= 0) { + if (nr > 0) { + debug(" BPF: start filter information for #%lu", nr); current_nr = nr; call->notify = true; } @@ -152,6 +152,17 @@ void filter_add_arg(int index, struct bpf_arg arg) { struct filter_call_input *call = filter_input + current_nr; struct bpf_entry *entry = &entries[index_entries]; + char buf[BUFSIZ]; + unsigned n; + + n = snprintf(buf, BUFSIZ, " BPF: adding #%i %s %lu", + index, bpf_cmp_str[arg.cmp], + (arg.type == BPF_U32) ? arg.value.v32 : arg.value.v64); + if (arg.cmp == AND_EQ || arg.cmp == AND_NE) { + snprintf(buf + n, BUFSIZ - n, " & %lu", + (arg.type == BPF_U32) ? arg.op2.v32 : arg.op2.v64); + } + debug("%s", buf); /* If it reaches the maximum number of entries per syscall, then we simply * notify for all the arguments and ignore the other arguments. @@ -169,6 +180,9 @@ void filter_add_arg(int index, struct bpf_arg arg) void filter_flush_args() { struct filter_call_input *call = filter_input + current_nr; + + debug(" BPF: flush filter information for #%lu", current_nr); + call->count++; index_entries++; } @@ -177,6 +191,8 @@ void filter_needs_deref(void) { struct filter_call_input *call = filter_input + current_nr; + debug(" BPF: arguments for #%lu now ignored", current_nr); + call->ignore_args = true; call->count = 0; } diff --git a/cooker/filter.h b/cooker/filter.h index fca9da7..5257f69 100644 --- a/cooker/filter.h +++ b/cooker/filter.h @@ -56,6 +56,7 @@ union bpf_value { uint64_t v64; }; +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 { diff --git a/cooker/match.c b/cooker/match.c index 5fd46db..374f277 100644 --- a/cooker/match.c +++ b/cooker/match.c @@ -79,8 +79,8 @@ static union value parse_field(struct gluten_ctx *g, int index, struct field *f, JSON_Value *jvalue) { struct gluten_offset const_offset, mask_offset, data_offset; + union value v = NO_VALUE, mask = NO_VALUE; struct gluten_offset seccomp_offset; - union value v = { .v_num = 0 }; struct field *f_inner; const char *tag_name; JSON_Object *tmp; @@ -182,6 +182,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx emit_cmp(g, cmp, masked, cmp_offset, gluten_size[f->type], jump); + emit_bpf_arg(index, f->type, cmpterm, set, cmp); break; } @@ -197,8 +198,8 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx v.v_num |= value_get_num(f->desc.d_num, jvalue); } } else if (f->flags & MASK) { - v.v_num = value_get_mask(f->desc.d_num); - mask_offset = emit_data(g, f->type, 0, &v); + mask.v_num = value_get_mask(f->desc.d_num); + mask_offset = emit_data(g, f->type, 0, &mask); data_offset = emit_bitwise(g, f->type, BITWISE_AND, NULL_OFFSET, offset, mask_offset); @@ -208,8 +209,12 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx } const_offset = emit_data(g, f->type, 0, &v); + emit_cmp(g, cmp, data_offset, const_offset, gluten_size[f->type], jump); + + emit_bpf_arg(index, f->type, v, mask, cmp); + break; case GNU_DEV_MAJOR: /* @@ -219,7 +224,10 @@ ______________________ _____________ v.v_num = value_get_num(f->desc.d_num, jvalue); v.v_num = (v.v_num & 0xfff) << 8 | (v.v_num & ~0xfff) << 32; const_offset = emit_data(g, U64, 0, &v); + emit_cmp_field(g, cmp, f, offset, const_offset, jump); + + filter_needs_deref(); /* No shifts in BPF */ break; case GNU_DEV_MINOR: /* @@ -230,6 +238,8 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx v.v_num = (v.v_num & 0xff) | (v.v_num & ~0xfff) << 12; const_offset = emit_data(g, U64, 0, &v); emit_cmp_field(g, cmp, f, offset, const_offset, jump); + + filter_needs_deref(); /* No shifts in BPF */ break; case SELECT: f_inner = f->desc.d_select->field; @@ -370,8 +380,9 @@ void handle_matches(struct gluten_ctx *g, JSON_Value *value) emit_nr(g, emit_data(g, U64, 0, &v)); filter_notify(call->number); - parse_match(g, args, call->args); + filter_flush_args(); + break; } call++; diff --git a/seitan-run b/seitan-run index 88cdcf0..c90e1d0 100755 --- a/seitan-run +++ b/seitan-run @@ -36,6 +36,8 @@ trap cleanup EXIT INT [ -z "${SEITAN}" ] && echo "seitan not found" && exit 1 "${COOKER}" "${1}" "${DIR}/gluten" "${DIR}/bpf" +echo "Cooked files now at ${DIR}" + shift ( "${EATER}" -i "${DIR}/bpf" -- ${@} & echo "${!}" > "${DIR}/eater.pid" 2>&1 ) & sleep 0.1 || sleep 1 -- cgit v1.2.3