summaryrefslogtreecommitdiff
path: root/python/runner/sandbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'python/runner/sandbox.c')
-rw-r--r--python/runner/sandbox.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/python/runner/sandbox.c b/python/runner/sandbox.c
new file mode 100644
index 0000000..12e2720
--- /dev/null
+++ b/python/runner/sandbox.c
@@ -0,0 +1,47 @@
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char* argv[])
+{
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s USERNAME FILE\n", argv[0]);
+ return 1;
+ }
+
+ // switch user (requires root or "setcap cap_setuid,cap_setgid+ep")
+ char const* username = argv[1];
+ struct passwd const* pw = getpwnam(username);
+ if (!pw) {
+ fprintf(stderr, "no such user: %s\n", username);
+ return 1;
+ }
+ int ret = 0;
+ if ((ret = setuid(pw->pw_uid)) != 0)
+ fprintf(stderr, "setuid returned %d\n", ret);
+ if ((ret = setgid(pw->pw_gid)) != 0)
+ fprintf(stderr, "setgid returned %d\n", ret);
+
+ // limit CPU time to 1 second
+ struct rlimit const cpu_limit = { .rlim_cur = 1, .rlim_max = 1 };
+ if ((ret = setrlimit(RLIMIT_CPU, &cpu_limit)) != 0)
+ fprintf(stderr, "setrlimit(CPU) returned %d\n", ret);
+
+ // don't allow writing files of any size
+ struct rlimit const fsize_limit = { .rlim_cur = 0, .rlim_max = 0 };
+ if ((ret = setrlimit(RLIMIT_FSIZE, &fsize_limit)) != 0)
+ fprintf(stderr, "setrlimit(FSIZE) returned %d\n", ret);
+
+ // there will be no fork
+ struct rlimit const nproc_limit = { .rlim_cur = 0, .rlim_max = 0 };
+ if ((ret = setrlimit(RLIMIT_NPROC, &nproc_limit)) != 0)
+ fprintf(stderr, "setrlimit(NPROC) returned %d\n", ret);
+
+ char* const args[] = { argv[2], (char*)0 };
+ return execvp(argv[2], args);
+}