-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathmount.c
116 lines (94 loc) · 2.77 KB
/
mount.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#define _GNU_SOURCE
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include "contain.h"
static char *root;
static void bindnode(char *src, char *dst) {
int fd;
if ((fd = open(dst, O_WRONLY | O_CREAT, 0600)) >= 0)
close(fd);
if (mount(src, dst, NULL, MS_BIND, NULL) < 0)
errx(EXIT_FAILURE, "Failed to bind %s into new /dev filesystem", src);
}
static void cleanup(void) {
if (root) {
umount2(root, MNT_DETACH);
rmdir(root);
}
}
void createroot(char *src, int console, char *helper) {
mode_t mask;
pid_t child;
root = tmpdir();
atexit(cleanup);
if (mount(src, root, NULL, MS_BIND | MS_REC, NULL) < 0)
errx(EXIT_FAILURE, "Failed to bind new root filesystem");
else if (chdir(root) < 0)
errx(EXIT_FAILURE, "Failed to enter new root filesystem");
mask = umask(0);
mkdir("dev" , 0755);
if (mount("tmpfs", "dev", "tmpfs", 0, "mode=0755") < 0)
errx(EXIT_FAILURE, "Failed to mount /dev tmpfs in new root filesystem");
mkdir("dev/pts", 0755);
if (mount("devpts", "dev/pts", "devpts", 0, "newinstance,ptmxmode=666") < 0)
errx(EXIT_FAILURE, "Failed to mount /dev/pts in new root filesystem");
mkdir("dev/tmp", 0755);
umask(mask);
if (console >= 0)
bindnode(ptsname(console), "dev/console");
bindnode("/dev/full", "dev/full");
bindnode("/dev/null", "dev/null");
bindnode("/dev/random", "dev/random");
bindnode("/dev/tty", "dev/tty");
bindnode("/dev/urandom", "dev/urandom");
bindnode("/dev/zero", "dev/zero");
symlink("pts/ptmx", "dev/ptmx");
if (helper)
switch (child = fork()) {
case -1:
err(EXIT_FAILURE, "fork");
case 0:
execlp(SHELL, SHELL, "-c", helper, NULL);
err(EXIT_FAILURE, "exec %s", helper);
default:
waitforexit(child);
}
}
void enterroot(void) {
if (syscall(__NR_pivot_root, ".", "dev/tmp") < 0)
errx(EXIT_FAILURE, "Failed to pivot into new root filesystem");
if (chdir("/dev/tmp") >= 0) {
while (*root == '/')
root++;
rmdir(root);
}
root = NULL;
if (chdir("/") < 0 || umount2("/dev/tmp", MNT_DETACH) < 0)
errx(EXIT_FAILURE, "Failed to detach old root filesystem");
else
rmdir("/dev/tmp");
}
void mountproc(void) {
mode_t mask;
mask = umask(0);
mkdir("proc" , 0755);
umask(mask);
if (mount("proc", "proc", "proc", 0, NULL) < 0)
errx(EXIT_FAILURE, "Failed to mount /proc in new root filesystem");
}
void mountsys(void) {
mode_t mask;
mask = umask(0);
mkdir("sys" , 0755);
umask(mask);
if (mount("sysfs", "sys", "sysfs", 0, NULL) < 0)
errx(EXIT_FAILURE, "Failed to mount /sys in new root filesystem");
mount("cgroup2", "sys/fs/cgroup", "cgroup2", 0, NULL);
}