-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
172 lines (153 loc) · 4.34 KB
/
main.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// clone
#define _GNU_SOURCE
#include <sched.h>
// time
#include <time.h>
// IO
#include <stdio.h>
// malloc, getenv
#include <stdlib.h>
// waitpid
#include <sys/wait.h>
// execv,sethostname
#include <unistd.h>
// mount
#include <sys/mount.h>
#include <sys/stat.h>
#include <string.h>
/******
* Functions declaration *
******/
void run(int argc, char **argv);
// Function to be used with clone
int processRun(void *args);
// Program manual
void manual();
/******
* Structs *
******/
struct run_data {
int size;
char **args;
};
/******
* Entry Point *
******/
int main(int argc, char **argv) {
if (argc < 2) {
manual();
exit(0);
}
if (strcmp(argv[1], "run") || strcmp(argv[1], "r")) {
if (argc < 3) {
printf("Please speficy a command to run.\n");
exit(1);
}
char *data = getenv("BOKS_IMAGE");
if (!data) {
printf(
"Please make sure that filesystem path is defined by BOKS_IMAGE env "
"variable.\n");
exit(1);
}
run(argc, argv);
}
if (strcmp(argv[1], "help") || strcmp(argv[1], "h")) {
manual();
}
return 0;
}
// Handle running command on container
void run(int argc, char **argv) {
// Flags to be used when cloning the processs
// CLONE_NEWUTS provides hostname and NIS Domain name isolation
// CLONE_NEWPID alllows created container to have it's own PID namespace
// -> this will not alter ps result as it gathers info from /proc
// CLONE_NEWNS mount a new namespace rather than living in the same one
// -> with it's parent
int namespaces = CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS;
// clone the process with the namepaces flags and run startAction inside of
// it. CLONE require CAP_SYS_ADMIN thus needs to be run as root.
struct run_data data;
data.args = argv;
data.size = argc;
void *args = (void *)&data;
pid_t child_pid =
clone(processRun, malloc(4096) + 4096, SIGCHLD | namespaces, args);
if (child_pid == -1) {
perror("Process clone error");
exit(1);
}
// Wait for child_pid to die (await)
waitpid(child_pid, NULL, 0);
}
int processRun(void *args) {
// Generate container hostname
srand ( time(NULL) );
char* my_array[7] = {"elephant","wolf","eagle","tortoise","dog","tiger"};
int random_index = rand() % 7;
char* random_value = my_array[random_index];
// Set container hostname
char *hostname = random_value;
int result = sethostname(hostname, sizeof(hostname));
// setup cgroup
char *cgroup_path = "sys/fs/cgroup/pids/boks";
mkdir(cgroup_path, 0755);
FILE *max_pid_file = fopen(strcat(cgroup_path, "/pids.max"), "w+");
if (fputs("10", max_pid_file) < 0) {
printf("Unable to set max pids cgroup");
exit(1);
}
fclose(max_pid_file);
FILE *notify_on_release_file =
fopen(strcat(cgroup_path, "/notify_on_release"), "w+");
if (fputs("1", notify_on_release_file) < 0) {
printf("Unable to set notify on release cgroup");
exit(1);
}
fclose(notify_on_release_file);
FILE *cgroup_procs_file = fopen(strcat(cgroup_path, "/cgroup.procs"), "w+");
int process_id = getpid();
char pid_string[30];
sprintf(pid_string, "%d", process_id);
if (fputs(pid_string, cgroup_procs_file) < 0) {
printf("Unable to set cgroup procs");
exit(1);
}
fclose(cgroup_procs_file);
// Set base directory to those of BOKS_IMAGE
char *new_root_path = getenv("BOKS_IMAGE");
if (!new_root_path) {
printf("Unable to get BOKS_IMAGE env variable.\n");
exit(1);
}
if (chroot(new_root_path) < 0) {
printf("Unable to set filesystem root, make sure that %s is "
"correct.\n",
new_root_path);
exit(1);
}
// change to /
if (chdir("/") < 0) {
printf("Unable to switch to root dir of image.\n");
exit(1);
}
// Mount proc to enable process data sharing between kernel and userspace
if (mount("/proc", "proc", "proc", 0, "") < 0) {
printf("Unable to mount proc.\n");
exit(1);
}
// run command
struct run_data *data = (struct run_data *)args;
char **execution_data = malloc((data->size - 2) * sizeof(char **));
memcpy(execution_data, data->args + 2, (data->size - 2) * sizeof(char **));
result = execv(data->args[2], execution_data);
if (result != 0) {
printf("Unable to execute command\n");
}
umount("/proc");
exit(result);
}
void manual() {
printf("#BOKS_IMAGE={{environment}} ./boks {{command}} {{args..}}\n" );
}