-
Notifications
You must be signed in to change notification settings - Fork 0
/
unshare-pid.c
85 lines (69 loc) · 2.15 KB
/
unshare-pid.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
#define _GNU_SOURCE
#include <errno.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#define STACK_SIZE (1024 * 1024)
static int print_pid(void* args)
{
fprintf(
stderr, "[child] PID: %d\n[child] Thread id: %d\n", getpid(), gettid());
return 0;
}
int clone_and_pid(void)
{
char* stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED) {
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
return -1;
}
int pid = clone(print_pid, stack + STACK_SIZE, 0, NULL);
if (pid == -1) {
fprintf(stderr, "error in clone: %s\n", strerror(errno));
munmap(stack, STACK_SIZE); // Clean up stack on failure
return -1;
}
waitpid(pid, NULL, 0);
munmap(stack, STACK_SIZE);
return 0;
}
int main()
{
fprintf(stdout, "[parent] PID: %d\n", getpid());
if (clone_and_pid() != 0)
return 1;
// sleep to let the child be scheduled
sleep(2);
int ret = unshare(CLONE_NEWPID);
if (ret == -1) {
fprintf(stderr, "error in unshare: %s\n", strerror(errno));
return 1;
}
fprintf(stdout,
"[!] unshare executed successfully, children will start from PID 1\n");
fprintf(stdout, "[!] Cloning a child\n");
if (clone_and_pid() != 0)
return 1;
// sleep to let the child be scheduled
sleep(2);
/*
This call should fail, since the first cloned process after
unshare acts as init(1) of the new namespace. Now since the init (or the
previous process) has already exited, we cannot create a new process in
the new namespace. For more information, see: unshare(2) manpage -- The
namespace init process section.
Quoted: " if the first child subsequently
created by a fork(2) terminates, then subsequent calls to fork(2) fail
with ENOMEM "
*/
fprintf(stdout,
"[!] Cloning a child again, this SHOULD FAIL. See comments in the "
"source code !\n");
if (clone_and_pid() != 0)
return 1;
return 0;
}