• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 static int sem_id = -1;
21 static int bad_id = -1;
22 
23 static struct semid_ds sem_ds;
24 static union semun sem_un = {.buf = &sem_ds};
25 static void *semds_ptr = &sem_un;
26 static void *bad_ptr;
27 static union semun arg = {0};
28 
libc_semctl(int semid,int semnum,int cmd,...)29 static int libc_semctl(int semid, int semnum, int cmd, ...)
30 {
31 	return semctl(semid, semnum, cmd, arg);
32 }
33 
sys_semctl(int semid,int semnum,int cmd,...)34 static int sys_semctl(int semid, int semnum, int cmd, ...)
35 {
36 	return tst_syscall(__NR_semctl, semid, semnum, cmd, arg);
37 }
38 
39 static struct tcases {
40 	int *sem_id;
41 	int ipc_cmd;
42 	void **buf;
43 	int error;
44 	char *message;
45 } tests[] = {
46 	{&sem_id, -1, &semds_ptr, EINVAL, "invalid IPC command"},
47 	{&bad_id, IPC_STAT, &semds_ptr, EINVAL, "invalid sem id"},
48 	{&sem_id, GETALL, &bad_ptr, EFAULT, "invalid union arg"},
49 	{&sem_id, IPC_SET, &bad_ptr, EFAULT, "invalid union arg"}
50 };
51 
52 static struct test_variants
53 {
54 	int (*semctl)(int semid, int semnum, int cmd, ...);
55 	char *desc;
56 } variants[] = {
57 	{ .semctl = libc_semctl, .desc = "libc semctl()"},
58 #if (__NR_sys_semctl != __LTP__NR_INVALID_SYSCALL)
59 	{ .semctl = sys_semctl,  .desc = "__NR_semctl syscall"},
60 #endif
61 };
62 
verify_semctl(unsigned int n)63 static void verify_semctl(unsigned int n)
64 {
65 	struct tcases *tc = &tests[n];
66 	struct test_variants *tv = &variants[tst_variant];
67 
68 	if (tc->error == EFAULT && tv->semctl == libc_semctl) {
69 		tst_res(TCONF, "EFAULT is skipped for libc variant");
70 		return;
71 	}
72 
73 	TST_EXP_FAIL(tv->semctl(*(tc->sem_id), 0, tc->ipc_cmd, *(tc->buf)),
74 		tc->error, "semctl() with %s", tc->message);
75 }
76 
setup(void)77 static void setup(void)
78 {
79 	static key_t semkey;
80 	struct test_variants *tv = &variants[tst_variant];
81 
82 	tst_res(TINFO, "Testing variant: %s", tv->desc);
83 
84 	semkey = GETIPCKEY();
85 
86 	sem_id = SAFE_SEMGET(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA);
87 
88 	bad_ptr = tst_get_bad_addr(NULL);
89 }
90 
cleanup(void)91 void cleanup(void)
92 {
93 	if (sem_id != -1)
94 		SAFE_SEMCTL(sem_id, 0, IPC_RMID);
95 }
96 
97 static struct tst_test test = {
98 	.setup = setup,
99 	.cleanup = cleanup,
100 	.test = verify_semctl,
101 	.tcnt = ARRAY_SIZE(tests),
102 	.test_variants = ARRAY_SIZE(variants),
103 };
104