Skip to content

Commit

Permalink
recvmmsg01: Workaround segfault on libc variant on 32 bit
Browse files Browse the repository at this point in the history
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.

Link: https://lore.kernel.org/ltp/[email protected]/
Suggested-by: Cyril Hrubis <[email protected]>
Reviewed-by: Wei Gao <[email protected]>
Reviewed-by: Cyril Hrubis <[email protected]>
Signed-off-by: Petr Vorel <[email protected]>
  • Loading branch information
pevik committed Nov 11, 2024
1 parent c998b28 commit 1d4d5a0
Showing 1 changed file with 40 additions and 8 deletions.
48 changes: 40 additions & 8 deletions testcases/kernel/syscalls/recvmmsg/recvmmsg01.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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(0);
}

SAFE_WAITPID(pid, &status, 0);

if (WIFEXITED(status) && !WEXITSTATUS(status))
return;

if (tv->ts_type == TST_LIBC_TIMESPEC &&
WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
tst_res(TPASS, "Child killed by expected 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)
Expand Down Expand Up @@ -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)},
Expand Down

0 comments on commit 1d4d5a0

Please sign in to comment.