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
child_exec(void * stuff)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 arguments %s\n",
24 			strerror(errno));
25 		exit(-1);
26 	}
27 	// we should never reach here!
28 	exit(EXIT_FAILURE);
29 }
30 
main(int argc,char ** argv)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 }
64