From 36cbebd3c81b75f709ac5e6f6df36e0e37893d3d Mon Sep 17 00:00:00 2001
From: Alice Frosi <afrosi@redhat.com>
Date: Wed, 22 Feb 2023 17:13:59 +0100
Subject: operations: add op_copy

---
 gluten.h     | 12 ++++++++++++
 operations.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 operations.h |  6 ++++--
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/gluten.h b/gluten.h
index 1b6c3d1..57b53ad 100644
--- a/gluten.h
+++ b/gluten.h
@@ -50,6 +50,7 @@ enum op_type {
 	OP_INJECT,
 	OP_INJECT_A,
 	OP_RETURN,
+	OP_COPY_ARGS,
 };
 
 enum value_type {
@@ -94,6 +95,16 @@ struct op_inject {
 	struct fd_type oldfd;
 };
 
+struct copy_arg {
+	uint16_t args_off;
+	bool need_copied;
+	size_t size;
+};
+
+struct op_copy_args {
+	struct copy_arg args[6];
+};
+
 struct op {
 	enum op_type type;
 	union {
@@ -102,6 +113,7 @@ struct op {
 		struct op_continue cont;
 		struct op_return ret;
 		struct op_inject inj;
+		struct op_copy_args copy;
 	};
 };
 #endif /* GLUTEN_H */
diff --git a/operations.c b/operations.c
index 82b99a8..cd67ccc 100644
--- a/operations.c
+++ b/operations.c
@@ -147,6 +147,43 @@ static int execute_syscall(void *args)
 	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].need_copied)
+			continue;
+		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;
+		}
+	}
+	close(fd);
+	return 0;
+}
+
 int do_call(struct arg_clone *c)
 {
 	char stack[STACK_SIZE];
@@ -187,8 +224,8 @@ static void set_inject_fields(uint64_t id, void *data, const struct op *a,
 	resp->newfd_flags = 0;
 }
 
-int do_operations(void *data, struct op operations[], unsigned int n_operations,
-	       int pid, int notifyfd, uint64_t id)
+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;
@@ -266,8 +303,14 @@ int do_operations(void *data, struct op operations[], unsigned int n_operations,
 			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;
 		default:
-			fprintf(stderr, "unknow operation %d \n", operations[i].type);
+			fprintf(stderr, "unknow operation %d \n",
+				operations[i].type);
 		}
 	}
 	return 0;
diff --git a/operations.h b/operations.h
index aeb09d5..8996065 100644
--- a/operations.h
+++ b/operations.h
@@ -2,6 +2,7 @@
 #define ACTIONS_H
 
 #include <errno.h>
+#include <linux/seccomp.h>
 
 #define STACK_SIZE (1024 * 1024 / 8)
 #define NS_NUM (sizeof(enum ns_type))
@@ -14,6 +15,7 @@ struct arg_clone {
 };
 
 int do_call(struct arg_clone *c);
-int do_operations(void *data, struct op operations[], unsigned int n_operations,
-	       int tpid, int notifyfd, uint64_t id);
+int do_operations(void *data, struct op operations[], struct seccomp_notif *req,
+		  unsigned int n_operations, int tpid, int notifyfd,
+		  uint64_t id);
 #endif /* ACTIONS_H */
-- 
cgit v1.2.3