2 * Copyright (C) 2019 Michael Jeanson <mjeanson@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by the
6 * Free Software Foundation; version 2.1 of the License.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <sys/types.h>
32 #include <common/compat/tid.h>
35 #include "signal-helper.h"
37 #define LTTNG_PROC_NS_PATH_MAX 40
40 static char *ns_opt
= NULL
;
41 static char *before_unshare_wait_file_path
= NULL
;
42 static char *after_unshare_wait_file_path
= NULL
;
43 static char *after_unshare_signal_file_path
= NULL
;
46 struct poptOption opts
[] = {
47 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
48 { "debug", 'd', POPT_ARG_NONE
, &debug
, 0, "Enable debug output", NULL
},
49 { "ns", 'n', POPT_ARG_STRING
, &ns_opt
, 0, "Namespace short identifier", NULL
},
50 { "before", 'b', POPT_ARG_STRING
, &before_unshare_wait_file_path
, 0, "Wait for file before unshare", NULL
},
51 { "after", 'a', POPT_ARG_STRING
, &after_unshare_wait_file_path
, 0, "Wait for file after unshare", NULL
},
52 { "signal", 's', POPT_ARG_STRING
, &after_unshare_signal_file_path
, 0, "Create signal file after unshare", NULL
},
54 { NULL
, 0, 0, NULL
, 0 }
58 void debug_printf(const char *format
, ...) {
60 va_start(args
, format
);
63 vfprintf(stderr
, format
, args
);
69 ino_t
get_ns_inum(char ns
[]) {
71 char proc_ns_path
[LTTNG_PROC_NS_PATH_MAX
];
74 * /proc/thread-self was introduced in kernel v3.17
76 if (snprintf(proc_ns_path
, LTTNG_PROC_NS_PATH_MAX
,
77 "/proc/thread-self/ns/%s", ns
) >= 0) {
78 if (stat(proc_ns_path
, &sb
) == 0) {
83 if (snprintf(proc_ns_path
, LTTNG_PROC_NS_PATH_MAX
,
84 "/proc/self/task/%d/%s/net",
87 if (stat(proc_ns_path
, &sb
) == 0) {
96 int do_the_needful(int ns_flag
, char ns_str
[]) {
100 ns1
= get_ns_inum(ns_str
);
101 debug_printf("Initial %s ns inode number: %lu\n", ns_str
, ns1
);
104 * Wait on synchronization before unshare
106 if (before_unshare_wait_file_path
) {
107 ret
= wait_on_file(before_unshare_wait_file_path
);
113 ret
= unshare(ns_flag
);
120 ns2
= get_ns_inum(ns_str
);
121 debug_printf("Post unshare %s ns inode number: %lu\n", ns_str
, ns2
);
124 * Signal that the unshare call is completed.
126 if (after_unshare_signal_file_path
) {
127 ret
= create_file(after_unshare_signal_file_path
);
135 * Wait on synchronization after unshare
137 if (after_unshare_wait_file_path
) {
138 ret
= wait_on_file(after_unshare_wait_file_path
);
148 int main(int argc
, const char **argv
) {
150 int ret
= EXIT_SUCCESS
;
153 pc
= poptGetContext(NULL
, argc
, argv
, opts
, 0);
154 poptReadDefaultConfig(pc
, 0);
157 poptPrintHelp(pc
, stderr
, 0);
162 while ((opt
= poptGetNextOpt(pc
)) >= 0) {
165 poptPrintUsage(pc
, stderr
, 0);
172 /* an error occurred during option processing */
173 poptPrintUsage(pc
, stderr
, 0);
174 fprintf(stderr
, "%s: %s\n",
175 poptBadOption(pc
, POPT_BADOPTION_NOALIAS
),
181 if (ns_opt
== NULL
) {
182 poptPrintUsage(pc
, stderr
, 0);
187 if (set_signal_handler()) {
192 if (strncmp(ns_opt
, "cgroup", 3) == 0) {
193 do_the_needful(CLONE_NEWCGROUP
, "cgroup");
194 } else if (strncmp(ns_opt
, "ipc", 3) == 0) {
195 do_the_needful(CLONE_NEWIPC
, "ipc");
196 } else if (strncmp(ns_opt
, "mnt", 3) == 0) {
197 do_the_needful(CLONE_NEWNS
, "mnt");
198 } else if (strncmp(ns_opt
, "net", 3) == 0) {
199 do_the_needful(CLONE_NEWNET
, "net");
200 } else if (strncmp(ns_opt
, "pid", 3) == 0) {
201 do_the_needful(CLONE_NEWPID
, "pid");
202 } else if (strncmp(ns_opt
, "user", 3) == 0) {
203 // Will always fail, requires a single threaded application, which can't happen with UST.
204 do_the_needful(CLONE_NEWUSER
, "user");
205 } else if (strncmp(ns_opt
, "uts", 3) == 0) {
206 do_the_needful(CLONE_NEWUTS
, "uts");
208 printf("invalid ns id\n");