-
Notifications
You must be signed in to change notification settings - Fork 1
/
shns.c
executable file
·145 lines (112 loc) · 2.74 KB
/
shns.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
/*
Tool running a shell in new namespaces
Author: R. Koucha
Date: 22-Jan-2020
*/
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include "util.h"
#define DEFAULT_CMD "/bin/sh"
#define NB_NS_NAME 7
struct ns_list_t {
char *name;
int selected;
int flag;
} ns_list[NB_NS_NAME] = {
{ "ipc", 0, CLONE_NEWIPC },
{ "pid", 0, CLONE_NEWPID },
{ "net", 0, CLONE_NEWNET },
{ "user", 0, CLONE_NEWUSER },
{ "uts", 0, CLONE_NEWUTS },
{ "cgroup", 0, CLONE_NEWCGROUP },
{ "mnt", 0, CLONE_NEWNS }
};
// Set the "selected" field in ns_list[] for the given
// namespace or all (if keyword "all" is passed)
static int select_ns(const char *ns)
{
int i, fnd;
fnd = 0;
for (i = 0; i < NB_NS_NAME; i ++) {
if (!strcmp("all", ns)) {
ns_list[i].selected = 1;
fnd = 1;
} else {
if (!strcmp(ns_list[i].name, ns)) {
ns_list[i].selected = 1;
return 0;
}
}
} // End for
// Bad namespace name
if (!fnd) {
return -1;
}
return 0;
} // select_ns
int main(int ac, char *av[])
{
pid_t child;
int i, rc;
int flags;
if ((ac > 1) && !strcmp(av[1], "-h")) {
fprintf(stderr, "Usage: %s [ns_name1 ns_name2... | all]\n", basename(av[0]));
return 0;
}
// If no namespaces on command line, select all of them
if (ac == 1) {
select_ns("all");
} else {
for (i = 1; i < ac; i ++) {
// Get the requested namespaces
rc = select_ns(av[i]);
if (rc != 0) {
ERR("Bad namespace '%s'\n", av[i]);
return 1;
}
} // End for
} // End if no namespace specified
// For each namespace of the target process, set the flag
flags = 0;
for (i = 0; i < NB_NS_NAME; i ++) {
if (ns_list[i].selected) {
printf("New namespace '%s'\n", ns_list[i].name);
flags |= ns_list[i].flag;
} // End if namespace selected
} // End for
// Create brand new namespaces
rc = unshare(flags);
if (rc != 0) {
ERR("unshare(0x%x): '%m' (%d)\n", flags, errno);
return 1;
}
// Fork a child process
child = fork();
if (!child) {
// Child process
char *av_cmd[] = { DEFAULT_CMD, NULL };
execv(av_cmd[0], av_cmd);
ERR("Unable to run '%s': %m (%d)\n", av_cmd[0], errno);
_exit(1);
} else {
// Father process
int status;
// Wait for the end of the child process
rc = waitpid(child, &status, 0);
if (rc < 0) {
ERR("waitpid(%d): %m (%d)", child, errno);
return 1;
}
printf("program's status: %d (0x%x)\n", status, status);
}
return 0;
} // main