[LTP] [PATCH 1/1] recvmmsg01: Workaround segfault on libc variant on 32 bit

Petr Vorel pvorel@suse.cz
Fri Nov 8 13:21:39 CET 2024


EFAULT test segfaults on newer kernels (e.g. 6.4) on libc variant on
32bit.  Use typical LTP workaround to test by forked child + checking
the terminating signal.

NOTE: testing kernel variants could be done without forking child, but
use it as well for simplicity.

Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
NOTE: working on other 3 tests affected by the same problem
(mq_timedreceive01.c, mq_timedsend01.c,  sigtimedwait01.c).

 .../kernel/syscalls/recvmmsg/recvmmsg01.c     | 48 +++++++++++++++----
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/syscalls/recvmmsg/recvmmsg01.c b/testcases/kernel/syscalls/recvmmsg/recvmmsg01.c
index fb21ea1e70..46658b133d 100644
--- a/testcases/kernel/syscalls/recvmmsg/recvmmsg01.c
+++ b/testcases/kernel/syscalls/recvmmsg/recvmmsg01.c
@@ -47,7 +47,7 @@ static struct test_case tcase[] = {
 		.desc = "bad message vector address",
 		.fd = &receive_sockfd,
 		.exp_errno = EFAULT,
-		.msg_vec = (void*)&bad_addr,
+		.msg_vec = (void *)&bad_addr,
 	},
 	{
 		.desc = "negative seconds in timeout",
@@ -74,23 +74,54 @@ static struct test_case tcase[] = {
 	}
 };
 
-static void do_test(unsigned int i)
+static void verify_recvmmsg(unsigned int i, void *timeout)
 {
 	struct time64_variants *tv = &variants[tst_variant];
 	struct test_case *tc = &tcase[i];
-	void *timeout;
 
 	ts.type = tv->ts_type;
 	tst_ts_set_sec(&ts, tc->tv_sec);
 	tst_ts_set_nsec(&ts, tc->tv_nsec);
 
+	TST_EXP_FAIL2(tv->recvmmsg(*tc->fd, *tc->msg_vec, VLEN, 0, timeout),
+		      tc->exp_errno, "recvmmsg() %s", tc->desc);
+}
+
+static void test_bad_addr(unsigned int i)
+{
+	struct time64_variants *tv = &variants[tst_variant];
+	void *timeout = bad_addr;
+	pid_t pid;
+	int status;
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		verify_recvmmsg(i, timeout);
+		_exit(!TST_PASS);
+	}
+
+	SAFE_WAITPID(pid, &status, 0);
+
+	if (WIFEXITED(status))
+		return;
+
+	if (tv->ts_type == TST_LIBC_TIMESPEC &&
+		WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
+		tst_res(TPASS, "Child killed by signal");
+		return;
+	}
+
+	tst_res(TFAIL, "Child %s", tst_strstatus(status));
+}
+
+static void do_test(unsigned int i)
+{
+	struct test_case *tc = &tcase[i];
+
 	if (tc->bad_ts_addr)
-		timeout = bad_addr;
+		test_bad_addr(i);
 	else
-		timeout = tst_ts_get(&ts);
-
-	TST_EXP_FAIL2(tv->recvmmsg(*tc->fd, *tc->msg_vec, VLEN, 0, timeout),
-	             tc->exp_errno, "recvmmsg() %s", tc->desc);
+		verify_recvmmsg(i, tst_ts_get(&ts));
 }
 
 static void setup(void)
@@ -139,6 +170,7 @@ static struct tst_test test = {
 	.setup = setup,
 	.cleanup = cleanup,
 	.test_variants = ARRAY_SIZE(variants),
+	.forks_child = 1,
 	.bufs = (struct tst_buffers []) {
 		{&iov, .iov_sizes = (int[]){1, -1}},
 		{&msg, .size = VLEN * sizeof(*msg)},
-- 
2.45.2



More information about the ltp mailing list