// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014 Red Hat, Inc. * Copyright (C) 2022 SUSE LLC Andrea Cervesato */ /*\ * [Description] * * Test SysV IPC semaphore usage between cloned processes. * * [Algorithm] * * 1. Clones two child processes with CLONE_NEWIPC flag, each child * creates System V semaphore (sem) with the _identical_ key. * 2. Child1 locks the semaphore. * 3. Child2 locks the semaphore. * 4. Locking the semaphore with the identical key but from two different * IPC namespaces should not interfere with each other, so if child2 * is able to lock the semaphore (after child1 locked it), test passes, * otherwise test fails. */ #define _GNU_SOURCE #include #include #include #include "tst_safe_sysv_ipc.h" #include "tst_test.h" #include "lapi/sem.h" #include "common.h" #define TESTKEY 124426L static void chld1_sem(void) { int id; struct sembuf sm = { .sem_num = 0, .sem_op = -1, .sem_flg = IPC_NOWAIT, }; union semun su = { .val = 1, }; id = SAFE_SEMGET(TESTKEY, 1, IPC_CREAT); SAFE_SEMCTL(id, 0, SETVAL, su); TST_CHECKPOINT_WAKE_AND_WAIT(0); SAFE_SEMOP(id, &sm, 1); TST_CHECKPOINT_WAKE_AND_WAIT(0); SAFE_SEMCTL(id, 0, IPC_RMID); } static void chld2_sem(void) { int id; struct sembuf sm = { .sem_num = 0, .sem_op = -1, .sem_flg = IPC_NOWAIT, }; union semun su = { .val = 1, }; TST_CHECKPOINT_WAIT(0); id = SAFE_SEMGET(TESTKEY, 1, IPC_CREAT); SAFE_SEMCTL(id, 0, SETVAL, su); TST_CHECKPOINT_WAKE_AND_WAIT(0); TEST(semop(id, &sm, 1)); if (TST_RET < 0) { if (TST_ERR != EAGAIN) tst_brk(TBROK | TERRNO, "semop error"); tst_res(TFAIL, "semaphore decremented from different namespace"); } else { tst_res(TPASS, "semaphore has not been decremented"); } TST_CHECKPOINT_WAKE(0); SAFE_SEMCTL(id, 0, IPC_RMID); } static void run(void) { clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_sem); clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_sem); } static struct tst_test test = { .test_all = run, .needs_root = 1, .needs_checkpoints = 1, .forks_child = 1, };