aboutgitcodelistschat:MatrixIRC
path: root/operations.c
diff options
context:
space:
mode:
authorAlice Frosi <afrosi@redhat.com>2023-05-02 17:21:57 +0200
committerAlice Frosi <afrosi@redhat.com>2023-05-08 14:36:43 +0200
commitc29157e78df7fa335c56d0d7f2cca7dc50bfffd6 (patch)
tree6c7ce428c01a602f89c8897015e7428b84038871 /operations.c
parent82b77505f9420f11d614c2ae0f74153ca4ee3cb5 (diff)
downloadseitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar.gz
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar.bz2
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar.lz
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar.xz
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.tar.zst
seitan-c29157e78df7fa335c56d0d7f2cca7dc50bfffd6.zip
seitan: refactor operations
Refactoring: - rename do_operations to eval and reduce the number of arguments - create macro HANDLE_OP - rename all functions with op_*(operation name) - exposed the op_* functions in the operations.h Fixes: - use pread for op_load
Diffstat (limited to 'operations.c')
-rw-r--r--operations.c320
1 files changed, 173 insertions, 147 deletions
diff --git a/operations.c b/operations.c
index 23d571c..870ecf1 100644
--- a/operations.c
+++ b/operations.c
@@ -23,7 +23,7 @@
#include <linux/audit.h>
#include <errno.h>
-#include "gluten.h"
+#include "common/gluten.h"
#include "operations.h"
static bool is_cookie_valid(int notifyFd, uint64_t id)
@@ -31,14 +31,14 @@ static bool is_cookie_valid(int notifyFd, uint64_t id)
return ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) == 0;
}
-static int send_target(const struct seccomp_notif_resp *resp, int notifyfd)
+static int send_target(const struct seccomp_notif_resp *resp, int notifier)
{
- if (!is_cookie_valid(notifyfd, resp->id)) {
+ if (!is_cookie_valid(notifier, resp->id)) {
fprintf(stderr,
"the response id isn't valid\ncheck if the targets has already terminated\n");
- return -1;
+ exit(0);
}
- if (ioctl(notifyfd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) {
+ if (ioctl(notifier, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) {
if (errno != EINPROGRESS) {
perror("sending the response");
return -1;
@@ -48,14 +48,14 @@ static int send_target(const struct seccomp_notif_resp *resp, int notifyfd)
}
static int send_inject_target(const struct seccomp_notif_addfd *resp,
- int notifyfd)
+ int notifier)
{
- if (!is_cookie_valid(notifyfd, resp->id)) {
+ if (!is_cookie_valid(notifier, resp->id)) {
fprintf(stderr,
"the response id isn't valid\ncheck if the targets has already terminated\n");
return -1;
}
- if (ioctl(notifyfd, SECCOMP_IOCTL_NOTIF_ADDFD, resp) < 0) {
+ if (ioctl(notifier, SECCOMP_IOCTL_NOTIF_ADDFD, resp) < 0) {
if (errno != EINPROGRESS) {
perror("sending the response");
return -1;
@@ -156,9 +156,10 @@ static int execute_syscall(void *args)
exit(0);
}
-static int op_load(struct seccomp_notif *req, int notifier, struct gluten *g,
- struct op_load *load)
+int op_load(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_load *load)
{
+ const long unsigned int *src = gluten_ptr(&req->data, g, load->src);
char path[PATH_MAX];
int fd, ret = 0;
@@ -176,43 +177,21 @@ static int op_load(struct seccomp_notif *req, int notifier, struct gluten *g,
ret = -1;
goto out;
}
-
- memcpy(gluten_write_ptr(g, load->dst),
- gluten_ptr(&req->data, g, load->src),
- load->size);
+ if (pread(fd, gluten_write_ptr(g, load->dst), load->size, *src) < 0) {
+ perror("pread");
+ return -1;
+ }
out:
close(fd);
return ret;
}
-static int resolve_fd(void *data, struct op_resolvedfd *resfd, pid_t pid)
-{
- char fdpath[PATH_MAX], buf[PATH_MAX];
- char *path = (char *)((uint16_t *)data + resfd->path_off);
- int *fd = (int *)((uint16_t *)data + resfd->fd_off);
- ssize_t nbytes;
-
- snprintf(fdpath, PATH_MAX, "/proc/%d/fd/%d", pid, *fd);
- if ((nbytes = readlink(fdpath, buf, resfd->path_size)) < 0) {
- fprintf(stderr, "error reading %s\n", fdpath);
- perror("readlink");
- return -1;
- }
- if (strcmp(path, buf) == 0)
- return 0;
- else
- return 1;
-}
-
int do_call(struct arg_clone *c)
{
char stack[STACK_SIZE];
pid_t child;
- c->ret = -1;
- c->err = 0;
-
/* Create a process that will be moved to the namespace */
child = clone(execute_syscall, stack + sizeof(stack),
CLONE_FILES | CLONE_VM | SIGCHLD, (void *)c);
@@ -224,23 +203,129 @@ int do_call(struct arg_clone *c)
return 0;
}
-static void set_inject_fields(uint64_t id, struct gluten *g,
- const struct op_inject *a,
- struct seccomp_notif_addfd *resp)
+int op_call(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_call *op)
+{
+ struct seccomp_notif_resp resp;
+ struct arg_clone c;
+
+ resp.id = req->id;
+ resp.val = 0;
+ resp.flags = 0;
+ resp.error = 0;
+ c.args = op;
+ c.pid = req->pid;
+ c.err = 0;
+
+ if (do_call(&c) == -1) {
+ resp.error = -1;
+ if (send_target(&resp, notifier) == -1)
+ return -1;
+ }
+ if (c.err != 0) {
+ resp.error = -1;
+ if (send_target(&resp, notifier) == -1)
+ return -1;
+ }
+ /*
+ * The result of the call needs to be save as
+ * reference
+ */
+ if (op->has_ret)
+ memcpy(gluten_write_ptr(g, op->ret), &c.ret, sizeof(c.ret));
+
+ return 0;
+}
+
+int op_block(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_block *op)
+{
+ struct seccomp_notif_resp resp;
+
+ (void)g;
+ resp.id = req->id;
+ resp.val = 0;
+ resp.flags = 0;
+ resp.error = op->error;
+
+ if (send_target(&resp, notifier) == -1)
+ return -1;
+
+ return 0;
+}
+
+int op_return(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_return *op)
+{
+ struct seccomp_notif_resp resp;
+
+ resp.id = req->id;
+ resp.flags = 0;
+ resp.error = 0;
+
+ memcpy(&resp.val, gluten_ptr(NULL, g, op->val), sizeof(resp.val));
+
+ if (send_target(&resp, notifier) == -1)
+ return -1;
+
+ return 0;
+}
+
+int op_continue(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ void *op)
+{
+ struct seccomp_notif_resp resp;
+
+ (void)g;
+ (void)op;
+
+ resp.id = req->id;
+ resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
+ resp.error = 0;
+ resp.val = 0;
+
+ if (send_target(&resp, notifier) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int do_inject(const struct seccomp_notif *req, int notifier,
+ struct gluten *g, struct op_inject *op, bool atomic)
{
- resp->flags = SECCOMP_ADDFD_FLAG_SETFD;
- resp->id = id;
+ struct seccomp_notif_addfd resp;
+
+ resp.flags = SECCOMP_ADDFD_FLAG_SETFD;
+ resp.newfd_flags = 0;
+ resp.id = req->id;
+
+ memcpy(&resp.newfd, gluten_ptr(NULL, g, op->new_fd),
+ sizeof(resp.newfd));
+ memcpy(&resp.srcfd, gluten_ptr(NULL, g, op->new_fd),
+ sizeof(resp.srcfd));
+
+ if (atomic)
+ resp.flags |= SECCOMP_ADDFD_FLAG_SEND;
+ if (send_inject_target(&resp, notifier) == -1)
+ return -1;
+
+ return 0;
+}
- memcpy(&resp->newfd, gluten_ptr(NULL, g, a->new_fd),
- sizeof(resp->newfd));
- memcpy(&resp->srcfd, gluten_ptr(NULL, g, a->new_fd),
- sizeof(resp->srcfd));
+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);
+}
- resp->newfd_flags = 0;
+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);
}
-static int op_cmp(struct seccomp_notif *req, int notifier, struct gluten *g,
- struct op_cmp *op)
+int op_cmp(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_cmp *op)
{
int res = memcmp(gluten_ptr(&req->data, g, op->x),
gluten_ptr(&req->data, g, op->y), op->size);
@@ -249,116 +334,57 @@ static int op_cmp(struct seccomp_notif *req, int notifier, struct gluten *g,
(void)notifier;
if ((res == 0 && (cmp == CMP_EQ || cmp == CMP_LE || cmp == CMP_GE)) ||
- (res < 0 && (cmp == CMP_LT || cmp == CMP_LE)) ||
- (res > 0 && (cmp == CMP_GT || cmp == CMP_GE)))
+ (res < 0 && (cmp == CMP_LT || cmp == CMP_LE)) ||
+ (res > 0 && (cmp == CMP_GT || cmp == CMP_GE)) ||
+ (res != 0 && (cmp == CMP_NE)))
return op->jmp;
- return -1;
+ return 0;
}
-int do_operations(struct gluten *g, struct op *ops, struct seccomp_notif *req,
- unsigned int n_ops, int notifyfd)
+int op_resolve_fd(const struct seccomp_notif *req, int notifier,
+ struct gluten *g, struct op_resolvedfd *op)
{
- struct seccomp_notif_addfd resp_fd;
- struct seccomp_notif_resp resp;
- struct arg_clone c;
- unsigned int i;
- struct op *op;
- int ret;
+ char fdpath[PATH_MAX], buf[PATH_MAX], path[PATH_MAX];
+ ssize_t nbytes;
+ int fd;
- for (i = 0, op = ops; i < n_ops; i++, op++) {
- switch (op->type) {
- case OP_CALL:
- resp.id = req->id;
- resp.val = 0;
- resp.flags = 0;
- c.args = &ops[i].op.call;
- c.pid = req->pid;
- if (do_call(&c) == -1) {
- resp.error = -1;
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- }
- if (c.err != 0) {
- resp.error = -1;
- if (send_target(&resp, notifyfd) == -1)
- return c.err;
- }
- /*
- * The result of the call needs to be save as
- * reference
- */
- if (ops[i].op.call.has_ret) {
- memcpy(gluten_write_ptr(g, op->op.call.ret),
- &c.ret, sizeof(c.ret));
- }
- break;
- case OP_BLOCK:
- resp.id = req->id;
- resp.val = 0;
- resp.flags = 0;
- resp.error = ops[i].op.block.error;
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- break;
- case OP_RETURN:
- resp.id = req->id;
- resp.flags = 0;
- resp.error = 0;
+ (void)notifier;
- memcpy(&resp.val,
- gluten_ptr(&req->data, g, op->op.ret.val),
- sizeof(resp.val));
+ memcpy(&path, gluten_ptr(NULL, g, op->path), op->path_size);
+ memcpy(&fd, gluten_ptr(NULL, g, op->fd), sizeof(fd));
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- break;
+ snprintf(fdpath, PATH_MAX, "/proc/%d/fd/%d", req->pid, fd);
+ if ((nbytes = readlink(fdpath, buf, op->path_size)) < 0) {
+ fprintf(stderr, "error reading %s\n", fdpath);
+ perror("readlink");
+ return -1;
+ }
+ if (strcmp(path, buf) == 0)
+ return op->jmp;
- case OP_CONT:
- resp.id = req->id;
- resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
- resp.error = 0;
- resp.val = 0;
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- break;
- case OP_INJECT_A:
- set_inject_fields(req->id, g, &ops[i].op.inject,
- &resp_fd);
- resp_fd.flags |= SECCOMP_ADDFD_FLAG_SEND;
- if (send_inject_target(&resp_fd, notifyfd) == -1)
- return -1;
- break;
- case OP_INJECT:
- set_inject_fields(req->id, g, &ops[i].op.inject,
- &resp_fd);
- if (send_inject_target(&resp_fd, notifyfd) == -1)
- return -1;
- break;
- case OP_LOAD:
- if (op_load(req, notifyfd, g, &op->op.load))
- return -1;
+ return 0;
+}
- break;
- case OP_END:
- return 0;
- case OP_CMP:
- ret = op_cmp(req, notifyfd, g, (struct op_cmp *)op);
- if (ret == -1)
- return -1;
-
- i = ret;
- break;
- case OP_RESOLVEDFD:
- ret = resolve_fd(g->data, &ops[i].op.resfd, req->pid);
- if (ret == -1)
- return -1;
- else if (ret == 1)
- i = ops[i].op.resfd.jmp;
- break;
+void eval(struct gluten *g, struct op *ops, const struct seccomp_notif *req,
+ int notifier)
+{
+ struct op *op = ops;
+
+ while (op->type != OP_END && op != NULL) {
+ switch (op->type) {
+ 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_INJECT_A, op_inject_a, inject);
+ HANDLE_OP(OP_INJECT, op_inject, inject);
+ HANDLE_OP(OP_LOAD, op_load, load);
+ HANDLE_OP(OP_CMP, op_cmp, cmp);
+ HANDLE_OP(OP_RESOLVEDFD, op_resolve_fd, resfd);
default:
- fprintf(stderr, "unknown operation %d \n", ops[i].type);
+ fprintf(stderr, "unknown operation %d \n", op->type);
+ return;
}
}
- return 0;
}