aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore17
-rw-r--r--Makefile.am2
-rwxr-xr-xbootstrap5
-rw-r--r--configure.ac5
-rw-r--r--main.c58
-rw-r--r--utils.c19
-rw-r--r--utils.h17
7 files changed, 123 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b0e9a62
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+.*
+!.gitignore
+
+Makefile.in
+aclocal.m4
+compile
+configure
+depcomp
+install-sh
+missing
+Makefile
+config.log
+config.status
+*.cache
+
+*.o
+uroot
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a451a6d
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,2 @@
+bin_PROGRAMS = uroot
+uroot_SOURCES = main.c utils.c
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..71f0ee2
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -e
+aclocal
+automake --foreign --add-missing
+autoconf
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..084b6bd
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,5 @@
+AC_INIT([uroot], [0.1], [cynerd@email.cz])
+AM_INIT_AUTOMAKE([-Wall])
+AC_PROG_CC
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..a20f6ff
--- /dev/null
+++ b/main.c
@@ -0,0 +1,58 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+#include "utils.h"
+
+void sigint_handler(int sig) { }
+
+int main(int argc, char **argv) {
+ pid_t ppid = getpid();
+
+ if (!fork()) {
+ system(aprintf("newuidmap %d 0 %d 1 1 65537 65536", ppid, getuid()));
+ system(aprintf("newgidmap %d 0 %d 1 1 65537 65536", ppid, getgid()));
+ kill(ppid, SIGINT);
+ return 0;
+ }
+
+ unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWPID);
+
+ signal(SIGINT, sigint_handler);
+ pause();
+ errno = 0; // Just clear error from pause()
+
+ pid_t chpid = fork();
+ if (chpid) {
+ int stat;
+ waitpid(chpid, &stat, 0);
+ return stat;
+ }
+
+ // mount /sys and /proc
+ mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL);
+ assert_perror(errno);
+ mount("none", "/proc", NULL, MS_REC | MS_PRIVATE, NULL);
+ assert_perror(errno);
+ mount("none", "/sys", NULL, MS_REC | MS_PRIVATE, NULL);
+ assert_perror(errno);
+ mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL);
+ assert_perror(errno);
+
+ // mount proc to root
+ // rbind mount dev and sys to root
+
+ // TODO verify that all upper directories have +rx rights
+ // TODO chroot
+ execv("/bin/sh", NULL);
+}
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..04806dd
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,19 @@
+#include "utils.h"
+
+// Compute the size needed (including \0) to format given message
+size_t printf_len(const char *msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ size_t result = vsnprintf(NULL, 0, msg, args);
+ va_end(args);
+ return result + 1;
+}
+
+// Like sprintf, but returs the string. Expects there's enough space.
+char *printf_into(char *dst, const char *msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ vsprintf(dst, msg, args);
+ va_end(args);
+ return dst;
+}
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..9e5984d
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,17 @@
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <alloca.h>
+
+// Compute the size needed (including \0) to format given message
+size_t printf_len(const char *msg, ...) __attribute__((format(printf, 1, 2)));
+// Like sprintf, but returs the string. Expects there's enough space.
+char *printf_into(char *dst, const char *msg, ...) __attribute__((format(printf, 2, 3)));
+// Like printf, but allocates the data on the stack with alloca and returns. It
+// uses the arguments multiple times, so beware of side effects.
+#define aprintf(...) printf_into(alloca(printf_len(__VA_ARGS__)), __VA_ARGS__)
+
+#endif /* _UTILS_H_ */