From 6455b9dff0554adc11e8dbe8027d134c8584bc5d Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 2 Jun 2023 16:48:29 +0200 Subject: cooker, seitan: OP_FD Signed-off-by: Stefano Brivio --- common/gluten.h | 18 ++++++++++++------ cooker/call.c | 4 ++-- cooker/emit.c | 25 +++++++++++++++++++++++++ cooker/emit.h | 1 + cooker/example.hjson | 5 ++--- cooker/parse.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- operations.c | 41 +++++++++++++++++++---------------------- 7 files changed, 107 insertions(+), 37 deletions(-) diff --git a/common/gluten.h b/common/gluten.h index 198e646..9aa721c 100644 --- a/common/gluten.h +++ b/common/gluten.h @@ -65,8 +65,7 @@ enum op_type { OP_COPY, OP_BLOCK, OP_CONT, - OP_INJECT, - OP_INJECT_A, + OP_FD, OP_RETURN, OP_LOAD, OP_CMP, @@ -149,6 +148,14 @@ struct syscall_desc { struct gluten_offset args[]; }; +struct fd_desc { + struct gluten_offset srcfd; + struct gluten_offset newfd; + uint8_t setfd :1; + uint8_t cloexec :1; + uint8_t do_return :1; +}; + struct op_call { struct gluten_offset desc; }; @@ -167,9 +174,8 @@ struct op_return { struct gluten_offset val; }; -struct op_inject { - struct gluten_offset new_fd; - struct gluten_offset old_fd; +struct op_fd { + struct gluten_offset desc; /* struct fd_desc */ }; struct op_load { @@ -215,7 +221,7 @@ struct op { struct op_call call; struct op_block block; struct op_return ret; - struct op_inject inject; + struct op_fd fd; struct op_load load; struct op_cmp cmp; struct op_resolvedfd resfd; diff --git a/cooker/call.c b/cooker/call.c index 9561568..05e0e55 100644 --- a/cooker/call.c +++ b/cooker/call.c @@ -215,8 +215,8 @@ static union value parse_field(struct gluten_ctx *g, struct arg *args, f_value = json_object_get_value(tmp1, f_inner->name); if (!f_value) continue; - parse_field(g, args, &struct_start, index, f_inner, f_value, - false, add); + parse_field(g, args, &struct_start, index, f_inner, + f_value, false, add); } break; default: diff --git a/cooker/emit.c b/cooker/emit.c index 05e3f81..b518ff9 100644 --- a/cooker/emit.c +++ b/cooker/emit.c @@ -52,6 +52,31 @@ void emit_nr(struct gluten_ctx *g, struct gluten_offset number) die("Too many instructions"); } +/** + * emit_fd() - Emit OP_FD instruction: add/set file descriptor in target + * @g: gluten context + * @desc: Pointer to file descriptors specification + */ +void emit_fd(struct gluten_ctx *g, struct fd_desc *desc) +{ + struct op *op = (struct op *)gluten_ptr(&g->g, g->ip); + struct op_fd *fd = &op->op.fd; + struct gluten_offset o; + struct fd_desc *dst; + + op->type = OP_FD; + + o = gluten_ro_alloc(g, sizeof(struct fd_desc)); + dst = (struct fd_desc *)gluten_ptr(&g->g, o); + memcpy(dst, desc, sizeof(struct fd_desc)); + fd->desc = o; + + debug(" %i: OP_FD: ...", g->ip.offset); + + if (++g->ip.offset > INST_MAX) + die("Too many instructions"); +} + /** * emit_call() - Emit OP_CALL instruction: execute a system call * @g: gluten context diff --git a/cooker/emit.h b/cooker/emit.h index d98789a..70997fc 100644 --- a/cooker/emit.h +++ b/cooker/emit.h @@ -7,6 +7,7 @@ #define EMIT_H void emit_nr(struct gluten_ctx *g, struct gluten_offset number); +void emit_fd(struct gluten_ctx *g, struct fd_desc *desc); void emit_call(struct gluten_ctx *g, struct ns_spec *ns, long nr, unsigned count, bool is_ptr[6], struct gluten_offset offset[6], struct gluten_offset ret_offset); diff --git a/cooker/example.hjson b/cooker/example.hjson index 7fec039..f445418 100644 --- a/cooker/example.hjson +++ b/cooker/example.hjson @@ -1,13 +1,13 @@ [ { "match": [ /* qemu-pr-helper and similar */ - { "connect": { "addr": { "family": "unix", "path": "/var/run/pr-helper.sock" }, "fd": { "tag": "fd" } } } + { "connect": { "addr": { "family": "unix", "path": "/var/run/pr-helper.sock" }, "fd": { "tag": "orig_fd" } } } ], "call": [ { "socket": { "family": "unix", "type": "stream", "flags": 0, "protocol": 0 }, "ret": "new_fd" }, { "connect": { "fd": { "tag": { "get": "new_fd" } }, "addr": { "family": "unix", "path": "/var/run/pr-helper.sock" } }, "ret": "y" } ], - "inject": { "what": "fd", "new": { "tag": "y" }, "old": { "tag": "fd" }, "return": 0 } + "fd": { "src": { "tag": "new_fd" }, "new": { "tag": "orig_fd" }, "return": true, "close_on_exec": false } }, { "match": [ /* qemu creates a tap interface */ @@ -38,7 +38,6 @@ "ret": "x", "context": { "user": "init", "mnt": "caller" } }, - "inject": { "what": "fd", "new": { "tag": "x" } }, "return": { "tag": "x" } } ] diff --git a/cooker/parse.c b/cooker/parse.c index 64901f5..46134b5 100644 --- a/cooker/parse.c +++ b/cooker/parse.c @@ -17,10 +17,52 @@ #include "emit.h" #include "util.h" -static void handle_inject(struct gluten_ctx *g, JSON_Value *value) +static void handle_fd(struct gluten_ctx *g, JSON_Value *value) { - (void)g; - (void)value; + JSON_Object *obj = json_value_get_object(value), *tmp; + struct fd_desc desc = { .cloexec = 1 }; + JSON_Value *jvalue; + const char *tag; + + debug(" Parsing \"fd\""); + + jvalue = json_object_get_value(obj, "src"); + if (json_value_get_type(jvalue) == JSONObject) { + tmp = json_object_get_object(obj, "src"); + if (!tmp || !(tag = json_object_get_string(tmp, "tag"))) + die("invalid tag specification"); + desc.srcfd = gluten_get_tag(g, tag); + } else if (json_value_get_type(jvalue) == JSONNumber) { + union value v = { .v_num = json_value_get_number(jvalue) }; + desc.srcfd = emit_data(g, U32, 0, &v); + } else { + die("no valid \"src\" in \"fd\""); + } + + jvalue = json_object_get_value(obj, "new"); + if (!jvalue) { + ; + } else if (json_value_get_type(jvalue) == JSONObject) { + tmp = json_object_get_object(obj, "new"); + if (!tmp || !(tag = json_object_get_string(tmp, "tag"))) + die("invalid tag specification"); + desc.newfd = gluten_get_tag(g, tag); + desc.setfd = 1; + } else if (json_value_get_type(jvalue) == JSONNumber) { + union value v = { .v_num = json_value_get_number(jvalue) }; + desc.newfd = emit_data(g, U32, 0, &v); + desc.setfd = 1; + } else { + die("invalid \"new\" in \"fd\""); + } + + if (json_object_get_boolean(obj, "return")) + desc.do_return = 1; + + if (json_object_get_value(obj, "close_on_exec")) + desc.cloexec = json_object_get_boolean(obj, "close_on_exec"); + + emit_fd(g, &desc); } static void handle_limit(struct gluten_ctx *g, JSON_Value *value) @@ -58,7 +100,7 @@ struct rule_parser { } parsers[] = { { "match", handle_matches }, { "call", handle_calls }, - { "inject", handle_inject }, + { "fd", handle_fd }, { "limit", handle_limit }, { "return", handle_return }, { "block", handle_block }, diff --git a/operations.c b/operations.c index 304b39b..e210e2f 100644 --- a/operations.c +++ b/operations.c @@ -309,42 +309,39 @@ int op_continue(const struct seccomp_notif *req, int notifier, struct gluten *g, return 0; } -static int do_inject(const struct seccomp_notif *req, int notifier, - struct gluten *g, struct op_inject *op, bool atomic) +static int op_fd(const struct seccomp_notif *req, int notifier, + struct gluten *g, struct op_fd *op) { + const struct fd_desc *desc = gluten_ptr(&req->data, g, op->desc); struct seccomp_notif_addfd resp; + void *fd; + + if (!desc) + return -1; resp.flags = SECCOMP_ADDFD_FLAG_SETFD; - resp.newfd_flags = 0; + resp.flags |= desc->do_return ? SECCOMP_ADDFD_FLAG_SEND : 0; + resp.newfd_flags = desc->cloexec ? O_CLOEXEC : 0; resp.id = req->id; - if (gluten_read(&req->data, g, &resp.newfd, op->new_fd, - sizeof(resp.newfd)) == -1) - return -1; - if (gluten_read(&req->data, g, &resp.srcfd, op->old_fd, - sizeof(resp.srcfd)) == -1) + if (!(fd = gluten_ptr(&req->data, g, desc->srcfd))) return -1; + resp.srcfd = *(uint32_t *)fd; + + if (desc->setfd) { + if (!(fd = gluten_ptr(&req->data, g, desc->newfd))) + return -1; + resp.newfd = *(uint32_t *)fd; + } else { + resp.newfd = 0; + } - if (atomic) - resp.flags |= SECCOMP_ADDFD_FLAG_SEND; if (send_inject_target(&resp, notifier) == -1) return -1; return 0; } -int op_inject(const struct seccomp_notif *req, int notifier, struct gluten *g, - struct op_inject *op) -{ - return do_inject(req, notifier, g, op, false); -} - -int op_inject_a(const struct seccomp_notif *req, int notifier, struct gluten *g, - struct op_inject *op) -{ - return do_inject(req, notifier, g, op, true); -} - int op_cmp(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_cmp *op) { -- cgit v1.2.3