From 5a9302bab9c9bb3d1577f04678d074fb7af4115f Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Wed, 15 May 2024 08:49:56 +0200 Subject: Add fsetxattr(), fremovexattr(), open_by_handle_at(), and "virtiofsd demo" Mostly assorted fixes, a new FDGET operation (get a copy of the target file descriptor via pidfd_getfd()) and a new "FD" flag that means we have to do that on direct tag reference. Signed-off-by: Stefano Brivio --- operations.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 10 deletions(-) (limited to 'operations.c') diff --git a/operations.c b/operations.c index 507a2f7..eb8d614 100644 --- a/operations.c +++ b/operations.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -160,7 +161,7 @@ static int prepare_arg_clone(const struct seccomp_notif *req, struct gluten *g, * value. */ if (GET_BIT(s->arg_deref, i) == 1) { - c->args[i] = gluten_ptr(NULL, g, s->args[i]); + c->args[i] = gluten_ptr(&req->data, g, s->args[i]); debug(" read pointer arg%d at offset %d", i, s->args[i].offset); } else if (s->args[i].type == OFFSET_METADATA) { @@ -169,7 +170,7 @@ static int prepare_arg_clone(const struct seccomp_notif *req, struct gluten *g, debug(" read metadata value %s: %d", metadata_type_str[s->args[i].offset], (int *)c->args[i]); } else { - if (gluten_read(NULL, g, &arg, s->args[i], + if (gluten_read(&req->data, g, &arg, s->args[i], sizeof(arg)) == -1) ret_err(-1, " failed reading arg %d", i); debug(" read arg%d at offset %d v=%ld", i, @@ -566,6 +567,27 @@ int op_fd(const struct seccomp_notif *req, int notifier, return 0; } +int op_fdget(const struct seccomp_notif *req, int notifier, + struct gluten *g, struct op_fdget *op) +{ + int pidfd, fd, n; + + (void)notifier; + + if (gluten_read(&req->data, g, &n, op->src, sizeof(n)) == -1) + return -1; + + if ((pidfd = syscall(SYS_pidfd_open, req->pid, 0)) < 0) + die(" pidfd_open"); + + if ((fd = syscall(SYS_pidfd_getfd, pidfd, n, 0)) < 0) + die(" pidfd_getfd"); + + close(pidfd); + + return gluten_write(g, op->dst, &fd, sizeof(fd)); +} + int op_bitwise(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_bitwise *op) { @@ -702,13 +724,14 @@ int op_resolve_fd(const struct seccomp_notif *req, int notifier, struct gluten *g, struct op_resolvefd *op) { const struct resolvefd_desc *desc = gluten_ptr(&req->data, g, op->desc); - char fdpath[PATH_MAX], buf[PATH_MAX]; + char fdpath[PATH_MAX], buf[BUFSIZ], *p = NULL; ssize_t nbytes; int fd; (void)notifier; - debug(" op_resolvefd: fd=(%s %d) path=(%s %d) path_max=%d", + debug(" op_resolvefd: %s fd=(%s %d) path=(%s %d) path_max=%d", + resolvefd_type_str[desc->type], gluten_offset_name[desc->fd.type], desc->fd.offset, gluten_offset_name[desc->path.type], desc->path.offset, desc->path_max); @@ -716,12 +739,51 @@ int op_resolve_fd(const struct seccomp_notif *req, int notifier, if (gluten_read(&req->data, g, &fd, desc->fd, sizeof(fd)) == -1) return -1; - snprintf(fdpath, PATH_MAX, "/proc/%d/fd/%d", req->pid, fd); - if ((nbytes = readlink(fdpath, buf, desc->path_max)) < 0) - ret_err(-1, "error reading %s", buf); + if (desc->type == RESOLVEFD_PATH) { + snprintf(fdpath, PATH_MAX, "/proc/%d/fd/%d", req->pid, fd); + if ((nbytes = readlink(fdpath, buf, desc->path_max)) < 0) + ret_err(-1, "error reading %s", buf); + + p = buf; + } else if (desc->type == RESOLVEFD_MOUNT) { + FILE *fp; + + snprintf(fdpath, PATH_MAX, "/proc/%d/mountinfo", req->pid); + if (!(fp = fopen(fdpath, "r"))) { + err("Couldn't open %s", fdpath); + return -1; + } + + while (fgets(buf, BUFSIZ, fp)) { + long n; + + errno = 0; + n = strtoul(buf, NULL, 0); + if (errno) { + fclose(fp); + return -errno; + } + + if (n == fd) { + int i; + + for (i = 0; i < 5; i++) + p = strtok(i ? NULL : buf, " "); + + break; + } + } + + fclose(fp); + + if (!p) { + err("No mountpoint for mount_fd %i", fd); + return -1; + } + } - debug(" op_resolvefd: fd %d -> path: %s", fd, buf); - gluten_write(g, desc->path, &buf, desc->path_max); + debug(" op_resolvefd: fd %d -> path: %s", fd, p); + gluten_write(g, desc->path, p, desc->path_max); return 0; } @@ -764,12 +826,13 @@ int eval(struct gluten *g, const struct seccomp_notif *req, HANDLE_OP(OP_CALL, op_call, call, g); HANDLE_OP(OP_RETURN, op_return, ret, g); HANDLE_OP(OP_FD, op_fd, fd, g); + HANDLE_OP(OP_FDGET, op_fdget, fdget, 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); + HANDLE_OP(OP_RESOLVEFD, op_resolve_fd, resfd, g); HANDLE_OP(OP_NR, op_nr, nr, g); HANDLE_OP(OP_COPY, op_copy, copy, g); default: -- cgit v1.2.3