aboutgitcodelistschat:MatrixIRC
path: root/operations.c
diff options
context:
space:
mode:
authorAlice Frosi <afrosi@redhat.com>2023-03-24 10:07:48 +0100
committerAlice Frosi <afrosi@redhat.com>2023-03-24 15:38:07 +0100
commit069009f8e39238ec1a67fba6cfb287b9a0cac83e (patch)
tree77f817eb7b96178b71f3d573a83cec19f7fba09c /operations.c
parent06b0f6d323c396ca1df000af96fdd07cc69b06e0 (diff)
downloadseitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar.gz
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar.bz2
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar.lz
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar.xz
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.tar.zst
seitan-069009f8e39238ec1a67fba6cfb287b9a0cac83e.zip
Re-organize project and add license header
Diffstat (limited to 'operations.c')
-rw-r--r--operations.c356
1 files changed, 0 insertions, 356 deletions
diff --git a/operations.c b/operations.c
deleted file mode 100644
index ed23885..0000000
--- a/operations.c
+++ /dev/null
@@ -1,356 +0,0 @@
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <linux/seccomp.h>
-#include <linux/filter.h>
-#include <linux/audit.h>
-#include <errno.h>
-
-#include "gluten.h"
-#include "operations.h"
-
-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)
-{
- if (!is_cookie_valid(notifyfd, 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_SEND, resp) < 0) {
- if (errno != EINPROGRESS) {
- perror("sending the response");
- return -1;
- }
- }
- return 0;
-}
-
-static int send_inject_target(const struct seccomp_notif_addfd *resp,
- int notifyfd)
-{
- if (!is_cookie_valid(notifyfd, 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 (errno != EINPROGRESS) {
- perror("sending the response");
- return -1;
- }
- }
- return 0;
-}
-
-static void proc_ns_name(unsigned i, char *ns)
-{
- switch (i) {
- case NS_CGROUP:
- snprintf(ns, PATH_MAX + 1, "cgroup");
- break;
- case NS_IPC:
- snprintf(ns, PATH_MAX + 1, "ipc");
- break;
- case NS_NET:
- snprintf(ns, PATH_MAX + 1, "net");
- break;
- case NS_MOUNT:
- snprintf(ns, PATH_MAX + 1, "mnt");
- break;
- case NS_PID:
- snprintf(ns, PATH_MAX + 1, "pid");
- break;
- case NS_USER:
- snprintf(ns, PATH_MAX + 1, "user");
- break;
- case NS_UTS:
- snprintf(ns, PATH_MAX + 1, "uts");
- break;
- case NS_TIME:
- snprintf(ns, PATH_MAX + 1, "time");
- break;
- default:
- fprintf(stderr, "unrecognized namespace index %d\n", i);
- }
-}
-
-static int set_namespaces(const struct op_call *a, int tpid)
-{
- char path[PATH_MAX + 1];
- char ns_name[PATH_MAX / 2];
- struct ns_spec ns;
- int fd;
- unsigned int i;
-
- for (i = 0, ns = (a->context).ns[i]; i < sizeof(enum ns_type);
- i++, ns = (a->context).ns[i]) {
- proc_ns_name(i, ns_name);
- switch (ns.type) {
- case NS_NONE:
- continue;
- case NS_SPEC_TARGET:
- snprintf(path, sizeof(path), "/proc/%d/ns/%s", tpid,
- ns_name);
- break;
- case NS_SPEC_PID:
- snprintf(path, sizeof(path), "/proc/%d/ns/%s", ns.pid,
- ns_name);
- break;
- case NS_SPEC_PATH:
- snprintf(path, sizeof(path), "%s", ns.path);
- break;
- }
-
- if ((fd = open(path, O_CLOEXEC)) < 0) {
- fprintf(stderr, "open for file %s: %s", path,
- strerror(errno));
- return -1;
- }
-
- if (setns(fd, 0) != 0) {
- perror("setns");
- return -1;
- }
- }
- return 0;
-}
-
-static int execute_syscall(void *args)
-{
- struct arg_clone *a = (struct arg_clone *)args;
- const struct op_call *c = a->args;
-
- if (set_namespaces(a->args, a->pid) < 0) {
- exit(EXIT_FAILURE);
- }
- /* execute syscall */
- a->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) {
- perror("syscall");
- exit(EXIT_FAILURE);
- }
- exit(0);
-}
-
-int copy_args(struct seccomp_notif *req, struct op_copy_args *copy, void *data,
- int notifier)
-{
- char path[PATH_MAX];
- unsigned int i;
- ssize_t nread;
- void *dest;
- int fd;
-
- snprintf(path, sizeof(path), "/proc/%d/mem", req->pid);
- if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
- perror("open mem");
- return -1;
- }
-
- /*
- * Avoid the TOCTOU and check if the read mappings are still valid
- */
- if (!is_cookie_valid(notifier, req->id)) {
- fprintf(stderr, "the seccomp request isn't valid anymore\n");
- return -1;
- }
- for (i = 0; i < 6; i++) {
- if (copy->args[i].type == REFERENCE) {
- dest = (uint16_t *)data + copy->args[i].args_off;
- nread = pread(fd, dest, copy->args[i].size,
- req->data.args[i]);
- if (nread < 0) {
- perror("pread");
- return -1;
- }
- } else {
- memcpy((uint16_t *)data + copy->args[i].args_off,
- &req->data.args[i], copy->args[i].size);
- }
- }
- close(fd);
- 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];
- 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);
- if (child == -1) {
- perror("clone");
- return -1;
- }
- wait(NULL);
- return 0;
-}
-
-static void set_inject_fields(uint64_t id, void *data, const struct op *a,
- struct seccomp_notif_addfd *resp)
-{
- const struct fd_type *new = &(a->inj).newfd;
- const struct fd_type *old = &(a->inj).oldfd;
-
- resp->flags = SECCOMP_ADDFD_FLAG_SETFD;
- resp->id = id;
- if (new->type == IMMEDIATE)
- resp->newfd = new->fd;
- else
- memcpy(&resp->srcfd, (uint16_t *)data + old->fd_off,
- sizeof(resp->srcfd));
- if (old->type == IMMEDIATE)
- resp->srcfd = old->fd;
- else
- memcpy(&resp->srcfd, (uint16_t *)data + old->fd_off,
- sizeof(resp->srcfd));
- resp->newfd_flags = 0;
-}
-
-int do_operations(void *data, struct op operations[], struct seccomp_notif *req,
- unsigned int n_operations, int pid, int notifyfd, uint64_t id)
-{
- struct seccomp_notif_addfd resp_fd;
- 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) {
- case OP_CALL:
- resp.id = id;
- resp.val = 0;
- resp.flags = 0;
- c.args = &operations[i].call;
- c.pid = 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 (operations[i].call.has_ret) {
- memcpy((uint16_t *)data +
- operations[i].call.ret_off,
- &c.ret, sizeof(c.ret));
- }
- break;
- case OP_BLOCK:
- resp.id = id;
- resp.val = 0;
- resp.flags = 0;
- resp.error = operations[i].block.error;
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- break;
- case OP_RETURN:
- resp.id = id;
- resp.flags = 0;
- resp.error = 0;
- if (operations[i].ret.type == IMMEDIATE)
- resp.val = operations[i].ret.value;
- else
- memcpy(&resp.val,
- (uint16_t *)data +
- operations[i].ret.value_off,
- sizeof(resp.val));
-
- if (send_target(&resp, notifyfd) == -1)
- return -1;
- break;
-
- case OP_CONT:
- resp.id = 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(id, data, &operations[i], &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(id, data, &operations[i], &resp_fd);
- if (send_inject_target(&resp_fd, notifyfd) == -1)
- return -1;
- break;
- case OP_COPY_ARGS:
- if (copy_args(req, &operations[i].copy, data,
- notifyfd) < 0)
- return -1;
- break;
- case OP_END:
- return 0;
- case OP_CMP:
- if (memcmp((uint16_t *)data + operations[i].cmp.s1_off,
- (uint16_t *)data + operations[i].cmp.s2_off,
- operations[i].cmp.size) != 0) {
- 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);
- }
- }
- return 0;
-}