aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--common/gluten.h24
-rw-r--r--operations.c68
-rw-r--r--operations.h9
-rw-r--r--tests/unit/test_operations.c59
-rw-r--r--tests/unit/testutil.h2
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)
{