1 |
commit: d96587d02f203e2c40790ac1c0e5778c6299d1a2 |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Sep 21 01:08:02 2015 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Sep 27 06:21:29 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=d96587d0 |
7 |
|
8 |
sandbox: enable support for linux namespaces |
9 |
|
10 |
This initial version doesn't enable their use by default. |
11 |
|
12 |
URL: https://bugs.gentoo.org/512794 |
13 |
Reported-by: Matthew Thode <prometheanfire <AT> gentoo.org> |
14 |
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org> |
15 |
|
16 |
configure.ac | 5 ++ |
17 |
etc/sandbox.conf | 20 +++++ |
18 |
headers.h | 12 +++ |
19 |
src/Makefile.am | 1 + |
20 |
src/namespaces.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
21 |
src/options.c | 71 ++++++++++++++++++ |
22 |
src/sandbox.c | 2 +- |
23 |
src/sandbox.h | 14 ++++ |
24 |
8 files changed, 343 insertions(+), 1 deletion(-) |
25 |
|
26 |
diff --git a/configure.ac b/configure.ac |
27 |
index 4c4cb20..843bb97 100644 |
28 |
--- a/configure.ac |
29 |
+++ b/configure.ac |
30 |
@@ -117,6 +117,7 @@ AC_CHECK_HEADERS_ONCE(m4_flatten([ |
31 |
memory.h |
32 |
pthread.h |
33 |
pwd.h |
34 |
+ sched.h |
35 |
siginfo.h |
36 |
signal.h |
37 |
sigsegv.h |
38 |
@@ -132,10 +133,13 @@ AC_CHECK_HEADERS_ONCE(m4_flatten([ |
39 |
unistd.h |
40 |
utime.h |
41 |
sys/file.h |
42 |
+ sys/ioctl.h |
43 |
sys/mman.h |
44 |
+ sys/mount.h |
45 |
sys/param.h |
46 |
sys/ptrace.h |
47 |
sys/reg.h |
48 |
+ sys/socket.h |
49 |
sys/stat.h |
50 |
sys/syscall.h |
51 |
sys/time.h |
52 |
@@ -225,6 +229,7 @@ AC_CHECK_FUNCS_ONCE(m4_flatten([ |
53 |
symlinkat |
54 |
truncate64 |
55 |
unlinkat |
56 |
+ unshare |
57 |
utime |
58 |
utimensat |
59 |
utimes |
60 |
|
61 |
diff --git a/etc/sandbox.conf b/etc/sandbox.conf |
62 |
index 1d7655c..5f09ee4 100644 |
63 |
--- a/etc/sandbox.conf |
64 |
+++ b/etc/sandbox.conf |
65 |
@@ -29,6 +29,26 @@ |
66 |
|
67 |
|
68 |
# |
69 |
+# Namespace Section (Linux-only) |
70 |
+# |
71 |
+ |
72 |
+# Global knob to control all namespaces. |
73 |
+#NAMESPACES_ENABLE="no" |
74 |
+ |
75 |
+# Knobs for different types of namespaces. If the runtime doesn't support a |
76 |
+# particular type, it will be automatically skipped. Default to off as these |
77 |
+# are currently experimental. |
78 |
+# For more details on each type, see the namespaces(7) manpage. |
79 |
+#NAMESPACE_IPC_ENABLE="no" |
80 |
+#NAMESPACE_MNT_ENABLE="no" |
81 |
+#NAMESPACE_NET_ENABLE="no" |
82 |
+#NAMESPACE_PID_ENABLE="no" |
83 |
+#NAMESPACE_SYSV_ENABLE="no" |
84 |
+#NAMESPACE_USER_ENABLE="no" |
85 |
+#NAMESPACE_UTS_ENABLE="no" |
86 |
+ |
87 |
+ |
88 |
+# |
89 |
# ACCESS Section |
90 |
# |
91 |
|
92 |
|
93 |
diff --git a/headers.h b/headers.h |
94 |
index 458958b..13e005a 100644 |
95 |
--- a/headers.h |
96 |
+++ b/headers.h |
97 |
@@ -53,6 +53,9 @@ |
98 |
#ifdef HAVE_PWD_H |
99 |
# include <pwd.h> |
100 |
#endif |
101 |
+#ifdef HAVE_SCHED_H |
102 |
+# include <sched.h> |
103 |
+#endif |
104 |
#ifdef HAVE_SIGINFO_H |
105 |
# include <siginfo.h> |
106 |
#endif |
107 |
@@ -96,11 +99,17 @@ |
108 |
#ifdef HAVE_SYS_FILE_H |
109 |
# include <sys/file.h> |
110 |
#endif |
111 |
+#ifdef HAVE_SYS_IOCTL_H |
112 |
+# include <sys/ioctl.h> |
113 |
+#endif |
114 |
#ifdef HAVE_SYS_MMAN_H |
115 |
# include <sys/mman.h> |
116 |
#else |
117 |
#error |
118 |
#endif |
119 |
+#ifdef HAVE_SYS_MOUNT_H |
120 |
+# include <sys/mount.h> |
121 |
+#endif |
122 |
#ifdef HAVE_SYS_PARAM_H |
123 |
# include <sys/param.h> |
124 |
#endif |
125 |
@@ -110,6 +119,9 @@ |
126 |
#ifdef HAVE_SYS_REG_H |
127 |
# include <sys/reg.h> |
128 |
#endif |
129 |
+#ifdef HAVE_SYS_SOCKET_H |
130 |
+# include <sys/socket.h> |
131 |
+#endif |
132 |
#ifdef HAVE_SYS_STAT_H |
133 |
# include <sys/stat.h> |
134 |
#endif |
135 |
|
136 |
diff --git a/src/Makefile.am b/src/Makefile.am |
137 |
index 24ffdcf..e7aeb30 100644 |
138 |
--- a/src/Makefile.am |
139 |
+++ b/src/Makefile.am |
140 |
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \ |
141 |
sandbox_LDADD = $(top_builddir)/libsbutil/libsbutil.la $(LIBDL) |
142 |
sandbox_SOURCES = \ |
143 |
environ.c \ |
144 |
+ namespaces.c \ |
145 |
options.c \ |
146 |
sandbox.h \ |
147 |
sandbox.c |
148 |
|
149 |
diff --git a/src/namespaces.c b/src/namespaces.c |
150 |
new file mode 100644 |
151 |
index 0000000..5be42f6 |
152 |
--- /dev/null |
153 |
+++ b/src/namespaces.c |
154 |
@@ -0,0 +1,219 @@ |
155 |
+/* |
156 |
+ * Initialize various namespaces |
157 |
+ * |
158 |
+ * Copyright 1999-2015 Gentoo Foundation |
159 |
+ * Licensed under the GPL-2 |
160 |
+ */ |
161 |
+ |
162 |
+#include "headers.h" |
163 |
+#include "sbutil.h" |
164 |
+#include "sandbox.h" |
165 |
+ |
166 |
+#ifdef __linux__ |
167 |
+ |
168 |
+#include <net/if.h> |
169 |
+ |
170 |
+#ifndef HAVE_UNSHARE |
171 |
+# ifdef __NR_unshare |
172 |
+# define unshare(x) syscall(__NR_unshare, x) |
173 |
+# else |
174 |
+# define unshare(x) -1 |
175 |
+# endif |
176 |
+#endif |
177 |
+ |
178 |
+#define xmount(...) sb_assert(mount(__VA_ARGS__) == 0) |
179 |
+#define xmkdir(...) sb_assert(mkdir(__VA_ARGS__) == 0) |
180 |
+#define xchmod(...) sb_assert(chmod(__VA_ARGS__) == 0) |
181 |
+#define xsymlink(...) sb_assert(symlink(__VA_ARGS__) == 0) |
182 |
+ |
183 |
+#define xasprintf(fmt, ...) \ |
184 |
+({ \ |
185 |
+ int _ret = asprintf(fmt, __VA_ARGS__); \ |
186 |
+ if (_ret == 0) \ |
187 |
+ sb_perr("asprintf(%s) failed", #fmt); \ |
188 |
+ _ret; \ |
189 |
+}) |
190 |
+#define xfopen(path, ...) \ |
191 |
+({ \ |
192 |
+ FILE *_ret = fopen(path, __VA_ARGS__); \ |
193 |
+ if (_ret == 0) \ |
194 |
+ sb_perr("fopen(%s) failed", #path); \ |
195 |
+ _ret; \ |
196 |
+}) |
197 |
+ |
198 |
+static void ns_user_switch(int uid, int gid, int nuid, int ngid) |
199 |
+{ |
200 |
+#ifdef CLONE_NEWUSER |
201 |
+ FILE *fp; |
202 |
+ char *map; |
203 |
+ |
204 |
+ if (uid == nuid || unshare(CLONE_NEWUSER)) |
205 |
+ return; |
206 |
+ |
207 |
+ fp = xfopen("/proc/self/uid_map", "we"); |
208 |
+ xasprintf(&map, "%i %i 1", nuid, uid); |
209 |
+ fputs(map, fp); |
210 |
+ fclose(fp); |
211 |
+ free(map); |
212 |
+ |
213 |
+ fp = xfopen("/proc/self/setgroups", "we"); |
214 |
+ fputs("deny", fp); |
215 |
+ fclose(fp); |
216 |
+ |
217 |
+ fp = xfopen("/proc/self/gid_map", "we"); |
218 |
+ xasprintf(&map, "%i %i 1\n", ngid, gid); |
219 |
+ fputs(map, fp); |
220 |
+ fclose(fp); |
221 |
+ free(map); |
222 |
+#endif |
223 |
+} |
224 |
+ |
225 |
+static void ns_net_setup(void) |
226 |
+{ |
227 |
+#ifdef CLONE_NEWNET |
228 |
+ if (unshare(CLONE_NEWNET)) |
229 |
+ return; |
230 |
+ |
231 |
+ int sock = socket(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0); |
232 |
+ struct ifreq ifr; |
233 |
+ |
234 |
+ strcpy(ifr.ifr_name, "lo"); |
235 |
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) |
236 |
+ sb_perr("ioctl(SIOCGIFFLAGS, lo) failed"); |
237 |
+ strcpy(ifr.ifr_name, "lo"); |
238 |
+ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; |
239 |
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) |
240 |
+ sb_perr("ioctl(SIOCSIFFLAGS, lo) failed"); |
241 |
+#endif |
242 |
+} |
243 |
+ |
244 |
+/* Create a nice empty /dev for playing in. */ |
245 |
+static void ns_mount_setup(void) |
246 |
+{ |
247 |
+#ifdef CLONE_NEWNS |
248 |
+ /* Create a new mount namespace. */ |
249 |
+ if (unshare(CLONE_NEWNS)) |
250 |
+ return; |
251 |
+ |
252 |
+ /* Mark the whole tree as private so we don't mess up the parent ns. */ |
253 |
+ if (mount("none", "/", NULL, MS_PRIVATE | MS_REC, NULL)) |
254 |
+ return; |
255 |
+ |
256 |
+ /* Create a unique /tmp dir for everyone. */ |
257 |
+ if (mount("/tmp", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_RELATIME, NULL)) |
258 |
+ sb_ewarn("could not mount /tmp"); |
259 |
+ |
260 |
+ /* Mount an empty dir inside of /dev which we'll populate with bind mounts |
261 |
+ * to the existing files in /dev. We can't just mknod ourselves because |
262 |
+ * the kernel will deny those calls when we aren't actually root. We pick |
263 |
+ * the /dev/shm dir as it should generally exist and we don't care about |
264 |
+ * binding its contents. */ |
265 |
+ if (mount("sandbox-dev", "/dev/shm", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_RELATIME, "mode=0755")) |
266 |
+ return; |
267 |
+ |
268 |
+ /* Now map in all the files/dirs we do want to expose. */ |
269 |
+ int fd; |
270 |
+#define bind_file(node) \ |
271 |
+ fd = open("/dev/shm/" node, O_CREAT, 0); \ |
272 |
+ sb_assert(fd != -1); \ |
273 |
+ close(fd); \ |
274 |
+ xmount("/dev/" node, "/dev/shm/" node, NULL, MS_BIND, NULL) |
275 |
+#define bind_dir(node) \ |
276 |
+ xmkdir("/dev/shm/" node, 0); \ |
277 |
+ xmount("/dev/" node, "/dev/shm/" node, NULL, MS_BIND, NULL) |
278 |
+ |
279 |
+ bind_file("full"); |
280 |
+ bind_file("null"); |
281 |
+ bind_file("ptmx"); |
282 |
+ bind_file("tty"); |
283 |
+ bind_file("urandom"); |
284 |
+ bind_file("zero"); |
285 |
+ bind_dir("pts"); |
286 |
+ |
287 |
+ xmkdir("/dev/shm/shm", 01777); |
288 |
+ xchmod("/dev/shm/shm", 01777); |
289 |
+ |
290 |
+ xsymlink("/proc/self/fd", "/dev/shm/fd"); |
291 |
+ xsymlink("fd/0", "/dev/shm/stdin"); |
292 |
+ xsymlink("fd/1", "/dev/shm/stdout"); |
293 |
+ xsymlink("fd/2", "/dev/shm/stderr"); |
294 |
+ |
295 |
+ xchmod("/dev/shm", 0555); |
296 |
+ |
297 |
+ /* Now that the new root looks good, move it to /dev. */ |
298 |
+ xmount("/dev/shm", "/dev", NULL, MS_MOVE, NULL); |
299 |
+#endif |
300 |
+} |
301 |
+ |
302 |
+static pid_t ns_pid_setup(void) |
303 |
+{ |
304 |
+ pid_t pid; |
305 |
+ |
306 |
+ if (unshare(CLONE_NEWPID) == 0) { |
307 |
+ /* Create a child in the new pid ns. */ |
308 |
+ pid = fork(); |
309 |
+ if (pid == 0) { |
310 |
+ /* Create a new mount namespace for the child. */ |
311 |
+ sb_assert(unshare(CLONE_NEWNS) == 0); |
312 |
+ xmount("none", "/proc", NULL, MS_PRIVATE | MS_REC, NULL); |
313 |
+ xmount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, NULL); |
314 |
+ } |
315 |
+ } else { |
316 |
+ /* At least hide other procs. */ |
317 |
+ if (umount2("/proc", MNT_FORCE | MNT_DETACH) == 0) |
318 |
+ xmount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, "hidepid=2"); |
319 |
+ pid = fork(); |
320 |
+ } |
321 |
+ |
322 |
+ return pid; |
323 |
+} |
324 |
+ |
325 |
+pid_t setup_namespaces(void) |
326 |
+{ |
327 |
+ /* We need to unshare namespaces independently anyways as users can |
328 |
+ * configure kernels to have only some enabled, and if we try to do |
329 |
+ * them all at once, we'll get EINVAL. */ |
330 |
+ |
331 |
+ int uid = getuid(); |
332 |
+ int gid = getgid(); |
333 |
+ pid_t pid; |
334 |
+ |
335 |
+ /* This comes first so we can do the others as non-root. */ |
336 |
+ if (opt_use_ns_user) |
337 |
+ ns_user_switch(uid, gid, 0, 0); |
338 |
+ |
339 |
+#ifdef CLONE_NEWIPC |
340 |
+ if (opt_use_ns_ipc) |
341 |
+ unshare(CLONE_NEWIPC); |
342 |
+#endif |
343 |
+#ifdef CLONE_SYSVSEM |
344 |
+ if (opt_use_ns_sysv) |
345 |
+ unshare(CLONE_SYSVSEM); |
346 |
+#endif |
347 |
+ |
348 |
+#ifdef CLONE_NEWUTS |
349 |
+ if (opt_use_ns_uts && unshare(CLONE_NEWUTS) == 0) { |
350 |
+ const char name[] = "gentoo-sandbox"; |
351 |
+ if (sethostname(name, sizeof(name) - 1)) |
352 |
+ /* silence gcc warning */; |
353 |
+ } |
354 |
+#endif |
355 |
+ |
356 |
+ if (opt_use_ns_net) |
357 |
+ ns_net_setup(); |
358 |
+ |
359 |
+ if (opt_use_ns_mnt) |
360 |
+ ns_mount_setup(); |
361 |
+ |
362 |
+ if (opt_use_ns_mnt && opt_use_ns_pid) |
363 |
+ pid = ns_pid_setup(); |
364 |
+ else |
365 |
+ pid = fork(); |
366 |
+ |
367 |
+ if (opt_use_ns_user) |
368 |
+ ns_user_switch(0, 0, uid, gid); |
369 |
+ |
370 |
+ return pid; |
371 |
+} |
372 |
+ |
373 |
+#endif |
374 |
|
375 |
diff --git a/src/options.c b/src/options.c |
376 |
index 10f937c..295ee75 100644 |
377 |
--- a/src/options.c |
378 |
+++ b/src/options.c |
379 |
@@ -9,6 +9,43 @@ |
380 |
#include "sbutil.h" |
381 |
#include "sandbox.h" |
382 |
|
383 |
+/* Setting to -1 will load defaults from the config file. */ |
384 |
+int opt_use_namespaces = -1; |
385 |
+int opt_use_ns_ipc = -1; |
386 |
+int opt_use_ns_mnt = -1; |
387 |
+int opt_use_ns_net = -1; |
388 |
+int opt_use_ns_pid = -1; |
389 |
+int opt_use_ns_sysv = -1; |
390 |
+int opt_use_ns_user = -1; |
391 |
+int opt_use_ns_uts = -1; |
392 |
+ |
393 |
+static const struct { |
394 |
+ const char *name; |
395 |
+ int *opt; |
396 |
+ int default_val; |
397 |
+} config_opts[] = { |
398 |
+ /* Default these to off until they can get more testing. */ |
399 |
+ { "NAMESPACES_ENABLE", &opt_use_namespaces, false, }, |
400 |
+ { "NAMESPACE_IPC_ENABLE", &opt_use_ns_ipc, false, }, |
401 |
+ { "NAMESPACE_MNT_ENABLE", &opt_use_ns_mnt, false, }, |
402 |
+ { "NAMESPACE_NET_ENABLE", &opt_use_ns_net, false, }, |
403 |
+ { "NAMESPACE_PID_ENABLE", &opt_use_ns_pid, false, }, |
404 |
+ { "NAMESPACE_SYSV_ENABLE", &opt_use_ns_sysv, false, }, |
405 |
+ { "NAMESPACE_USER_ENABLE", &opt_use_ns_user, false, }, |
406 |
+ { "NAMESPACE_UTS_ENABLE", &opt_use_ns_uts, false, }, |
407 |
+}; |
408 |
+ |
409 |
+static void read_config(void) |
410 |
+{ |
411 |
+ size_t i; |
412 |
+ |
413 |
+ for (i = 0; i < ARRAY_SIZE(config_opts); ++i) { |
414 |
+ int *opt = config_opts[i].opt; |
415 |
+ if (*opt == -1) |
416 |
+ *opt = sb_get_cnf_bool(config_opts[i].name, config_opts[i].default_val); |
417 |
+ } |
418 |
+} |
419 |
+ |
420 |
static void show_version(void) |
421 |
{ |
422 |
puts( |
423 |
@@ -36,11 +73,43 @@ static void show_version(void) |
424 |
#define PARSE_FLAGS "+hV" |
425 |
#define a_argument required_argument |
426 |
static struct option const long_opts[] = { |
427 |
+ {"ns-on", no_argument, &opt_use_namespaces, true}, |
428 |
+ {"ns-off", no_argument, &opt_use_namespaces, false}, |
429 |
+ {"ns-ipc-on", no_argument, &opt_use_ns_ipc, true}, |
430 |
+ {"ns-ipc-off", no_argument, &opt_use_ns_ipc, false}, |
431 |
+ {"ns-mnt-on", no_argument, &opt_use_ns_mnt, true}, |
432 |
+ {"ns-mnt-off", no_argument, &opt_use_ns_mnt, false}, |
433 |
+ {"ns-net-on", no_argument, &opt_use_ns_net, true}, |
434 |
+ {"ns-net-off", no_argument, &opt_use_ns_net, false}, |
435 |
+ {"ns-pid-on", no_argument, &opt_use_ns_pid, true}, |
436 |
+ {"ns-pid-off", no_argument, &opt_use_ns_pid, false}, |
437 |
+ {"ns-sysv-on", no_argument, &opt_use_ns_sysv, true}, |
438 |
+ {"ns-sysv-off", no_argument, &opt_use_ns_sysv, false}, |
439 |
+ {"ns-user-on", no_argument, &opt_use_ns_user, true}, |
440 |
+ {"ns-user-off", no_argument, &opt_use_ns_user, false}, |
441 |
+ {"ns-uts-on", no_argument, &opt_use_ns_uts, true}, |
442 |
+ {"ns-uts-off", no_argument, &opt_use_ns_uts, false}, |
443 |
{"help", no_argument, NULL, 'h'}, |
444 |
{"version", no_argument, NULL, 'V'}, |
445 |
{NULL, no_argument, NULL, 0x0} |
446 |
}; |
447 |
static const char * const opts_help[] = { |
448 |
+ "Enable the use of namespaces", |
449 |
+ "Disable the use of namespaces", |
450 |
+ "Enable the use of IPC (and System V) namespaces", |
451 |
+ "Disable the use of IPC (and System V) namespaces", |
452 |
+ "Enable the use of mount namespaces", |
453 |
+ "Disable the use of mount namespaces", |
454 |
+ "Enable the use of network namespaces", |
455 |
+ "Disable the use of network namespaces", |
456 |
+ "Enable the use of process (pid) namespaces", |
457 |
+ "Disable the use of process (pid) namespaces", |
458 |
+ "Enable the use of System V namespaces", |
459 |
+ "Disable the use of System V namespaces", |
460 |
+ "Enable the use of user namespaces", |
461 |
+ "Disable the use of user namespaces", |
462 |
+ "Enable the use of UTS (hostname/uname) namespaces", |
463 |
+ "Disable the use of UTS (hostname/uname) namespaces", |
464 |
"Print this help and exit", |
465 |
"Print version and exit", |
466 |
NULL |
467 |
@@ -113,4 +182,6 @@ void parseargs(int argc, char *argv[]) |
468 |
show_usage(1); |
469 |
} |
470 |
} |
471 |
+ |
472 |
+ read_config(); |
473 |
} |
474 |
|
475 |
diff --git a/src/sandbox.c b/src/sandbox.c |
476 |
index 15c87b2..c668ab6 100644 |
477 |
--- a/src/sandbox.c |
478 |
+++ b/src/sandbox.c |
479 |
@@ -160,7 +160,7 @@ static int spawn_shell(char *argv_bash[], char **env, int debug) |
480 |
int status = 0; |
481 |
int ret = 0; |
482 |
|
483 |
- child_pid = fork(); |
484 |
+ child_pid = opt_use_namespaces ? setup_namespaces() : fork(); |
485 |
|
486 |
/* Child's process */ |
487 |
if (0 == child_pid) { |
488 |
|
489 |
diff --git a/src/sandbox.h b/src/sandbox.h |
490 |
index 4233bd6..303dac4 100644 |
491 |
--- a/src/sandbox.h |
492 |
+++ b/src/sandbox.h |
493 |
@@ -28,6 +28,12 @@ extern char **setup_environ(struct sandbox_info_t *sandbox_info); |
494 |
|
495 |
extern bool sb_get_cnf_bool(const char *, bool); |
496 |
|
497 |
+#ifdef __linux__ |
498 |
+extern pid_t setup_namespaces(void); |
499 |
+#else |
500 |
+#define setup_namespaces() fork() |
501 |
+#endif |
502 |
+ |
503 |
#define sb_warn(fmt, args...) fprintf(stderr, "%s:%s " fmt "\n", "sandbox", __func__, ## args) |
504 |
#define sb_pwarn(fmt, args...) sb_warn(fmt ": %s\n", ## args, strerror(errno)) |
505 |
#define _sb_err(func, fmt, args...) do { sb_##func(fmt, ## args); exit(EXIT_FAILURE); } while (0) |
506 |
@@ -36,5 +42,13 @@ extern bool sb_get_cnf_bool(const char *, bool); |
507 |
|
508 |
/* Option parsing related code */ |
509 |
extern void parseargs(int argc, char *argv[]); |
510 |
+extern int opt_use_namespaces; |
511 |
+extern int opt_use_ns_ipc; |
512 |
+extern int opt_use_ns_mnt; |
513 |
+extern int opt_use_ns_net; |
514 |
+extern int opt_use_ns_pid; |
515 |
+extern int opt_use_ns_sysv; |
516 |
+extern int opt_use_ns_user; |
517 |
+extern int opt_use_ns_uts; |
518 |
|
519 |
#endif |