1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2009
4f08c3bdfSopenharmony_ci *				Veerendra C <vechandr@in.ibm.com>
5f08c3bdfSopenharmony_ci * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Test SysV IPC semaphore usage between namespaces and processes.
12f08c3bdfSopenharmony_ci *
13f08c3bdfSopenharmony_ci * [Algorithm]
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci * Create 2 'containers'
16f08c3bdfSopenharmony_ci * In container1 create semaphore with a specific key and lock it
17f08c3bdfSopenharmony_ci * In container2 try to access the semaphore created in container1 and try to
18f08c3bdfSopenharmony_ci * unlock it.
19f08c3bdfSopenharmony_ci *
20f08c3bdfSopenharmony_ci * If mode = None, test will PASS when semaphore created process1 can be read
21f08c3bdfSopenharmony_ci * and unlocked from process2.
22f08c3bdfSopenharmony_ci * If mode = Clone, test will PASS when semaphore created in container1 can't
23f08c3bdfSopenharmony_ci * be accessed from container2.
24f08c3bdfSopenharmony_ci * If mode = Unshare, test will PASS when semaphore created in container2 can't
25f08c3bdfSopenharmony_ci * be accessed from container2.
26f08c3bdfSopenharmony_ci */
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#define _GNU_SOURCE
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci#include <sys/wait.h>
31f08c3bdfSopenharmony_ci#include <sys/msg.h>
32f08c3bdfSopenharmony_ci#include <sys/types.h>
33f08c3bdfSopenharmony_ci#include <sys/sem.h>
34f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h"
35f08c3bdfSopenharmony_ci#include "tst_test.h"
36f08c3bdfSopenharmony_ci#include "common.h"
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#define MY_KEY 124326L
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_cistatic char *str_op;
41f08c3bdfSopenharmony_cistatic int use_clone;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_cistatic void check_sem1(void)
44f08c3bdfSopenharmony_ci{
45f08c3bdfSopenharmony_ci	int id;
46f08c3bdfSopenharmony_ci	struct sembuf sm = {
47f08c3bdfSopenharmony_ci		.sem_num = 0,
48f08c3bdfSopenharmony_ci		.sem_op = 1,
49f08c3bdfSopenharmony_ci		.sem_flg = SEM_UNDO,
50f08c3bdfSopenharmony_ci	};
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	id = SAFE_SEMGET(MY_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci	tst_res(TINFO, "%s: created key in child1", str_op);
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE_AND_WAIT(0);
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	tst_res(TINFO, "Lock semaphore in container1");
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	SAFE_SEMOP(id, &sm, 1);
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE_AND_WAIT(0);
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	SAFE_SEMCTL(id, IPC_RMID, 0);
65f08c3bdfSopenharmony_ci}
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_cistatic void check_sem2(void)
68f08c3bdfSopenharmony_ci{
69f08c3bdfSopenharmony_ci	int id;
70f08c3bdfSopenharmony_ci	struct sembuf sm = {
71f08c3bdfSopenharmony_ci		.sem_num = 0,
72f08c3bdfSopenharmony_ci		.sem_op = -1,
73f08c3bdfSopenharmony_ci		.sem_flg = IPC_NOWAIT | SEM_UNDO,
74f08c3bdfSopenharmony_ci	};
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	tst_res(TINFO, "%s: reading key in child2", str_op);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	id = semget(MY_KEY, 1, 0);
81f08c3bdfSopenharmony_ci	if (id >= 0) {
82f08c3bdfSopenharmony_ci		if (use_clone == T_NONE)
83f08c3bdfSopenharmony_ci			tst_res(TPASS, "Plain cloned process able to access the semaphore created");
84f08c3bdfSopenharmony_ci		else
85f08c3bdfSopenharmony_ci			tst_res(TFAIL, "%s: In namespace2 found semaphore created in namespace1", str_op);
86f08c3bdfSopenharmony_ci	} else {
87f08c3bdfSopenharmony_ci		if (use_clone == T_NONE)
88f08c3bdfSopenharmony_ci			tst_res(TFAIL, "Plain cloned process didn't find semaphore");
89f08c3bdfSopenharmony_ci		else
90f08c3bdfSopenharmony_ci			tst_res(TPASS, "%s: In namespace2 unable to access semaphore created in namespace1", str_op);
91f08c3bdfSopenharmony_ci	}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE_AND_WAIT(0);
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci	if (id >= 0) {
96f08c3bdfSopenharmony_ci		tst_res(TINFO, "Trying to unlock semaphore in container2");
97f08c3bdfSopenharmony_ci		TEST(semop(id, &sm, 1));
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci		if (TST_RET >= 0) {
100f08c3bdfSopenharmony_ci			if (use_clone == T_NONE)
101f08c3bdfSopenharmony_ci				tst_res(TPASS, "Plain cloned process able to unlock semaphore");
102f08c3bdfSopenharmony_ci			else
103f08c3bdfSopenharmony_ci				tst_res(TFAIL, "%s: In namespace2 able to unlock the semaphore created in an namespace1", str_op);
104f08c3bdfSopenharmony_ci		} else {
105f08c3bdfSopenharmony_ci			if (use_clone == T_NONE)
106f08c3bdfSopenharmony_ci				tst_res(TFAIL, "Plain cloned process unable to unlock semaphore");
107f08c3bdfSopenharmony_ci			else
108f08c3bdfSopenharmony_ci				tst_res(TPASS, "%s: In namespace2 unable to unlock the semaphore created in an namespace1", str_op);
109f08c3bdfSopenharmony_ci		}
110f08c3bdfSopenharmony_ci	}
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
113f08c3bdfSopenharmony_ci}
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_cistatic void run(void)
116f08c3bdfSopenharmony_ci{
117f08c3bdfSopenharmony_ci	clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem1);
118f08c3bdfSopenharmony_ci	clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem2);
119f08c3bdfSopenharmony_ci}
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_cistatic void setup(void)
122f08c3bdfSopenharmony_ci{
123f08c3bdfSopenharmony_ci	use_clone = get_clone_unshare_enum(str_op);
124f08c3bdfSopenharmony_ci}
125f08c3bdfSopenharmony_ci
126f08c3bdfSopenharmony_cistatic void cleanup(void)
127f08c3bdfSopenharmony_ci{
128f08c3bdfSopenharmony_ci	int id;
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci	id = semget(MY_KEY, 1, 0);
131f08c3bdfSopenharmony_ci	if (id >= 0) {
132f08c3bdfSopenharmony_ci		tst_res(TINFO, "Destroy semaphore");
133f08c3bdfSopenharmony_ci		SAFE_SEMCTL(id, IPC_RMID, 0);
134f08c3bdfSopenharmony_ci	}
135f08c3bdfSopenharmony_ci}
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_cistatic struct tst_test test = {
138f08c3bdfSopenharmony_ci	.test_all = run,
139f08c3bdfSopenharmony_ci	.setup = setup,
140f08c3bdfSopenharmony_ci	.cleanup = cleanup,
141f08c3bdfSopenharmony_ci	.needs_root = 1,
142f08c3bdfSopenharmony_ci	.forks_child = 1,
143f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
144f08c3bdfSopenharmony_ci	.options = (struct tst_option[]) {
145f08c3bdfSopenharmony_ci		{ "m:", &str_op, "Test execution mode <clone|unshare|none>" },
146f08c3bdfSopenharmony_ci		{},
147f08c3bdfSopenharmony_ci	},
148f08c3bdfSopenharmony_ci};
149