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 <andrea.cervesato@suse.com>
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
36static 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
61static 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
96static 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
102static struct tst_test test = {
103	.test_all = run,
104	.needs_root = 1,
105	.needs_checkpoints = 1,
106	.forks_child = 1,
107};
108