From a3d47a8356fd96f9c74a7cd3f58e1df850bb4364 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 15 Mar 2023 14:08:42 +0100 Subject: seitan: add op_resolvedfd The op_resolvedfd verifies that the fd points to a path. Signed-off-by: Alice Frosi --- gluten.h | 9 +++++++++ operations.c | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/gluten.h b/gluten.h index 570d82a..8370cf5 100644 --- a/gluten.h +++ b/gluten.h @@ -53,6 +53,7 @@ enum op_type { OP_COPY_ARGS, OP_END, OP_CMP, + OP_RESOLVEDFD, }; enum value_type { @@ -114,6 +115,13 @@ struct op_cmp { unsigned int jmp; }; +struct op_resolvedfd { + uint16_t fd_off; + uint16_t path_off; + size_t path_size; + unsigned int jmp; +}; + struct op { enum op_type type; union { @@ -124,6 +132,7 @@ struct op { struct op_inject inj; struct op_copy_args copy; struct op_cmp cmp; + struct op_resolvedfd resfd; }; }; #endif /* GLUTEN_H */ diff --git a/operations.c b/operations.c index afc4b00..ed23885 100644 --- a/operations.c +++ b/operations.c @@ -187,6 +187,25 @@ int copy_args(struct seccomp_notif *req, struct op_copy_args *copy, void *data, return 0; } +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]; @@ -234,6 +253,7 @@ int do_operations(void *data, struct op operations[], struct seccomp_notif *req, struct seccomp_notif_resp resp; struct arg_clone c; unsigned int i; + int ret; for (i = 0; i < n_operations; i++) { switch (operations[i].type) { @@ -320,6 +340,13 @@ int do_operations(void *data, struct op operations[], struct seccomp_notif *req, i = operations[i].cmp.jmp; } break; + case OP_RESOLVEDFD: + ret = resolve_fd(data, &operations[i].resfd, pid); + if (ret == -1) + return -1; + else if (ret == 1) + i = operations[i].resfd.jmp; + break; default: fprintf(stderr, "unknow operation %d \n", operations[i].type); -- cgit v1.2.3