1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) International Business Machines Corp., 2009
4 * Copyright (c) Nadia Derbey, 2009 <Nadia.Derbey@bull.net>
5 * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
6 */
7
8/*\
9 * [Description]
10 *
11 * Create a mqueue with the same name in both parent and isolated/forked child,
12 * then check namespace isolation.
13 */
14
15#include "tst_test.h"
16#include "lapi/sched.h"
17#include "tst_safe_posix_ipc.h"
18
19#define MQNAME "/MQ1"
20
21static mqd_t mqd;
22static char *str_op;
23
24static int create_message_queue(void)
25{
26	return mq_open(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
27}
28
29static void shared_child(void)
30{
31	mqd_t mqd1 = -1;
32
33	TST_EXP_FAIL(mqd1 = create_message_queue(), EEXIST);
34
35	if (mqd1 != -1) {
36		SAFE_MQ_CLOSE(mqd1);
37		SAFE_MQ_UNLINK(MQNAME);
38	}
39}
40
41static void isolated_child(void)
42{
43	mqd_t mqd1 = -1;
44
45	TST_EXP_POSITIVE(mqd1 = create_message_queue());
46
47	if (mqd1 != -1) {
48		SAFE_MQ_CLOSE(mqd1);
49		SAFE_MQ_UNLINK(MQNAME);
50	}
51}
52
53static void run(void)
54{
55	const struct tst_clone_args clone_args = {
56		.flags = CLONE_NEWIPC,
57		.exit_signal = SIGCHLD,
58	};
59
60	tst_res(TINFO, "Checking namespaces isolation from parent to child");
61
62	if (str_op && !strcmp(str_op, "clone")) {
63		tst_res(TINFO, "Spawning isolated process");
64
65		if (!SAFE_CLONE(&clone_args)) {
66			isolated_child();
67			return;
68		}
69	} else if (str_op && !strcmp(str_op, "unshare")) {
70		tst_res(TINFO, "Spawning unshared process");
71
72		if (!SAFE_FORK()) {
73			SAFE_UNSHARE(CLONE_NEWIPC);
74			isolated_child();
75			return;
76		}
77	} else {
78		tst_res(TINFO, "Spawning plain process");
79
80		if (!SAFE_FORK()) {
81			shared_child();
82			return;
83		}
84	}
85}
86
87static void setup(void)
88{
89	mqd = SAFE_MQ_OPEN(MQNAME, O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
90}
91
92static void cleanup(void)
93{
94	if (mqd != -1) {
95		SAFE_MQ_CLOSE(mqd);
96		SAFE_MQ_UNLINK(MQNAME);
97	}
98}
99
100static struct tst_test test = {
101	.test_all = run,
102	.setup = setup,
103	.cleanup = cleanup,
104	.needs_root = 1,
105	.forks_child = 1,
106	.options = (struct tst_option[]) {
107		{ "m:", &str_op, "Child process isolation <clone|unshare>" },
108		{},
109	},
110	.needs_kconfigs = (const char *[]) {
111		"CONFIG_USER_NS",
112		NULL
113	},
114};
115