aboutgitcodelistschat:MatrixIRC
path: root/cooker/emit.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2023-05-16 03:19:01 +0200
committerStefano Brivio <sbrivio@redhat.com>2023-05-16 07:20:25 +0200
commit7ab2bda2e69d4a862572be4b5e389a6aa864470d (patch)
treefa9653204a4ab9581b76499c95d76d16d467301d /cooker/emit.c
parent049bd1ca828da835f2903b88adcf9ce0bdacd6e4 (diff)
downloadseitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar.gz
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar.bz2
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar.lz
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar.xz
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.tar.zst
seitan-7ab2bda2e69d4a862572be4b5e389a6aa864470d.zip
cooker, seitan: Now with 100% more gluten
Pseudorandom changes and progress around cooker and seitan: - cooker: - rename matching functions, split match.c - fix up SELECT semantics - add some form of handling for all syscalls in the example (some stubs) - OP_CMP for all basic and compound types except for flags - link jumps to next block and next match - completed implementation of tags - gluten write - filter clean-ups, write filters (probably not working) - seitan: - load gluten and source instructions and data from there $ ./seitan-cooker cooker/example.hjson example.gluten example.bpf Parsing block 0 Parsing match 0: connect Found description for connect 0: OP_NR: if syscall number is not 0, jump to next block Parsing match argument fd setting tag reference 'fd' tag 'fd' now refers to seccomp data at 0 Parsing match argument addr allocating 128 at offset 0 1: OP_LOAD: #0 < args[1] (size: 128) C#0: (INT) 1 2: OP_CMP: if temporary data: #0 NE (size: 4) read-only data: #0, jump to next block C#4: (STRING:24) /var/run/pr-helper.sock 3: OP_CMP: if temporary data: #0 NE (size: 24) read-only data: #4, jump to next block Linking match... Linking block... linked jump of instruction #0 to #4 linked jump of instruction #2 to #4 linked jump of instruction #3 to #4 Parsing block 1 Parsing match 0: ioctl Found description for ioctl 4: OP_NR: if syscall number is not 112, jump to next block Parsing match argument path Parsing match argument request C#28: (INT) 1074025674 5: OP_CMP: if seccomp data: #1 NE (size: 4) read-only data: #28, jump to next block Parsing match argument ifr allocating 40 at offset 128 6: OP_LOAD: #128 < args[2] (size: 40) C#32: (STRING:5) tap0 7: OP_CMP: if temporary data: #128 NE (size: 5) read-only data: #32, jump to next block C#37: (INT) 1 8: OP_CMP: if temporary data: #128 NE (size: 4) read-only data: #37, jump to next block Linking match... Linking block... linked jump of instruction #4 to #9 linked jump of instruction #5 to #9 linked jump of instruction #7 to #9 linked jump of instruction #8 to #9 Parsing block 2 Parsing match 0: unshare Found description for unshare 9: OP_NR: if syscall number is not 164, jump to next block Parsing match argument flags Linking match... Linking block... linked jump of instruction #9 to #10 Parsing block 3 Parsing match 0: unshare Found description for unshare 10: OP_NR: if syscall number is not 164, jump to next block Parsing match argument flags Linking match... Linking block... linked jump of instruction #10 to #11 Parsing block 4 Parsing match 0: mknod Found description for mknod 11: OP_NR: if syscall number is not 164, jump to next block Parsing match argument path allocating 1 at offset 168 12: OP_LOAD: #168 < args[0] (size: 1) setting tag reference 'path' tag 'path' now refers to temporary data at 168 Parsing match argument mode Parsing match argument major Parsing match argument minor setting tag reference 'minor' tag 'minor' now refers to seccomp data at 2 Linking match... Linking block... linked jump of instruction #11 to #13 Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'cooker/emit.c')
-rw-r--r--cooker/emit.c150
1 files changed, 126 insertions, 24 deletions
diff --git a/cooker/emit.c b/cooker/emit.c
index 8c35f1d..c233b0a 100644
--- a/cooker/emit.c
+++ b/cooker/emit.c
@@ -14,8 +14,10 @@
#include "emit.h"
static const char *type_str[] = {
+ "UNDEF", "NONE",
"INT", "INTMASK", "INTFLAGS",
"U32", "U32MASK", "U32FLAGS",
+ "U64", "U64MASK", "U64FLAGS",
"LONG", "LONGMASK", "LONGFLAGS",
"STRING",
"STRUCT", "SELECT",
@@ -25,83 +27,183 @@ static const char *type_str[] = {
NULL
};
-static const char *cmp_type_str[] = { "EQ", "GT", "GE", "LT", "LE", NULL };
+static const char *cmp_type_str[] = {
+ "EQ", "NE", "GT", "GE", "LT", "LE", NULL
+};
-void emit_nr(struct gluten_ctx *g, long number)
+/**
+ * emit_nr() - Emit OP_NR instruction: jump on syscall mismatch
+ * @g: gluten context
+ * @number: Pointer to system call number
+ */
+void emit_nr(struct gluten_ctx *g, struct gluten_offset number)
{
- struct op_nr *nr = (struct op_nr *)gluten_ptr(&g->g, g->ip);
+ struct op *op = (struct op *)gluten_ptr(&g->g, g->ip);
+ struct op_nr *nr = &op->op.nr;
+
+ op->type = OP_NR;
nr->nr = number;
nr->no_match.type = OFFSET_INSTRUCTION;
- nr->no_match.offset = NEXT_BLOCK;
+ nr->no_match.offset = JUMP_NEXT_BLOCK;
- debug(" %i: OP_NR %li, < >", g->ip.offset, number);
+ debug(" %i: OP_NR: if syscall number is not %li, jump to %s",
+ g->ip.offset, number, jump_name[nr->no_match.offset]);
if (++g->ip.offset > INST_MAX)
die("Too many instructions");
}
+/**
+ * emit_load() - Emit OP_LOAD instruction: dereference and copy syscall argument
+ * @g: gluten context
+ * @dst: gluten destination to copy dereferenced data
+ * @index: Index of system call argument
+ * @len: Length of data item pointed by reference
+ */
void emit_load(struct gluten_ctx *g, struct gluten_offset dst,
int index, size_t len)
{
- struct op_load *load = (struct op_load *)gluten_ptr(&g->g, g->ip);
+ struct op *op = (struct op *)gluten_ptr(&g->g, g->ip);
+ struct op_load *load = &op->op.load;
+
+ op->type = OP_LOAD;
load->src.type = OFFSET_SECCOMP_DATA;
load->src.offset = index;
load->dst = dst;
- debug(" %i: OP_LOAD #%i < %i (%lu)", g->ip.offset, dst.offset,
- index, len);
+ debug(" %i: OP_LOAD: #%i < args[%i] (size: %lu)",
+ g->ip.offset, dst.offset, index, len);
if (++g->ip.offset > INST_MAX)
die("Too many instructions");
}
-void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp,
+/**
+ * emit_cmp(): Emit OP_CMP instruction: compare data from two offsets
+ * @g: gluten context
+ * @cmp_type: Type of comparison
+ * @x: gluten pointer to first operand of comparison
+ * @y: gluten pointer to second operand of comparison
+ * @size: Size of comparison
+ * @jmp: Jump direction if comparison is true
+ */
+void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
struct gluten_offset x, struct gluten_offset y, size_t size,
enum jump_type jmp)
{
- struct op_cmp *op = (struct op_cmp *)gluten_ptr(&g->g, g->ip);
+ struct op *op = (struct op *)gluten_ptr(&g->g, g->ip);
+ struct op_cmp *cmp = &op->op.cmp;
- op->x = x;
- op->y = y;
- op->size = size;
- op->cmp = cmp;
- op->jmp = jmp;
+ op->type = OP_CMP;
- debug(" %i: OP_CMP (#%lu) %%%lu %s %%%lu", g->ip.offset, size,
- x.offset, cmp_type_str[cmp], y.offset);
+ cmp->x = x;
+ cmp->y = y;
+ cmp->size = size;
+ cmp->cmp = cmp_type;
+ cmp->jmp.type = OFFSET_INSTRUCTION;
+ cmp->jmp.offset = jmp;
+
+ debug(" %i: OP_CMP: if %s: #%lu %s (size: %lu) %s: #%lu, jump to %s",
+ g->ip.offset,
+ gluten_offset_name[x.type], x.offset,
+ cmp_type_str[cmp_type], size,
+ gluten_offset_name[y.type], y.offset,
+ jump_name[jmp]);
if (++g->ip.offset > INST_MAX)
die("Too many instructions");
}
+/**
+ * emit_cmp_field() - Emit OP_CMP for a given field type
+ * @g: gluten context
+ * @cmp: Type of comparison
+ * @field: Description of field from system call model
+ * @x: gluten pointer to first operand of comparison
+ * @y: gluten pointer to second operand of comparison
+ * @jmp: Jump direction if comparison is true
+ */
void emit_cmp_field(struct gluten_ctx *g, enum op_cmp_type cmp,
struct field *field,
- struct gluten_offset base, struct gluten_offset match,
+ struct gluten_offset x, struct gluten_offset y,
enum jump_type jmp)
{
- base.offset += field->offset;
-
- emit_cmp(g, cmp, base, match,
+ emit_cmp(g, cmp, x, y,
field->strlen ? field->strlen : gluten_size[field->type],
jmp);
}
struct gluten_offset emit_data(struct gluten_ctx *g, enum type type,
- union value *value)
+ size_t str_len, union value *value)
{
void *p = gluten_ptr(&g->g, g->cp);
struct gluten_offset ret = g->cp;
- if (type == INT) {
+ switch (type) {
+ case INT:
+ if (g->cp.offset + sizeof(int) > RO_DATA_SIZE)
+ die(" Read-only data section exceeded");
+
*(int *)p = value->v_int;
debug(" C#%i: (%s) %i", g->cp.offset, type_str[type],
value->v_int);
- if ((g->cp.offset += sizeof(int)) > RO_DATA_SIZE)
+
+ g->cp.offset += sizeof(int);
+ break;
+ case STRING:
+ if (g->cp.offset + str_len > RO_DATA_SIZE)
die(" Read-only data section exceeded");
+
+ strncpy(p, value->v_str, str_len);
+ debug(" C#%i: (%s:%i) %s", g->cp.offset, type_str[type],
+ str_len, value->v_str);
+
+ g->cp.offset += str_len;
+ break;
+ default:
+ ;
}
return ret;
}
+
+static void gluten_link(struct gluten_ctx *g, enum jump_type type,
+ struct op *start)
+{
+ struct gluten_offset *jmp;
+ struct op *op;
+
+ for (op = (struct op *)start; op->type; op++) {
+ switch (op->type) {
+ case OP_NR:
+ jmp = &op->op.nr.no_match;
+ break;
+ case OP_CMP:
+ jmp = &op->op.cmp.jmp;
+ break;
+ default:
+ continue;
+ }
+
+ if (jmp->offset == type) {
+ jmp->offset = g->ip.offset;
+ debug(" linked jump of instruction #%i to #%i",
+ op - (struct op *)g->g.inst, g->ip.offset);
+ }
+ }
+}
+
+void link_block(struct gluten_ctx *g)
+{
+ debug(" Linking block...");
+ gluten_link(g, JUMP_NEXT_BLOCK, (struct op *)gluten_ptr(&g->g, g->lr));
+}
+
+void link_match(struct gluten_ctx *g)
+{
+ debug(" Linking match...");
+ gluten_link(g, JUMP_NEXT_MATCH, (struct op *)gluten_ptr(&g->g, g->mr));
+}