From 46a3a54c0a0e1ce9d8f5705184e46386565d2319 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 11 May 2023 11:26:11 +0200 Subject: Adjust op_call with gluten_offset --- common/gluten.h | 24 +++++++--------- operations.c | 68 ++++++++++++++++++++++++++++---------------- operations.h | 9 ++++-- tests/unit/test_operations.c | 59 +++++++++++++++++++------------------- tests/unit/testutil.h | 2 +- 5 files changed, 92 insertions(+), 70 deletions(-) diff --git a/common/gluten.h b/common/gluten.h index f6be7bb..3df638e 100644 --- a/common/gluten.h +++ b/common/gluten.h @@ -28,6 +28,8 @@ extern struct seccomp_data anonymous_seccomp_data; MAX(MAX(MAX(DATA_SIZE, RO_DATA_SIZE), INST_MAX), \ ARRAY_SIZE(anonymous_seccomp_data.args)) +#define OP_EMPTY { .block = { -1 } } +#define NO_FIELD block enum gluten_offset_type { OFFSET_RO_DATA = 0, @@ -50,17 +52,18 @@ BUILD_BUG_ON(BITS_PER_NUM(OFFSET_TYPE_MAX) + BITS_PER_NUM(OFFSET_MAX) > 16) enum ns_spec_type { NS_NONE, + /* Read the pid from seccomp_data */ NS_SPEC_TARGET, + /* Read the pid from gluten */ NS_SPEC_PID, NS_SPEC_PATH, }; struct ns_spec { enum ns_spec_type type; - union { - pid_t pid; - char *path; - } id; + /* Pid or path based on the type */ + struct gluten_offset id; + size_t size; }; /* @@ -99,26 +102,22 @@ enum op_type { }; struct op_nr { - long nr; + struct gluten_offset nr; struct gluten_offset no_match; }; struct op_call { - long nr; - bool has_ret; - void *args[6]; + struct gluten_offset nr; + struct gluten_offset args[6]; struct op_context context; struct gluten_offset ret; + bool has_ret; }; struct op_block { int32_t error; }; -struct op_continue { - bool cont; -}; - struct op_return { struct gluten_offset val; }; @@ -163,7 +162,6 @@ struct op { union { struct op_nr nr; struct op_call call; - struct op_continue cont; struct op_block block; struct op_return ret; struct op_inject inject; diff --git a/operations.c b/operations.c index 47a9a9f..9fbf609 100644 --- a/operations.c +++ b/operations.c @@ -84,35 +84,58 @@ static void proc_ns_name(unsigned i, char *ns) } } -static int set_namespaces(const struct op_call *a, int tpid) +static int prepare_arg_clone(const struct seccomp_notif *req, struct gluten *g, + const struct op_call *op, struct arg_clone *c) { - char path[PATH_MAX + 1]; char ns_name[PATH_MAX / 2]; - struct ns_spec ns; - int fd; + const struct ns_spec *ns; + char p[PATH_MAX]; unsigned int i; + pid_t pid; + + c->err = 0; + c->ret = -1; + + if (gluten_read(NULL, g, &c->nr, op->nr, sizeof(c->nr)) == -1) + return -1; - for (i = 0, ns = (a->context).ns[i]; i < sizeof(enum ns_type); - i++, ns = (a->context).ns[i]) { + for (i = 0; i < sizeof(enum ns_type); i++) { + ns = &op->context.ns[i]; proc_ns_name(i, ns_name); - switch (ns.type) { + switch (ns->type) { case NS_NONE: - continue; + strncpy(c->ns[i].path, "", PATH_MAX); + break; case NS_SPEC_TARGET: - snprintf(path, sizeof(path), "/proc/%d/ns/%s", tpid, + snprintf(c->ns[i].path, PATH_MAX, "/proc/%d/ns/%s", req->pid, ns_name); break; case NS_SPEC_PID: - snprintf(path, sizeof(path), "/proc/%d/ns/%s", - ns.id.pid, ns_name); + if (gluten_read(NULL, g, &pid, ns->id, ns->size) == -1) + return -1; + snprintf(c->ns[i].path, PATH_MAX , "/proc/%d/ns/%s", pid, + ns_name); break; case NS_SPEC_PATH: - snprintf(path, sizeof(path), "%s", ns.id.path); + if (gluten_read(NULL, g, &p, ns->id, ns->size) == -1) + return -1; + snprintf(c->ns[i].path, PATH_MAX , "%s", p); break; } + } + return 0; +} - if ((fd = open(path, O_CLOEXEC)) < 0) - ret_err(-1, "open for file %s", path); +static int set_namespaces(struct arg_clone *c) +{ + unsigned int i; + int fd; + + for (i = 0; i < sizeof(enum ns_type); i++) { + if(strcmp(c->ns[i].path, "") == 0) + continue; + if ((fd = open(c->ns[i].path, O_CLOEXEC)) < 0) + ret_err(-1, "open for file %s", c->ns[i].path); if (setns(fd, 0) != 0) ret_err(-1, "setns"); @@ -122,17 +145,16 @@ static int set_namespaces(const struct op_call *a, int tpid) static int execute_syscall(void *args) { - struct arg_clone *a = (struct arg_clone *)args; - const struct op_call *c = a->args; + struct arg_clone *c = (struct arg_clone *)args; - if (set_namespaces(a->args, a->pid) < 0) { + if (set_namespaces(c) < 0) { exit(EXIT_FAILURE); } /* execute syscall */ - a->ret = syscall(c->nr, c->args[0], c->args[1], c->args[2], c->args[3], + c->ret = syscall(c->nr, c->args[0], c->args[1], c->args[2], c->args[3], c->args[4], c->args[5]); - a->err = errno; - if (a->ret < 0) { + c->err = errno; + if (c->ret < 0) { perror("syscall"); exit(EXIT_FAILURE); } @@ -197,10 +219,8 @@ int op_call(const struct seccomp_notif *req, int notifier, struct gluten *g, resp.val = 0; resp.flags = 0; resp.error = 0; - c.args = op; - c.pid = req->pid; - c.err = 0; + prepare_arg_clone(req, g, op, &c); if (do_call(&c) == -1) { resp.error = -1; if (send_target(&resp, notifier) == -1) @@ -370,7 +390,7 @@ int eval(struct gluten *g, struct op *ops, const struct seccomp_notif *req, HANDLE_OP(OP_CALL, op_call, call); HANDLE_OP(OP_BLOCK, op_block, block); HANDLE_OP(OP_RETURN, op_return, ret); - HANDLE_OP(OP_CONT, op_continue, cont); + HANDLE_OP(OP_CONT, op_continue, NO_FIELD); HANDLE_OP(OP_INJECT_A, op_inject_a, inject); HANDLE_OP(OP_INJECT, op_inject, inject); HANDLE_OP(OP_LOAD, op_load, load); diff --git a/operations.h b/operations.h index ccc42c2..f68ea89 100644 --- a/operations.h +++ b/operations.h @@ -27,9 +27,14 @@ } while (0); \ break +struct ns_path { + char path[PATH_MAX]; +}; + struct arg_clone { - const struct op_call *args; - pid_t pid; + long nr; + void *args[6]; + struct ns_path ns[sizeof(enum ns_type)]; long ret; int err; }; diff --git a/tests/unit/test_operations.c b/tests/unit/test_operations.c index 0e22754..a83db5a 100644 --- a/tests/unit/test_operations.c +++ b/tests/unit/test_operations.c @@ -129,13 +129,12 @@ END_TEST START_TEST(test_op_call) { - struct op operations[] = { - { OP_CALL, { .call = { __NR_getppid, false } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, - { 0 }, - }; - + long nr = __NR_getppid; + struct op operations[] = { { OP_CALL, + { .call = { .nr = { OFFSET_DATA, 0 } } } }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY } }; + ck_write_gluten(gluten, operations[0].op.call.nr, nr); ck_assert_int_eq(eval(&gluten, operations, &req, notifyfd), 0); check_target_result(1, 0, true); } @@ -143,16 +142,18 @@ END_TEST START_TEST(test_op_call_ret) { + long nr = __NR_getppid; long r; struct op operations[] = { { OP_CALL, - { .call = { __NR_getppid, true, - .ret = { .type = OFFSET_DATA, .offset = 0 } } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, - { 0 }, + { .call = { .nr = { OFFSET_DATA, 0 }, + .ret = { OFFSET_DATA, sizeof(nr) }, + .has_ret = true } } }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, }; + ck_write_gluten(gluten, operations[0].op.call.nr, nr); ck_assert_int_eq(eval(&gluten, operations, &req, notifyfd), 0); check_target_result(1, 0, true); ck_read_gluten(gluten, operations[0].op.call.ret, r); @@ -211,8 +212,7 @@ START_TEST(test_op_load) sizeof(struct sockaddr_un) } } }, { OP_RETURN, { .ret = { { OFFSET_DATA, sizeof(struct sockaddr_un) } } } }, - { OP_END, { { 0 } } }, - { 0 }, + { OP_END, OP_EMPTY }, }; struct sockaddr_un addr; int v = 2; @@ -237,9 +237,9 @@ static void test_op_cmp_int(int a, int b, enum op_cmp_type cmp) cmp, 3 } } }, { OP_BLOCK, { .block = { -1 } } }, - { OP_END, { { 0 } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, + { OP_END, OP_EMPTY }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, { 0 }, }; @@ -298,9 +298,9 @@ START_TEST(test_op_cmp_string_eq) CMP_EQ, 3 } } }, { OP_BLOCK, { .block = { -1 } } }, - { OP_END, { { 0 } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, + { OP_END, OP_EMPTY }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, { 0 }, }; ck_write_gluten(gluten, operations[0].op.cmp.x, s1); @@ -322,10 +322,10 @@ START_TEST(test_op_cmp_string_false) sizeof(s1), CMP_EQ, 2 } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, { OP_BLOCK, { .block = { -1 } } }, - { OP_END, { { 0 } } }, + { OP_END, OP_EMPTY }, { 0 }, }; @@ -346,9 +346,9 @@ START_TEST(test_op_resolvedfd_eq) sizeof(path), 3 } } }, { OP_BLOCK, { .block = { -1 } } }, - { OP_END, { { 0 } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, + { OP_END, OP_EMPTY }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, { 0 }, }; @@ -370,10 +370,9 @@ START_TEST(test_op_resolvedfd_neq) sizeof(path), 3 } } }, { OP_BLOCK, { .block = { -1 } } }, - { OP_END, { { 0 } } }, - { OP_CONT, { { 0 } } }, - { OP_END, { { 0 } } }, - { 0 }, + { OP_END, OP_EMPTY }, + { OP_CONT, OP_EMPTY }, + { OP_END, OP_EMPTY }, }; ck_write_gluten(gluten, operations[0].op.resfd.fd, at->fd); diff --git a/tests/unit/testutil.h b/tests/unit/testutil.h index 861efb0..638dd0a 100644 --- a/tests/unit/testutil.h +++ b/tests/unit/testutil.h @@ -16,7 +16,7 @@ #include "common/gluten.h" #define STACK_SIZE (1024 * 1024 / 8) - +#define _EMPTY_ { .cont = { false } } static inline void *test_gluten_write_ptr(struct gluten *g, const struct gluten_offset x) { -- cgit v1.2.3