diff options
-rw-r--r-- | gluten.h | 12 | ||||
-rw-r--r-- | operations.c | 49 | ||||
-rw-r--r-- | operations.h | 6 |
3 files changed, 62 insertions, 5 deletions
@@ -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 */ |