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 semaphore usage between cloned processes.
11 *
12 * [Algorithm]
13 *
14 * 1. Clones two child processes with CLONE_NEWIPC flag, each child
15 * creates System V semaphore (sem) with the _identical_ key.
16 * 2. Child1 locks the semaphore.
17 * 3. Child2 locks the semaphore.
18 * 4. Locking the semaphore with the identical key but from two different
19 * IPC namespaces should not interfere with each other, so if child2
20 * is able to lock the semaphore (after child1 locked it), test passes,
21 * otherwise test fails.
22 */
23
24 #define _GNU_SOURCE
25
26 #include <sys/wait.h>
27 #include <sys/msg.h>
28 #include <sys/types.h>
29 #include "tst_safe_sysv_ipc.h"
30 #include "tst_test.h"
31 #include "lapi/sem.h"
32 #include "common.h"
33
34 #define TESTKEY 124426L
35
chld1_sem(void)36 static void chld1_sem(void)
37 {
38 int id;
39 struct sembuf sm = {
40 .sem_num = 0,
41 .sem_op = -1,
42 .sem_flg = IPC_NOWAIT,
43 };
44 union semun su = {
45 .val = 1,
46 };
47
48 id = SAFE_SEMGET(TESTKEY, 1, IPC_CREAT);
49
50 SAFE_SEMCTL(id, 0, SETVAL, su);
51
52 TST_CHECKPOINT_WAKE_AND_WAIT(0);
53
54 SAFE_SEMOP(id, &sm, 1);
55
56 TST_CHECKPOINT_WAKE_AND_WAIT(0);
57
58 SAFE_SEMCTL(id, 0, IPC_RMID);
59 }
60
chld2_sem(void)61 static void chld2_sem(void)
62 {
63 int id;
64 struct sembuf sm = {
65 .sem_num = 0,
66 .sem_op = -1,
67 .sem_flg = IPC_NOWAIT,
68 };
69 union semun su = {
70 .val = 1,
71 };
72
73 TST_CHECKPOINT_WAIT(0);
74
75 id = SAFE_SEMGET(TESTKEY, 1, IPC_CREAT);
76
77 SAFE_SEMCTL(id, 0, SETVAL, su);
78
79 TST_CHECKPOINT_WAKE_AND_WAIT(0);
80
81 TEST(semop(id, &sm, 1));
82 if (TST_RET < 0) {
83 if (TST_ERR != EAGAIN)
84 tst_brk(TBROK | TERRNO, "semop error");
85
86 tst_res(TFAIL, "semaphore decremented from different namespace");
87 } else {
88 tst_res(TPASS, "semaphore has not been decremented");
89 }
90
91 TST_CHECKPOINT_WAKE(0);
92
93 SAFE_SEMCTL(id, 0, IPC_RMID);
94 }
95
run(void)96 static void run(void)
97 {
98 clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_sem);
99 clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_sem);
100 }
101
102 static struct tst_test test = {
103 .test_all = run,
104 .needs_root = 1,
105 .needs_checkpoints = 1,
106 .forks_child = 1,
107 };
108