]> git.proxmox.com Git - mirror_lxc.git/blame - src/tests/share_ns.c
file_utils: handle libcs without fmemopen()
[mirror_lxc.git] / src / tests / share_ns.c
CommitLineData
7acb5ce3
CB
1/* liblxcapi
2 *
3 * Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#include <alloca.h>
20#include <errno.h>
21#include <pthread.h>
22#include <sched.h>
23#include <signal.h>
24#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/reboot.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30
31#include "lxc/lxccontainer.h"
32#include "lxctest.h"
1b9aca11 33#include "../lxc/compiler.h"
7acb5ce3
CB
34
35struct thread_args {
36 int thread_id;
37 bool success;
38 pid_t init_pid;
dab55f77
CB
39 char inherited_ipc_ns[4096];
40 char inherited_net_ns[4096];
7acb5ce3
CB
41};
42
1b9aca11 43__noreturn void *ns_sharing_wrapper(void *data)
7acb5ce3
CB
44{
45 int init_pid;
46 ssize_t ret;
47 char name[100];
48 char owning_ns_init_pid[100];
dab55f77
CB
49 char proc_ns_path[256];
50 char ns_buf[256];
7acb5ce3
CB
51 struct lxc_container *c;
52 struct thread_args *args = data;
53
54 lxc_debug("Starting namespace sharing thread %d\n", args->thread_id);
55
56 sprintf(name, "share-ns-%d", args->thread_id);
57 c = lxc_container_new(name, NULL);
58 if (!c) {
59 lxc_error("Failed to create container \"%s\"\n", name);
1b9aca11 60 goto out_pthread_exit;
7acb5ce3
CB
61 }
62
63 if (c->is_defined(c)) {
64 lxc_error("Container \"%s\" is defined\n", name);
65 goto out;
66 }
67
68 if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) {
69 lxc_error("Failed to create busybox container \"%s\"\n", name);
70 goto out;
71 }
72
73 if (!c->is_defined(c)) {
74 lxc_error("Container \"%s\" is not defined\n", name);
75 goto out;
76 }
77
78 if (!c->load_config(c, NULL)) {
79 lxc_error("Failed to load config for container \"%s\"\n", name);
80 goto out;
81 }
82
83 /* share ipc namespace by container name */
b074bbf1
CB
84 if (!c->set_config_item(c, "lxc.namespace.share.ipc", "owning-ns")) {
85 lxc_error("Failed to set \"lxc.namespace.share.ipc=owning-ns\" for container \"%s\"\n", name);
7acb5ce3
CB
86 goto out;
87 }
88
89 /* clear all network configuration */
90 if (!c->set_config_item(c, "lxc.net", "")) {
b074bbf1 91 lxc_error("Failed to set \"lxc.namespace.share.ipc=owning-ns\" for container \"%s\"\n", name);
7acb5ce3
CB
92 goto out;
93 }
94
95 if (!c->set_config_item(c, "lxc.net.0.type", "empty")) {
96 lxc_error("Failed to set \"lxc.net.0.type=empty\" for container \"%s\"\n", name);
97 goto out;
98 }
99
100 sprintf(owning_ns_init_pid, "%d", args->init_pid);
101 /* share net namespace by pid */
b074bbf1
CB
102 if (!c->set_config_item(c, "lxc.namespace.share.net", owning_ns_init_pid)) {
103 lxc_error("Failed to set \"lxc.namespace.share.net=%s\" for container \"%s\"\n", owning_ns_init_pid, name);
7acb5ce3
CB
104 goto out;
105 }
106
107 if (!c->want_daemonize(c, true)) {
108 lxc_error("Failed to mark container \"%s\" daemonized\n", name);
109 goto out;
110 }
111
112 if (!c->startl(c, 0, NULL)) {
113 lxc_error("Failed to start container \"%s\" daemonized\n", name);
114 goto out;
115 }
116
117 init_pid = c->init_pid(c);
118 if (init_pid < 0) {
119 lxc_error("Failed to retrieve init pid of container \"%s\"\n", name);
120 goto out;
121 }
122
123 /* Check whether we correctly inherited the ipc namespace. */
124 ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/ipc", init_pid);
125 if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) {
126 lxc_error("Failed to create string for container \"%s\"\n", name);
127 goto out;
128 }
129
130 ret = readlink(proc_ns_path, ns_buf, sizeof(ns_buf));
131 if (ret < 0 || (size_t)ret >= sizeof(ns_buf)) {
132 lxc_error("Failed to retrieve ipc namespace for container \"%s\"\n", name);
133 goto out;
134 }
135 ns_buf[ret] = '\0';
136
137 if (strcmp(args->inherited_ipc_ns, ns_buf) != 0) {
138 lxc_error("Failed to inherit ipc namespace from container \"owning-ns\": %s != %s\n", args->inherited_ipc_ns, ns_buf);
139 goto out;
140 }
141 lxc_debug("Inherited ipc namespace from container \"owning-ns\": %s == %s\n", args->inherited_ipc_ns, ns_buf);
142
143 /* Check whether we correctly inherited the net namespace. */
144 ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/net", init_pid);
145 if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) {
146 lxc_error("Failed to create string for container \"%s\"\n", name);
147 goto out;
148 }
149
150 ret = readlink(proc_ns_path, ns_buf, sizeof(ns_buf));
151 if (ret < 0 || (size_t)ret >= sizeof(ns_buf)) {
152 lxc_error("Failed to retrieve ipc namespace for container \"%s\"\n", name);
153 goto out;
154 }
155 ns_buf[ret] = '\0';
156
157 if (strcmp(args->inherited_net_ns, ns_buf) != 0) {
158 lxc_error("Failed to inherit net namespace from container \"owning-ns\": %s != %s\n", args->inherited_net_ns, ns_buf);
159 goto out;
160 }
161 lxc_debug("Inherited net namespace from container \"owning-ns\": %s == %s\n", args->inherited_net_ns, ns_buf);
162
163 args->success = true;
164
165out:
dab55f77 166 if (c->is_running(c) && !c->stop(c))
7acb5ce3 167 lxc_error("Failed to stop container \"%s\"\n", name);
7acb5ce3 168
dab55f77 169 if (!c->destroy(c))
7acb5ce3 170 lxc_error("Failed to destroy container \"%s\"\n", name);
7acb5ce3 171
1b9aca11 172out_pthread_exit:
7acb5ce3 173 pthread_exit(NULL);
7acb5ce3
CB
174}
175
176int main(int argc, char *argv[])
177{
dab55f77
CB
178 struct thread_args *args = NULL;
179 size_t nthreads = 10;
7acb5ce3
CB
180 int i, init_pid, j;
181 char proc_ns_path[4096];
182 char ipc_ns_buf[4096];
183 char net_ns_buf[4096];
184 pthread_attr_t attr;
185 pthread_t threads[10];
7acb5ce3
CB
186 struct lxc_container *c;
187 int ret = EXIT_FAILURE;
188
dab55f77
CB
189 pthread_attr_init(&attr);
190
7acb5ce3
CB
191 c = lxc_container_new("owning-ns", NULL);
192 if (!c) {
193 lxc_error("%s", "Failed to create container \"owning-ns\"");
194 exit(ret);
195 }
196
197 if (c->is_defined(c)) {
198 lxc_error("%s\n", "Container \"owning-ns\" is defined");
199 goto on_error_put;
200 }
201
202 if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) {
203 lxc_error("%s\n", "Failed to create busybox container \"owning-ns\"");
204 goto on_error_put;
205 }
206
207 if (!c->is_defined(c)) {
208 lxc_error("%s\n", "Container \"owning-ns\" is not defined");
209 goto on_error_put;
210 }
211
212 c->clear_config(c);
213
214 if (!c->load_config(c, NULL)) {
215 lxc_error("%s\n", "Failed to load config for container \"owning-ns\"");
216 goto on_error_stop;
217 }
218
219 if (!c->want_daemonize(c, true)) {
220 lxc_error("%s\n", "Failed to mark container \"owning-ns\" daemonized");
221 goto on_error_stop;
222 }
223
224 if (!c->startl(c, 0, NULL)) {
225 lxc_error("%s\n", "Failed to start container \"owning-ns\" daemonized");
226 goto on_error_stop;
227 }
228
229 init_pid = c->init_pid(c);
230 if (init_pid < 0) {
231 lxc_error("%s\n", "Failed to retrieve init pid of container \"owning-ns\"");
232 goto on_error_stop;
233 }
234
235 /* record our ipc namespace */
236 ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/ipc", init_pid);
237 if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) {
238 lxc_error("%s\n", "Failed to create string for container \"owning-ns\"");
239 goto on_error_stop;
240 }
241
242 ret = readlink(proc_ns_path, ipc_ns_buf, sizeof(ipc_ns_buf));
243 if (ret < 0 || (size_t)ret >= sizeof(ipc_ns_buf)) {
244 lxc_error("%s\n", "Failed to retrieve ipc namespace for container \"owning-ns\"");
245 goto on_error_stop;
246
247 }
248 ipc_ns_buf[ret] = '\0';
249
250 /* record our net namespace */
251 ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/net", init_pid);
252 if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) {
253 lxc_error("%s\n", "Failed to create string for container \"owning-ns\"");
254 goto on_error_stop;
255 }
256
257 ret = readlink(proc_ns_path, net_ns_buf, sizeof(net_ns_buf));
258 if (ret < 0 || (size_t)ret >= sizeof(net_ns_buf)) {
259 lxc_error("%s\n", "Failed to retrieve ipc namespace for container \"owning-ns\"");
260 goto on_error_stop;
261 }
262 net_ns_buf[ret] = '\0';
263
264 sleep(5);
265
dab55f77
CB
266 args = malloc(sizeof(struct thread_args) * nthreads);
267 if (!args) {
268 lxc_error("%s\n", "Failed to allocate memory");
269 goto on_error_stop;
270 }
7acb5ce3
CB
271
272 for (j = 0; j < 10; j++) {
273 lxc_debug("Starting namespace sharing test iteration %d\n", j);
274
dab55f77 275 for (i = 0; i < nthreads; i++) {
7acb5ce3
CB
276 args[i].thread_id = i;
277 args[i].success = false;
278 args[i].init_pid = init_pid;
dab55f77
CB
279 memcpy(args[i].inherited_ipc_ns, ipc_ns_buf, sizeof(args[i].inherited_ipc_ns));
280 memcpy(args[i].inherited_net_ns, net_ns_buf, sizeof(args[i].inherited_net_ns));
7acb5ce3 281
dab55f77 282 ret = pthread_create(&threads[i], &attr, ns_sharing_wrapper, (void *)&args[i]);
7acb5ce3
CB
283 if (ret != 0)
284 goto on_error_stop;
285 }
286
dab55f77 287 for (i = 0; i < nthreads; i++) {
7acb5ce3
CB
288 ret = pthread_join(threads[i], NULL);
289 if (ret != 0)
290 goto on_error_stop;
291
292 if (!args[i].success) {
293 lxc_error("ns sharing thread %d failed\n", args[i].thread_id);
294 goto on_error_stop;
295 }
296 }
297 }
298
299 ret = EXIT_SUCCESS;
300
301on_error_stop:
dab55f77
CB
302 free(args);
303 pthread_attr_destroy(&attr);
304
7acb5ce3
CB
305 if (c->is_running(c) && !c->stop(c))
306 lxc_error("%s\n", "Failed to stop container \"owning-ns\"");
307
308 if (!c->destroy(c))
309 lxc_error("%s\n", "Failed to destroy container \"owning-ns\"");
310
311on_error_put:
312 lxc_container_put(c);
313 if (ret == EXIT_SUCCESS)
314 lxc_debug("%s\n", "All state namespace sharing tests passed");
dab55f77 315
7acb5ce3
CB
316 exit(ret);
317}