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