From bdbec30a849807fb5e6841a38cfe0d168e5962b9 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Thu, 21 Dec 2023 12:06:05 +0100 Subject: seitan: Add netlink, sendto()/sendmsg(), iovec handling, demo with routes A bit rough at the moment, but it does the trick. Bonus: setsockopt() (with magic values only, not used in any demo yet). Signed-off-by: Stefano Brivio --- operations.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 4 deletions(-) (limited to 'operations.c') diff --git a/operations.c b/operations.c index 33596aa..507a2f7 100644 --- a/operations.c +++ b/operations.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,8 @@ #include "common/util.h" #include "operations.h" +#include "cooker/calls.h" + static bool is_cookie_valid(int notifyFd, uint64_t id) { return ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) == 0; @@ -301,12 +304,13 @@ static int execute_syscall(void *args) c->ret = syscall(c->nr, c->args[0], c->args[1], c->args[2], c->args[3], c->args[4], c->args[5]); c->err = errno; - debug(" execute syscall %s: ret=%ld errno=%d%s%s", syscall_name_str[c->nr], c->ret, - c->err, *c->cwd ? " cwd=" : "", *c->cwd ? c->cwd : ""); + debug(" execute syscall %s: ret=%ld errno=%d%s%s", syscall_name(c->nr), + c->ret, c->err, *c->cwd ? " cwd=" : "", *c->cwd ? c->cwd : ""); if (c->ret < 0) { perror(" syscall"); exit(EXIT_FAILURE); } + exit(0); } @@ -398,6 +402,65 @@ out: return ret; } +int op_iovload(const struct seccomp_notif *req, int notifier, struct gluten *g, + struct op_iovload *load) +{ + const long unsigned int *iovptr = gluten_ptr(&req->data, g, load->iov); + const size_t *iovlen = gluten_ptr(&req->data, g, load->iovlen); + unsigned char *dst = gluten_write_ptr(g, load->dst); + struct iovec iovbuf[UIO_MAXIOV], *iov = iovbuf; + char path[PATH_MAX]; + char dbuf[BUFSIZ]; + unsigned i, count; + int fd; + + if (!*iovlen || *iovlen >= UIO_MAXIOV) + ret_err(EINVAL, "bad iovlen: %lu", *iovlen); + + debug(" op_iovload: vector at (%s %d) to (%s %d) iovlen=%zu, size=%zu", + gluten_offset_name[load->iov.type], load->iov.offset, + gluten_offset_name[load->dst.type], load->dst.offset, *iovlen, + load->size); + + snprintf(path, sizeof(path), "/proc/%d/mem", req->pid); + if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) + ret_err(-1, "error opening mem for %d", req->pid); + + if (!is_cookie_valid(notifier, req->id)) + ret_err(EIO, "expired seccomp notification"); + + if (!check_gluten_limits(load->dst, load->size)) + ret_err(EINVAL, "destination out of range"); + + if (pread(fd, iov, *iovlen * sizeof(struct iovec), *iovptr) <= 0) + ret_err(EIO, "pread"); + + for (i = 0, count = 0; i < *iovlen && count < load->size; i++, iov++) { + unsigned j, dn = 0; + ssize_t n; + + n = pread(fd, dst + count, + MIN(load->size - count, iov->iov_len), + (intptr_t)iov->iov_base); + + if (n < 0) + ret_err(EIO, "pread"); + + for (j = 0; j < n; j++) { + dn += snprintf(dbuf + dn, BUFSIZ - dn, "%02x ", + dst[count + j]); + } + + count += n; + } + + debug(" %s", dbuf); + + close(fd); + + return 0; +} + int op_store(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_store *store) { @@ -672,11 +735,12 @@ int op_nr(const struct seccomp_notif *req, int notifier, struct gluten *g, if (gluten_read(NULL, g, &nr, op->nr, sizeof(nr)) == -1) return -1; - debug(" op_nr: checking syscall %s", syscall_name_str[nr]); + + debug(" op_nr: checking syscall %s (%li)", syscall_name(nr), nr); if (nr == req->data.nr) return 0; - debug(" op_nr: jmp to instr %d", op->no_match.offset); + debug(" op_nr: no match: jump to #%d", op->no_match.offset); return op->no_match.offset; } @@ -702,6 +766,7 @@ int eval(struct gluten *g, const struct seccomp_notif *req, HANDLE_OP(OP_FD, op_fd, fd, g); HANDLE_OP(OP_LOAD, op_load, load, g); HANDLE_OP(OP_STORE, op_store, store, g); + HANDLE_OP(OP_IOVLOAD, op_iovload, iovload, g); HANDLE_OP(OP_BITWISE, op_bitwise, bitwise, g); HANDLE_OP(OP_CMP, op_cmp, cmp, g); HANDLE_OP(OP_RESOLVEDFD, op_resolve_fd, resfd, g); -- cgit v1.2.3