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 --- cooker/call.c | 4 ++-- cooker/emit.c | 25 +++++++++++++++++++++++++ cooker/emit.h | 1 + cooker/example.hjson | 5 ++--- cooker/parse.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 76 insertions(+), 9 deletions(-) (limited to 'cooker') 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 }, -- cgit v1.2.3