forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.c
167 lines (147 loc) · 4.85 KB
/
init.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
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include "fs/devices.h"
#include "fs/fd.h"
#include "fs/real.h"
#include "fs/tty.h"
#include "kernel/calls.h"
#include "kernel/init.h"
int mount_root(const struct fs_ops *fs, const char *source) {
char source_realpath[MAX_PATH + 1];
if (realpath(source, source_realpath) == NULL)
return errno_map();
int err = do_mount(fs, source_realpath, "", "", 0);
if (err < 0)
return err;
return 0;
}
static void establish_signal_handlers() {
extern void sigusr1_handler(int sig);
struct sigaction sigact;
sigact.sa_handler = sigusr1_handler;
sigact.sa_flags = 0;
sigemptyset(&sigact.sa_mask);
sigaddset(&sigact.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &sigact, NULL);
signal(SIGPIPE, SIG_IGN);
}
// copied from include/asm-generic/resource.h in the kernel
static struct rlimit_ init_rlimits[16] = {
[RLIMIT_CPU_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_FSIZE_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_DATA_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_STACK_] = {8*1024*1024, RLIM_INFINITY_},
[RLIMIT_CORE_] = {0, RLIM_INFINITY_},
[RLIMIT_RSS_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_NPROC_] = {1024, 1024},
[RLIMIT_NOFILE_] = {1024, 4096},
[RLIMIT_MEMLOCK_] = {64*1024, 64*1024},
[RLIMIT_AS_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_LOCKS_] = {RLIM_INFINITY_, RLIM_INFINITY_},
[RLIMIT_SIGPENDING_] = {1024, 1024},
[RLIMIT_MSGQUEUE_] = {819200, 819200},
[RLIMIT_NICE_] = {0, 0},
[RLIMIT_RTPRIO_] = {0, 0},
[RLIMIT_RTTIME_] = {RLIM_INFINITY_, RLIM_INFINITY_},
};
// TODO error propagation
static struct task *construct_task(struct task *parent) {
struct task *task = task_create_(parent);
struct tgroup *group = malloc(sizeof(struct tgroup));
*group = (struct tgroup) {};
list_init(&group->threads);
lock_init(&group->lock);
cond_init(&group->child_exit);
cond_init(&group->stopped_cond);
memcpy(group->limits, init_rlimits, sizeof(init_rlimits));
group->leader = task;
list_add(&group->threads, &task->group_links);
task->group = group;
task->tgid = task->pid;
task_setsid(task);
task_set_mm(task, mm_new());
task->sighand = sighand_new();
task->files = fdtable_new(3); // why is there a 3 here
task->fs = fs_info_new();
task->fs->umask = 0022;
// we'll need to have current set to do the open call
struct task *old_current = current;
current = task;
task->fs->root = generic_open("/", O_RDONLY_, 0);
if (IS_ERR(task->fs->root))
return PTR_ERR(ERR_PTR(task->fs->root));
task->fs->pwd = fd_retain(task->fs->root);
current = old_current;
return task;
}
int become_first_process() {
// now seems like a nice time
establish_signal_handlers();
struct task *task = construct_task(NULL);
if (IS_ERR(task))
return PTR_ERR(task);
current = task;
return 0;
}
int become_new_init_child() {
// locking? who needs locking?!
struct task *init = pid_get_task(1);
assert(init != NULL);
struct task *task = construct_task(init);
if (IS_ERR(task))
return PTR_ERR(task);
// these are things we definitely don't want to inherit
task->clear_tid = 0;
task->vfork = NULL;
task->blocked = task->pending = task->waiting = 0;
list_init(&task->queue);
// TODO: think about whether it would be a good idea to inherit fs_info
current = task;
return 0;
}
extern int console_major;
extern int console_minor;
void set_console_device(int major, int minor) {
console_major = major;
console_minor = minor;
}
int create_stdio(const char *file, int major, int minor) {
struct fd *fd = generic_open(file, O_RDWR_, 0);
if (IS_ERR(fd)) {
// fallback to adhoc files for stdio
fd = adhoc_fd_create(NULL);
fd->stat.rdev = dev_make(major, minor);
fd->stat.mode = S_IFCHR | S_IRUSR;
fd->flags = O_RDWR_;
int err = dev_open(major, minor, DEV_CHAR, fd);
if (err < 0)
return err;
}
fd->refcount = 0;
current->files->files[0] = fd_retain(fd);
current->files->files[1] = fd_retain(fd);
current->files->files[2] = fd_retain(fd);
return 0;
}
static struct fd *open_fd_from_actual_fd(int fd_no) {
struct fd *fd = adhoc_fd_create(&realfs_fdops);
if (fd == NULL) {
return NULL;
}
fd->real_fd = fd_no;
fd->dir = NULL;
return fd;
}
int create_piped_stdio() {
if (!(current->files->files[0] = open_fd_from_actual_fd(STDIN_FILENO))) {
return -1;
}
if (!(current->files->files[1] = open_fd_from_actual_fd(STDOUT_FILENO))) {
return -1;
}
if (!(current->files->files[2] = open_fd_from_actual_fd(STDERR_FILENO))) {
return -1;
}
return 0;
}