• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
4  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
5  *
6  * Authors:
7  * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
8  * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
9  * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
10  */
11 
12 #include <errno.h>
13 #include <limits.h>
14 
15 static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
16 
17 #include "mq_timed.h"
18 
19 static struct tst_ts ts;
20 static void *bad_addr;
21 
22 static struct test_case tcase[] = {
23 	{
24 		.fd = &fd,
25 	},
26 	{
27 		.fd = &fd,
28 		.len = 1,
29 	},
30 	{
31 		.fd = &fd,
32 		.len = MAX_MSGSIZE,
33 	},
34 	{
35 		.fd = &fd,
36 		.len = 1,
37 		.prio = MQ_PRIO_MAX - 1,
38 	},
39 	{
40 		.fd = &fd,
41 		.len = MAX_MSGSIZE + 1,
42 		.ret = -1,
43 		.err = EMSGSIZE,
44 	},
45 	{
46 		.fd = &fd_invalid,
47 		.ret = -1,
48 		.err = EBADF,
49 	},
50 	{
51 		.fd = &fd_maxint,
52 		.ret = -1,
53 		.err = EBADF,
54 	},
55 	{
56 		.fd = &fd_root,
57 		.ret = -1,
58 		.err = EBADF,
59 	},
60 	{
61 		.fd = &fd_nonblock,
62 		.len = 16,
63 		.ret = -1,
64 		.err = EAGAIN,
65 	},
66 	{
67 		.fd = &fd,
68 		.len = 1,
69 		.prio = MQ_PRIO_MAX,
70 		.ret = -1,
71 		.err = EINVAL,
72 	},
73 	{
74 		.fd = &fd,
75 		.len = 16,
76 		.tv_sec = -1,
77 		.rq = &ts,
78 		.send = 1,
79 		.ret = -1,
80 		.err = EINVAL,
81 	},
82 	{
83 		.fd = &fd,
84 		.len = 16,
85 		.tv_nsec = -1,
86 		.rq = &ts,
87 		.send = 1,
88 		.ret = -1,
89 		.err = EINVAL,
90 	},
91 	{
92 		.fd = &fd,
93 		.len = 16,
94 		.tv_nsec = 1000000000,
95 		.rq = &ts,
96 		.send = 1,
97 		.ret = -1,
98 		.err = EINVAL,
99 	},
100 	{
101 		.fd = &fd,
102 		.len = 16,
103 		.rq = &ts,
104 		.send = 1,
105 		.timeout = 1,
106 		.ret = -1,
107 		.err = ETIMEDOUT,
108 	},
109 	{
110 		.fd = &fd,
111 		.len = 16,
112 		.send = 1,
113 		.signal = 1,
114 		.rq = &ts,
115 		.ret = -1,
116 		.err = EINTR,
117 	},
118 	{
119 		.fd = &fd,
120 		.len = 16,
121 		.bad_msg_addr = 1,
122 		.ret = -1,
123 		.err = EFAULT,
124 	},
125 	{
126 		.fd = &fd,
127 		.len = 16,
128 		.bad_ts_addr = 1,
129 		.ret = -1,
130 		.err = EFAULT,
131 	}
132 };
133 
setup(void)134 static void setup(void)
135 {
136 	struct time64_variants *tv = &variants[tst_variant];
137 
138 	tst_res(TINFO, "Testing variant: %s", tv->desc);
139 	ts.type = tv->ts_type;
140 
141 	bad_addr = tst_get_bad_addr(cleanup_common);
142 
143 	setup_common();
144 }
145 
verify_mqt_send_receive(unsigned int i,pid_t pid)146 static void verify_mqt_send_receive(unsigned int i, pid_t pid)
147 {
148 	struct time64_variants *tv = &variants[tst_variant];
149 	const struct test_case *tc = &tcase[i];
150 	unsigned int j;
151 	unsigned int prio;
152 	char rmsg[MAX_MSGSIZE];
153 	void *msg_ptr, *abs_timeout;
154 
155 	if (tc->bad_msg_addr)
156 		msg_ptr = bad_addr;
157 	else
158 		msg_ptr = smsg;
159 
160 	if (tc->bad_ts_addr)
161 		abs_timeout = bad_addr;
162 	else
163 		abs_timeout = tst_ts_get(tc->rq);
164 
165 	TEST(tv->mqt_send(*tc->fd, msg_ptr, tc->len, tc->prio, abs_timeout));
166 
167 	if (pid > 0)
168 		kill_pid(pid);
169 
170 	if (TST_RET < 0) {
171 		if (tc->err != TST_ERR)
172 			tst_res(TFAIL | TTERRNO,
173 				"mq_timedsend() failed unexpectedly, expected %s",
174 				tst_strerrno(tc->err));
175 		else
176 			tst_res(TPASS | TTERRNO, "mq_timedsend() failed expectedly");
177 
178 		if (*tc->fd == fd)
179 			cleanup_queue(fd);
180 
181 		return;
182 	}
183 
184 	TEST(tv->mqt_receive(*tc->fd, rmsg, MAX_MSGSIZE, &prio, tst_ts_get(tc->rq)));
185 
186 	if (*tc->fd == fd)
187 		cleanup_queue(fd);
188 
189 	if (TST_RET < 0) {
190 		if (tc->err != TST_ERR) {
191 			tst_res(TFAIL | TTERRNO,
192 				"mq_timedreceive() failed unexpectedly, expected %s",
193 				tst_strerrno(tc->err));
194 			return;
195 		}
196 
197 		if (tc->ret >= 0) {
198 			tst_res(TFAIL | TTERRNO, "mq_timedreceive() returned %ld, expected %d",
199 					TST_RET, tc->ret);
200 			return;
201 		}
202 	}
203 
204 	if ((long)tc->len != TST_RET) {
205 		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
206 			TST_RET, tc->len);
207 		return;
208 	}
209 
210 	if (tc->prio != prio) {
211 		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
212 			prio, tc->prio);
213 		return;
214 	}
215 
216 	for (j = 0; j < tc->len; j++) {
217 		if (rmsg[j] != smsg[j]) {
218 			tst_res(TFAIL,
219 				"mq_timedreceive() wrong data %d in %u, expected %d",
220 				rmsg[j], i, smsg[j]);
221 			return;
222 		}
223 	}
224 
225 	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %i",
226 			TST_RET, prio, MAX_MSGSIZE);
227 }
228 
test_bad_addr(unsigned int i)229 static void test_bad_addr(unsigned int i)
230 {
231 	struct time64_variants *tv = &variants[tst_variant];
232 	pid_t pid;
233 	int status;
234 
235 	pid = SAFE_FORK();
236 	if (!pid) {
237 		verify_mqt_send_receive(i, pid);
238 		_exit(0);
239 	}
240 
241 	SAFE_WAITPID(pid, &status, 0);
242 
243 	if (WIFEXITED(status) && !WEXITSTATUS(status))
244 		return;
245 
246 	if (tv->ts_type == TST_LIBC_TIMESPEC &&
247 		WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
248 		tst_res(TPASS, "Child killed by expected signal");
249 		return;
250 	}
251 
252 	tst_res(TFAIL, "Child %s", tst_strstatus(status));
253 }
254 
do_test(unsigned int i)255 static void do_test(unsigned int i)
256 {
257 	struct time64_variants *tv = &variants[tst_variant];
258 	const struct test_case *tc = &tcase[i];
259 	unsigned int j;
260 	pid_t pid = -1;
261 
262 	tst_ts_set_sec(&ts, tc->tv_sec);
263 	tst_ts_set_nsec(&ts, tc->tv_nsec);
264 
265 	if (tc->bad_ts_addr || tc->bad_msg_addr) {
266 		test_bad_addr(i);
267 		return;
268 	}
269 
270 	if (tc->signal)
271 		pid = set_sig(tc->rq, tv->clock_gettime);
272 
273 	if (tc->timeout)
274 		set_timeout(tc->rq, tv->clock_gettime);
275 
276 	if (tc->send) {
277 		for (j = 0; j < MSG_LENGTH; j++)
278 			if (tv->mqt_send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
279 				tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
280 				return;
281 			}
282 	}
283 
284 	verify_mqt_send_receive(i, pid);
285 }
286 
287 static struct tst_test test = {
288 	.tcnt = ARRAY_SIZE(tcase),
289 	.test = do_test,
290 	.test_variants = ARRAY_SIZE(variants),
291 	.setup = setup,
292 	.cleanup = cleanup_common,
293 	.forks_child = 1,
294 };
295