xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/futex/futex_waitv01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2021 SUSE LLC Andrea Cervesato <[email protected]>
4  */
5 
6 /*\
7  * [Description]
8  *
9  * This test verifies EINVAL for futex_waitv syscall.
10  */
11 
12 #include <time.h>
13 #include <stdlib.h>
14 #include "tst_test.h"
15 #include "lapi/futex.h"
16 #include "futex2test.h"
17 #include "tst_safe_clocks.h"
18 
19 static uint32_t *futex;
20 static struct futex_waitv *waitv;
21 
setup(void)22 static void setup(void)
23 {
24 	futex = SAFE_MALLOC(sizeof(uint32_t));
25 	*futex = FUTEX_INITIALIZER;
26 }
27 
init_timeout(struct timespec * to)28 static void init_timeout(struct timespec *to)
29 {
30 	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, to);
31 	to->tv_sec++;
32 }
33 
init_waitv(void)34 static void init_waitv(void)
35 {
36 	waitv->uaddr = (uintptr_t)futex;
37 	waitv->flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
38 	waitv->val = 0;
39 }
40 
test_invalid_flags(void)41 static void test_invalid_flags(void)
42 {
43 	struct timespec to;
44 
45 	init_waitv();
46 	init_timeout(&to);
47 
48 	/* Testing a waiter without FUTEX_32 flag */
49 	waitv->flags = FUTEX_PRIVATE_FLAG;
50 
51 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_MONOTONIC), EINVAL,
52 		     "futex_waitv with invalid flags");
53 }
54 
test_unaligned_address(void)55 static void test_unaligned_address(void)
56 {
57 	struct timespec to;
58 
59 	init_waitv();
60 	init_timeout(&to);
61 
62 	waitv->uaddr = 1;
63 
64 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_MONOTONIC), EINVAL,
65 		     "futex_waitv with unligned address");
66 }
67 
test_null_address(void)68 static void test_null_address(void)
69 {
70 	struct timespec to;
71 
72 	init_waitv();
73 	init_timeout(&to);
74 
75 	waitv->uaddr = 0x00000000;
76 
77 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_MONOTONIC), EFAULT,
78 		     "futex_waitv address is NULL");
79 }
80 
test_null_waiters(void)81 static void test_null_waiters(void)
82 {
83 	struct timespec to;
84 
85 	init_timeout(&to);
86 
87 	TST_EXP_FAIL(futex_waitv(NULL, 1, 0, &to, CLOCK_MONOTONIC), EINVAL,
88 		     "futex_waitv waiters are NULL");
89 }
90 
test_invalid_clockid(void)91 static void test_invalid_clockid(void)
92 {
93 	struct timespec to;
94 
95 	init_waitv();
96 	init_timeout(&to);
97 
98 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_TAI), EINVAL,
99 		     "futex_waitv invalid clockid");
100 }
101 
test_invalid_nr_futexes(void)102 static void test_invalid_nr_futexes(void)
103 {
104 	struct timespec to;
105 
106 	init_waitv();
107 	init_timeout(&to);
108 
109 	/* Valid nr_futexes is [1, 128] */
110 	TST_EXP_FAIL(futex_waitv(waitv, 129, 0, &to, CLOCK_MONOTONIC), EINVAL,
111 		     "futex_waitv invalid nr_futexes");
112 	TST_EXP_FAIL(futex_waitv(waitv, 0, 0, &to, CLOCK_MONOTONIC), EINVAL,
113 		     "futex_waitv invalid nr_futexes");
114 }
115 
test_mismatch_between_uaddr_and_val(void)116 static void test_mismatch_between_uaddr_and_val(void)
117 {
118 	struct timespec to;
119 
120 	waitv->uaddr = (uintptr_t)futex;
121 	waitv->flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
122 	waitv->val = 1;
123 
124 	init_timeout(&to);
125 
126 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_MONOTONIC), EAGAIN,
127 		     "futex_waitv mismatch between value of uaddr and val");
128 }
129 
test_timeout(void)130 static void test_timeout(void)
131 {
132 	struct timespec to;
133 
134 	waitv->uaddr = (uintptr_t)futex;
135 	waitv->flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
136 	waitv->val = 0;
137 
138 	SAFE_CLOCK_GETTIME(CLOCK_REALTIME, &to);
139 	to = tst_timespec_add_us(to, 10000);
140 
141 	TST_EXP_FAIL(futex_waitv(waitv, 1, 0, &to, CLOCK_REALTIME), ETIMEDOUT,
142 		     "futex_waitv timeout");
143 }
144 
cleanup(void)145 static void cleanup(void)
146 {
147 	free(futex);
148 }
149 
run(void)150 static void run(void)
151 {
152 	test_invalid_flags();
153 	test_unaligned_address();
154 	test_null_address();
155 	test_null_waiters();
156 	test_invalid_clockid();
157 	test_invalid_nr_futexes();
158 	test_mismatch_between_uaddr_and_val();
159 	test_timeout();
160 }
161 
162 static struct tst_test test = {
163 	.test_all = run,
164 	.setup = setup,
165 	.cleanup = cleanup,
166 	.min_kver = "5.16",
167 	.bufs =
168 		(struct tst_buffers[]){
169 			{ &waitv, .size = sizeof(struct futex_waitv) },
170 			{},
171 		},
172 };
173