3#include "thread_impl.h"
6#include <linux/sched.h>
12#include <sys/syscall.h>
14#include <sys/random.h>
17#define DEFAULT_STACK_SIZE (3 * 1024)
35long clod_execution_bootstrap(
const struct clone_args *args,
struct stack_header *stack);
36int clod_execution_main(
const struct stack_header *stack);
45 clod_process_main *main;
50static_assert(offsetof(
struct stack_header, stack_guard) == 0x28);
51static_assert(offsetof(
struct stack_header, errno_location) == 0x10);
53#pragma GCC diagnostic push
55#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
58long clod_execution_bootstrap(
const struct clone_args *args,
struct stack_header *stack) {
61 "mov %[args], %%rdi\n"
62 "mov %[args_size], %%rsi\n"
63 "mov %[clone3], %%eax\n"
70 "push %[stack_size]\n"
71 "mov %[stack], %%rdi\n"
80 "mov %[munmap], %%eax\n"
85 "mov %[exit], %%eax\n"
90 "mov %%rax, %[result]\n"
92 [result]
"=r" (result)
94 [args]
"r" ((long)args),
95 [stack]
"r" ((long)stack),
96 [stack_ptr]
"r" ((long)stack->stack),
97 [stack_size]
"r" ((long)stack->stack_size),
98 [main]
"r" ((long)&clod_execution_main),
100 [args_size]
"i" ((long)
sizeof(
struct clone_args)),
101 [clone3]
"i" (SYS_clone3),
102 [munmap]
"i" (SYS_munmap),
103 [exit]
"i" (SYS_exit)
107 "rdi", "rsi", "rax", "rcx", "r11", "memory", "cc"
111#pragma GCC diagnostic pop
114#error "Process bootstrap method not implemented for this architecture"
117int clod_execution_main(const struct stack_header *stack) {
118 return stack->main(stack->args->arg_count, stack->args->arg_vector);
121void *get_stack(
size_t *stack_size_out) {
122 pid_t tid = gettid();
124 snprintf(buff,
sizeof(buff),
"/proc/self/task/%d/maps", tid);
125 FILE *
file = fopen(buff,
"r");
126 if (!
file)
file = fopen(
"/proc/self/maps",
"r");
127 if (!
file)
return nullptr;
129 uintptr_t stack_start = 0, stack_end = 0;
131 while (fgets(buff,
sizeof(buff),
file)) {
132 if (strstr(buff,
"[stack]")) {
134 stack_start = strtoul(buff, &end, 16);
135 stack_end = strtoul(end + 1, &end, 16);
142 if (stack_start == 0 || stack_end == 0)
return nullptr;
143 *stack_size_out = stack_end - stack_start;
144 return (
void*)stack_start;
149 return CLOD_PROCESS_INVALID;
151 return CLOD_PROCESS_INVALID;
153 size_t stack_header_size =
sizeof(
struct stack_header);
160 size_t stack_header_offset = 0;
161 size_t stack_args_offset = ALIGN(stack_header_offset + stack_header_size, 16);
163 size_t stack_offset = stack_args_offset + stack_args_size;
164 size_t stack_size = stack_offset;
166 stack_size = ALIGN(stack_size + 4096, 4096);
170 PROT_READ | PROT_WRITE,
171 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK,
174 if (stack == MAP_FAILED)
175 return CLOD_PROCESS_NO_MEMORY;
176 mprotect(stack, 4096, PROT_NONE);
178 char *stack_data = stack + stack_size - stack_offset;
179 auto header = (
struct stack_header *)(stack_data + stack_header_offset);
182 header->main = opts->
main;
183 header->errno_location = &header->error_number;
184 header->stack = stack;
185 header->stack_size = stack_size;
187 getrandom(&header->stack_guard,
sizeof(header->stack_guard), 0);
188 header->stack_guard &= ~(uint64_t)0xFF;
195 struct clone_args clone_args = {0};
196 clone_args.stack = (__u64)stack;
197 clone_args.stack_size = stack_size - stack_offset;
198 clone_args.tls = (__u64)stack_data;
200 switch (opts->
type) {
202 CLONE_VM | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND | CLONE_FS | CLONE_IO | CLONE_SYSVSEM | CLONE_SETTLS;
205 CLONE_VM | CLONE_FILES | CLONE_SIGHAND | CLONE_FS | CLONE_IO | CLONE_SYSVSEM | CLONE_SETTLS;
208 CLONE_VM | CLONE_FILES | CLONE_CLEAR_SIGHAND | CLONE_SETTLS;
215 clone_args.child_tid = (__u64)&process->child_tid;
216 clone_args.flags |= CLONE_CHILD_SETTID;
217 *process_out = &process->common;
220 long res = clod_execution_bootstrap(&clone_args, header);
222 if (process) free(process);
223 munmap(stack, stack_size);
225 case ENOMEM:
return CLOD_PROCESS_NO_MEMORY;
226 default:
return CLOD_PROCESS_INVALID;
230 return CLOD_PROCESS_OK;
235 syscall(SYS_futex_wait, &linux_process->child_tid, 0,
nullptr,
nullptr, 0);
236 return CLOD_PROCESS_OK;
clod_process_main * main
Process entry point.
int arg_count
Number of arguments passed to main.
enum clod_process_type type
Type of process to create.