github.com/SamWhited/moby@v1.13.1/contrib/syscall-test/userns.c (about) 1 #define _GNU_SOURCE 2 #include <errno.h> 3 #include <sched.h> 4 #include <signal.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/mman.h> 9 #include <sys/wait.h> 10 #include <unistd.h> 11 12 #define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */ 13 14 struct clone_args { 15 char **argv; 16 }; 17 18 // child_exec is the func that will be executed as the result of clone 19 static int child_exec(void *stuff) 20 { 21 struct clone_args *args = (struct clone_args *)stuff; 22 if (execvp(args->argv[0], args->argv) != 0) { 23 fprintf(stderr, "failed to execvp argments %s\n", 24 strerror(errno)); 25 exit(-1); 26 } 27 // we should never reach here! 28 exit(EXIT_FAILURE); 29 } 30 31 int main(int argc, char **argv) 32 { 33 struct clone_args args; 34 args.argv = &argv[1]; 35 36 int clone_flags = CLONE_NEWUSER | SIGCHLD; 37 38 // allocate stack for child 39 char *stack; /* Start of stack buffer */ 40 char *child_stack; /* End of stack buffer */ 41 stack = 42 mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, 43 MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0); 44 if (stack == MAP_FAILED) { 45 fprintf(stderr, "mmap failed: %s\n", strerror(errno)); 46 exit(EXIT_FAILURE); 47 } 48 child_stack = stack + STACK_SIZE; /* Assume stack grows downward */ 49 50 // the result of this call is that our child_exec will be run in another 51 // process returning its pid 52 pid_t pid = clone(child_exec, child_stack, clone_flags, &args); 53 if (pid < 0) { 54 fprintf(stderr, "clone failed: %s\n", strerror(errno)); 55 exit(EXIT_FAILURE); 56 } 57 // lets wait on our child process here before we, the parent, exits 58 if (waitpid(pid, NULL, 0) == -1) { 59 fprintf(stderr, "failed to wait pid %d\n", pid); 60 exit(EXIT_FAILURE); 61 } 62 exit(EXIT_SUCCESS); 63 }