aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--common/common.c2
-rw-r--r--common/gluten.h16
-rw-r--r--operations.c137
4 files changed, 102 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index 9edf4f2..591e734 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ HEADERS := $(COMMON_DIR)/common.h $(COMMON_DIR)/gluten.h \
$(COMMON_DIR)/numbers.h $(COMMON_DIR)/util.h operations.h
CFLAGS += -DTMP_DATA_SIZE=1000
-CFLAGS += -Wall -Wextra -pedantic -I$(COMMON_DIR)
+CFLAGS += -Wall -Wextra -pedantic -std=c99 -I$(COMMON_DIR)
all: cooker eater seitan
diff --git a/common/common.c b/common/common.c
index cd792de..f67f175 100644
--- a/common/common.c
+++ b/common/common.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <stddef.h>
#include <stdio.h>
#include <string.h>
@@ -11,6 +12,7 @@
#include <linux/audit.h>
#include <linux/seccomp.h>
+#include <linux/limits.h>
#include "util.h"
#include "common.h"
diff --git a/common/gluten.h b/common/gluten.h
index 9bd4689..6c0fc25 100644
--- a/common/gluten.h
+++ b/common/gluten.h
@@ -33,6 +33,7 @@ extern struct seccomp_data anonymous_seccomp_data;
#define NO_FIELD block
#define NS_NUM sizeof(enum ns_type)
+#define GET_BIT(x, i) (((x) & (1UL << (i))) != 0)
enum gluten_offset_type {
OFFSET_RO_DATA = 0,
@@ -113,12 +114,17 @@ struct op_nr {
struct gluten_offset no_match;
};
+struct syscall_desc {
+ unsigned nr : 9;
+ unsigned arg_count : 3;
+ unsigned has_ret : 1;
+ unsigned arg_deref : 6;
+ struct gluten_offset data[];
+};
+
struct op_call {
- struct gluten_offset nr;
- struct gluten_offset args[6];
- struct op_context context;
- struct gluten_offset ret;
- bool has_ret;
+ struct gluten_offset syscall;
+ struct gluten_offset context;
};
struct op_block {
diff --git a/operations.c b/operations.c
index c751919..d28c4b8 100644
--- a/operations.c
+++ b/operations.c
@@ -84,27 +84,70 @@ static void proc_ns_name(unsigned i, char *ns)
}
}
+static struct gluten_offset *get_syscall_ret(struct syscall_desc *s)
+{
+ if (s == NULL)
+ return NULL;
+ if (s->has_ret == 0)
+ return NULL;
+ if (s->arg_count == 0)
+ return s->data;
+ return s->data + s->arg_count + 1;
+}
+
+static int write_syscall_ret(struct gluten *g, struct syscall_desc *s,
+ const struct arg_clone *c)
+{
+ struct gluten_offset *p = get_syscall_ret(s);
+
+ if (p != NULL)
+ return gluten_write(g, *p, &c->ret, sizeof(c->ret));
+
+ return 0;
+}
+
static int prepare_arg_clone(const struct seccomp_notif *req, struct gluten *g,
- const struct op_call *op, struct arg_clone *c)
+ const struct op_call *op, struct syscall_desc *s,
+ struct arg_clone *c)
{
char ns_name[PATH_MAX / 2];
const struct ns_spec *ns;
+ struct op_context context;
char p[PATH_MAX];
+ struct gluten_offset x;
unsigned int i;
+ long arg;
pid_t pid;
+ if (gluten_read(NULL, g, s, op->syscall, sizeof(struct syscall_desc)) == -1)
+ return -1;
+ if (gluten_read(NULL, g, &context, op->context, sizeof(context)) == -1)
+ return -1;
+
c->err = 0;
c->ret = -1;
+ c->nr = s-> nr;
- if (gluten_read(NULL, g, &c->nr, op->nr, sizeof(c->nr)) == -1)
- return -1;
- for (i = 0; i < 6; i++)
- if (gluten_read(NULL, g, &c->args[i], op->args[i],
- sizeof(c->args[i])) == -1)
+ for (i = 0; i < s->arg_count; i++) {
+ if (gluten_read(NULL, g, &arg, s->data[i], sizeof(arg)) == -1)
return -1;
+ /* If arg is a pointer then need to calculate the absolute
+ * address and the value of arg is the relative offset of the actual
+ * value.
+ */
+ if (GET_BIT(s->arg_deref, i) == 1) {
+ x.type = s->data[i].type;
+ x.offset = arg;
+ if (gluten_read(NULL, g, &c->args[i], x,
+ sizeof(c->args[i])) == -1)
+ return -1;
+ } else {
+ c->args[i] = (void *)arg;
+ }
+ }
- for (i = 0; i < sizeof(enum ns_type); i++) {
- ns = &op->context.ns[i];
+ for (i = 0; i < NS_NUM; i++) {
+ ns = &context.ns[i];
proc_ns_name(i, ns_name);
switch (ns->type) {
case NS_NONE:
@@ -127,6 +170,7 @@ static int prepare_arg_clone(const struct seccomp_notif *req, struct gluten *g,
break;
}
}
+
return 0;
}
@@ -165,40 +209,6 @@ static int execute_syscall(void *args)
exit(0);
}
-int op_load(const struct seccomp_notif *req, int notifier, struct gluten *g,
- struct op_load *load)
-{
- const long unsigned int *src = gluten_ptr(&req->data, g, load->src);
- char path[PATH_MAX];
- int fd, ret = 0;
-
- 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);
-
- /*
- * Avoid the TOCTOU and check if the read mappings are still valid
- */
- if (!is_cookie_valid(notifier, req->id)) {
- err("the seccomp request isn't valid anymore");
- ret = -1;
- goto out;
- }
- if (!check_gluten_limits(load->dst, load->size)) {
- ret = -1;
- goto out;
- }
- if (pread(fd, gluten_write_ptr(g, load->dst), load->size, *src) < 0) {
- err("pread");
- ret = -1;
- goto out;
- }
-
-out:
- close(fd);
- return ret;
-}
-
int do_call(struct arg_clone *c)
{
char stack[STACK_SIZE];
@@ -216,6 +226,7 @@ int op_call(const struct seccomp_notif *req, int notifier, struct gluten *g,
struct op_call *op)
{
struct seccomp_notif_resp resp;
+ struct syscall_desc s;
struct arg_clone c;
resp.id = req->id;
@@ -223,7 +234,7 @@ int op_call(const struct seccomp_notif *req, int notifier, struct gluten *g,
resp.flags = 0;
resp.error = 0;
- if (prepare_arg_clone(req, g, op, &c) == -1)
+ if (prepare_arg_clone(req, g, op, &s, &c) == -1)
return -1;
debug(" op_call: execute syscall nr=%ld", c.nr);
if (do_call(&c) == -1) {
@@ -237,14 +248,42 @@ int op_call(const struct seccomp_notif *req, int notifier, struct gluten *g,
if (send_target(&resp, notifier) == -1)
return -1;
}
+
+ return write_syscall_ret(g, &s, &c);
+}
+
+int op_load(const struct seccomp_notif *req, int notifier, struct gluten *g,
+ struct op_load *load)
+{
+ const long unsigned int *src = gluten_ptr(&req->data, g, load->src);
+ char path[PATH_MAX];
+ int fd, ret = 0;
+
+ 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);
+
/*
- * The result of the call needs to be save as
- * reference
- */
- if (op->has_ret)
- return gluten_write(g, op->ret, &c.ret, sizeof(c.ret));
+ * Avoid the TOCTOU and check if the read mappings are still valid
+ */
+ if (!is_cookie_valid(notifier, req->id)) {
+ err("the seccomp request isn't valid anymore");
+ ret = -1;
+ goto out;
+ }
+ if (!check_gluten_limits(load->dst, load->size)) {
+ ret = -1;
+ goto out;
+ }
+ if (pread(fd, gluten_write_ptr(g, load->dst), load->size, *src) < 0) {
+ err("pread");
+ ret = -1;
+ goto out;
+ }
- return 0;
+out:
+ close(fd);
+ return ret;
}
int op_block(const struct seccomp_notif *req, int notifier, struct gluten *g,