xref: /aosp_15_r20/external/ltp/testcases/kernel/containers/sysvipc/sem_comm.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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