aboutgitcodelistschat:MatrixIRC
path: root/cooker
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2023-06-09 18:52:16 +0200
committerStefano Brivio <sbrivio@redhat.com>2023-06-09 18:52:38 +0200
commitd4757b140364cd277f7f7f373475eb427003cb42 (patch)
tree159e5da9d3c9f151c99c25ec0e9bffc2222de970 /cooker
parent65b5eacaa500e702b982c6848e1ffc18094bc9a9 (diff)
downloadseitan-d4757b140364cd277f7f7f373475eb427003cb42.tar
seitan-d4757b140364cd277f7f7f373475eb427003cb42.tar.gz
seitan-d4757b140364cd277f7f7f373475eb427003cb42.tar.bz2
seitan-d4757b140364cd277f7f7f373475eb427003cb42.tar.lz
seitan-d4757b140364cd277f7f7f373475eb427003cb42.tar.xz
seitan-d4757b140364cd277f7f7f373475eb427003cb42.tar.zst
seitan-d4757b140364cd277f7f7f373475eb427003cb42.zip
cooker: Pass arguments to filter
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'cooker')
-rw-r--r--cooker/cooker.h6
-rw-r--r--cooker/emit.c27
-rw-r--r--cooker/emit.h2
-rw-r--r--cooker/filter.c30
-rw-r--r--cooker/filter.h1
-rw-r--r--cooker/match.c19
6 files changed, 74 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 <string.h>
#include <unistd.h>
+#include <util.h>
+
#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++;