1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * HISTORY 6 * 03/2001 - Written by Wayne Boyer 7 */ 8/*\ 9 * [Description] 10 * 11 * Test for semctl() EINVAL and EFAULT errors 12 */ 13 14#include "tst_safe_sysv_ipc.h" 15#include "tst_test.h" 16#include "lapi/sem.h" 17#include "libnewipc.h" 18#include "lapi/syscalls.h" 19 20static int sem_id = -1; 21static int bad_id = -1; 22 23static struct semid_ds sem_ds; 24static union semun sem_un = {.buf = &sem_ds}; 25static void *semds_ptr = &sem_un; 26static void *bad_ptr; 27static union semun arg = {0}; 28 29static int libc_semctl(int semid, int semnum, int cmd, ...) 30{ 31 va_list ap; 32 33 va_start(ap, cmd); 34 arg = va_arg(ap, union semun); 35 va_end(ap); 36 return semctl(semid, semnum, cmd, arg); 37} 38 39static int sys_semctl(int semid, int semnum, int cmd, ...) 40{ 41 va_list ap; 42 43 va_start(ap, cmd); 44 arg = va_arg(ap, union semun); 45 va_end(ap); 46 return tst_syscall(__NR_semctl, semid, semnum, cmd, arg); 47} 48 49static struct tcases { 50 int *sem_id; 51 int ipc_cmd; 52 void **buf; 53 int error; 54 char *message; 55} tests[] = { 56 {&sem_id, -1, &semds_ptr, EINVAL, "invalid IPC command"}, 57 {&bad_id, IPC_STAT, &semds_ptr, EINVAL, "invalid sem id"}, 58 {&sem_id, GETALL, &bad_ptr, EFAULT, "invalid union arg"}, 59 {&sem_id, IPC_SET, &bad_ptr, EFAULT, "invalid union arg"} 60}; 61 62static struct test_variants 63{ 64 int (*semctl)(int semid, int semnum, int cmd, ...); 65 char *desc; 66} variants[] = { 67 { .semctl = libc_semctl, .desc = "libc semctl()"}, 68#if (__NR_sys_semctl != __LTP__NR_INVALID_SYSCALL) 69 { .semctl = sys_semctl, .desc = "__NR_semctl syscall"}, 70#endif 71}; 72 73static void verify_semctl(unsigned int n) 74{ 75 struct tcases *tc = &tests[n]; 76 struct test_variants *tv = &variants[tst_variant]; 77 78 if (tc->error == EFAULT && tv->semctl == libc_semctl) { 79 tst_res(TCONF, "EFAULT is skipped for libc variant"); 80 return; 81 } 82 83 TST_EXP_FAIL(tv->semctl(*(tc->sem_id), 0, tc->ipc_cmd, *(tc->buf)), 84 tc->error, "semctl() with %s", tc->message); 85} 86 87static void setup(void) 88{ 89 static key_t semkey; 90 struct test_variants *tv = &variants[tst_variant]; 91 92 tst_res(TINFO, "Testing variant: %s", tv->desc); 93 94 semkey = GETIPCKEY(); 95 96 sem_id = SAFE_SEMGET(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); 97 98 bad_ptr = tst_get_bad_addr(NULL); 99} 100 101static void cleanup(void) 102{ 103 if (sem_id != -1) 104 SAFE_SEMCTL(sem_id, 0, IPC_RMID); 105} 106 107static struct tst_test test = { 108 .setup = setup, 109 .cleanup = cleanup, 110 .test = verify_semctl, 111 .tcnt = ARRAY_SIZE(tests), 112 .test_variants = ARRAY_SIZE(variants), 113}; 114