1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2014 Red Hat, Inc.
4 * Copyright (C) 2022 SUSE LLC Andrea Cervesato <[email protected]>
5 */
6
7 /*\
8 * [Description]
9 *
10 * Test SysV IPC message passing through different processes.
11 *
12 * [Algorithm]
13 *
14 * 1. Clones two child processes with CLONE_NEWIPC flag, each child
15 * gets System V message queue (msg) with the _identical_ key.
16 * 2. Child1 appends a message with identifier #1 to the message queue.
17 * 3. Child2 appends a message with identifier #2 to the message queue.
18 * 4. Appends to the message queue with the identical key but from
19 * two different IPC namespaces should not interfere with each other
20 * and so child1 checks whether its message queue doesn't contain
21 * a message with identifier #2, if it doesn't test passes, otherwise
22 * test fails.
23 */
24
25 #define _GNU_SOURCE
26
27 #include <sys/wait.h>
28 #include <sys/msg.h>
29 #include <sys/types.h>
30 #include "tst_safe_sysv_ipc.h"
31 #include "tst_test.h"
32 #include "common.h"
33
34 #define TESTKEY 124426L
35
36 struct sysv_msg {
37 long mtype;
38 char mtext[1];
39 };
40
chld1_msg(void)41 static void chld1_msg(void)
42 {
43 int id;
44 struct sysv_msg m = {
45 .mtype = 1,
46 .mtext = "A",
47 };
48 struct sysv_msg rec;
49
50 id = SAFE_MSGGET(TESTKEY, IPC_CREAT | 0600);
51
52 SAFE_MSGSND(id, &m, sizeof(m.mtext), 0);
53
54 TST_CHECKPOINT_WAIT(0);
55
56 TEST(msgrcv(id, &rec, sizeof(rec.mtext), 2, IPC_NOWAIT));
57 if (TST_RET < 0 && TST_ERR != ENOMSG)
58 tst_brk(TBROK | TERRNO, "msgrcv error");
59
60 /* if child1 message queue has changed (by child2) report fail */
61 if (TST_RET > 0)
62 tst_res(TFAIL, "messages leak between namespacess");
63 else
64 tst_res(TPASS, "messages does not leak between namespaces");
65
66 TST_CHECKPOINT_WAKE(0);
67
68 SAFE_MSGCTL(id, IPC_RMID, NULL);
69 }
70
chld2_msg(void)71 static void chld2_msg(void)
72 {
73 int id;
74 struct sysv_msg m = {
75 .mtype = 2,
76 .mtext = "B",
77 };
78
79 id = SAFE_MSGGET(TESTKEY, IPC_CREAT | 0600);
80
81 SAFE_MSGSND(id, &m, sizeof(m.mtext), 0);
82
83 TST_CHECKPOINT_WAKE_AND_WAIT(0);
84
85 SAFE_MSGCTL(id, IPC_RMID, NULL);
86 }
87
run(void)88 static void run(void)
89 {
90 clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_msg);
91 clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_msg);
92 }
93
94 static struct tst_test test = {
95 .test_all = run,
96 .needs_root = 1,
97 .needs_checkpoints = 1,
98 .forks_child = 1,
99 };
100