1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd 4f08c3bdfSopenharmony_ci * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, 5f08c3bdfSopenharmony_ci * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, 6f08c3bdfSopenharmony_ci * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> 7f08c3bdfSopenharmony_ci * Copyright (c) 2016 Linux Test Project 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#ifndef _GNU_SOURCE 11f08c3bdfSopenharmony_ci#define _GNU_SOURCE 12f08c3bdfSopenharmony_ci#endif 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <errno.h> 15f08c3bdfSopenharmony_ci#include <poll.h> 16f08c3bdfSopenharmony_ci#include <signal.h> 17f08c3bdfSopenharmony_ci#include <stdlib.h> 18f08c3bdfSopenharmony_ci#include <sys/types.h> 19f08c3bdfSopenharmony_ci#include <sys/wait.h> 20f08c3bdfSopenharmony_ci#include "ltp_signal.h" 21f08c3bdfSopenharmony_ci#include "time64_variants.h" 22f08c3bdfSopenharmony_ci#include "tst_sig_proc.h" 23f08c3bdfSopenharmony_ci#include "tst_test.h" 24f08c3bdfSopenharmony_ci#include "tst_timer.h" 25f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci/* Older versions of glibc don't publish this constant's value. */ 28f08c3bdfSopenharmony_ci#ifndef POLLRDHUP 29f08c3bdfSopenharmony_ci#define POLLRDHUP 0x2000 30f08c3bdfSopenharmony_ci#endif 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#define TYPE_NAME(x) .ttype = x, .desc = #x 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_cistruct test_case { 35f08c3bdfSopenharmony_ci int ttype; /* test type (enum) */ 36f08c3bdfSopenharmony_ci const char *desc; /* test description (name) */ 37f08c3bdfSopenharmony_ci int ret; /* expected ret code */ 38f08c3bdfSopenharmony_ci int err; /* expected errno code */ 39f08c3bdfSopenharmony_ci short expect_revents; /* expected revents value */ 40f08c3bdfSopenharmony_ci unsigned int nfds; /* nfds ppoll parameter */ 41f08c3bdfSopenharmony_ci sigset_t *sigmask; /* sigmask ppoll parameter */ 42f08c3bdfSopenharmony_ci sigset_t *sigmask_cur; /* sigmask set for current process */ 43f08c3bdfSopenharmony_ci struct tst_ts *ts; /* ts ppoll parameter */ 44f08c3bdfSopenharmony_ci struct pollfd *fds; /* fds ppoll parameter */ 45f08c3bdfSopenharmony_ci int sigint_count; /* if > 0, spawn process to send SIGINT */ 46f08c3bdfSopenharmony_ci /* 'count' times to current process */ 47f08c3bdfSopenharmony_ci unsigned int sigint_delay; /* delay between SIGINT signals */ 48f08c3bdfSopenharmony_ci}; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cienum test_type { 51f08c3bdfSopenharmony_ci NORMAL, 52f08c3bdfSopenharmony_ci MASK_SIGNAL, 53f08c3bdfSopenharmony_ci TIMEOUT, 54f08c3bdfSopenharmony_ci FD_ALREADY_CLOSED, 55f08c3bdfSopenharmony_ci SEND_SIGINT, 56f08c3bdfSopenharmony_ci SEND_SIGINT_RACE_TEST, 57f08c3bdfSopenharmony_ci INVALID_NFDS, 58f08c3bdfSopenharmony_ci INVALID_FDS, 59f08c3bdfSopenharmony_ci}; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic int fd1 = -1; 62f08c3bdfSopenharmony_cistatic sigset_t sigmask_empty, sigmask_sigint; 63f08c3bdfSopenharmony_cistatic struct pollfd fds_good[1], fds_already_closed[1]; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cistatic struct tst_ts ts_short, ts_long; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci/* Test cases 68f08c3bdfSopenharmony_ci * 69f08c3bdfSopenharmony_ci * test status of errors on man page 70f08c3bdfSopenharmony_ci * 71f08c3bdfSopenharmony_ci * EBADF can't check because EBADF never happen even though 72f08c3bdfSopenharmony_ci * fd was invalid. In this case, information of invalid 73f08c3bdfSopenharmony_ci * fd is set in revents 74f08c3bdfSopenharmony_ci * EFAULT v ('fds' array in the invalid address space) 75f08c3bdfSopenharmony_ci * EINTR v (a non blocked signal was caught) 76f08c3bdfSopenharmony_ci * EINVAL v ('nfds' is over the 'RLIMIT_NOFILE' value) 77f08c3bdfSopenharmony_ci * ENOMEM can't check because it's difficult to create no-memory 78f08c3bdfSopenharmony_ci */ 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic struct test_case tcase[] = { 81f08c3bdfSopenharmony_ci { 82f08c3bdfSopenharmony_ci TYPE_NAME(NORMAL), 83f08c3bdfSopenharmony_ci .expect_revents = POLLIN | POLLOUT, 84f08c3bdfSopenharmony_ci .ret = 1, 85f08c3bdfSopenharmony_ci .err = 0, 86f08c3bdfSopenharmony_ci .nfds = 1, 87f08c3bdfSopenharmony_ci .ts = &ts_long, 88f08c3bdfSopenharmony_ci .fds = fds_good, 89f08c3bdfSopenharmony_ci }, 90f08c3bdfSopenharmony_ci { 91f08c3bdfSopenharmony_ci TYPE_NAME(MASK_SIGNAL), 92f08c3bdfSopenharmony_ci .ret = 0, 93f08c3bdfSopenharmony_ci .err = 0, 94f08c3bdfSopenharmony_ci .nfds = 0, 95f08c3bdfSopenharmony_ci .sigmask = &sigmask_sigint, 96f08c3bdfSopenharmony_ci .ts = &ts_short, 97f08c3bdfSopenharmony_ci .fds = fds_good, 98f08c3bdfSopenharmony_ci .sigint_count = 4, 99f08c3bdfSopenharmony_ci .sigint_delay = 100000, 100f08c3bdfSopenharmony_ci }, 101f08c3bdfSopenharmony_ci { 102f08c3bdfSopenharmony_ci TYPE_NAME(TIMEOUT), 103f08c3bdfSopenharmony_ci .ret = 0, 104f08c3bdfSopenharmony_ci .err = 0, 105f08c3bdfSopenharmony_ci .nfds = 0, 106f08c3bdfSopenharmony_ci .ts = &ts_short, 107f08c3bdfSopenharmony_ci .fds = fds_good, 108f08c3bdfSopenharmony_ci }, 109f08c3bdfSopenharmony_ci { 110f08c3bdfSopenharmony_ci TYPE_NAME(FD_ALREADY_CLOSED), 111f08c3bdfSopenharmony_ci .expect_revents = POLLNVAL, 112f08c3bdfSopenharmony_ci .ret = 1, 113f08c3bdfSopenharmony_ci .err = 0, 114f08c3bdfSopenharmony_ci .nfds = 1, 115f08c3bdfSopenharmony_ci .ts = &ts_long, 116f08c3bdfSopenharmony_ci .fds = fds_already_closed, 117f08c3bdfSopenharmony_ci }, 118f08c3bdfSopenharmony_ci { 119f08c3bdfSopenharmony_ci TYPE_NAME(SEND_SIGINT), 120f08c3bdfSopenharmony_ci .ret = -1, 121f08c3bdfSopenharmony_ci .err = EINTR, 122f08c3bdfSopenharmony_ci .nfds = 0, 123f08c3bdfSopenharmony_ci .ts = &ts_long, 124f08c3bdfSopenharmony_ci .fds = fds_good, 125f08c3bdfSopenharmony_ci .sigint_count = 40, 126f08c3bdfSopenharmony_ci .sigint_delay = 100000, 127f08c3bdfSopenharmony_ci }, 128f08c3bdfSopenharmony_ci { 129f08c3bdfSopenharmony_ci TYPE_NAME(SEND_SIGINT_RACE_TEST), 130f08c3bdfSopenharmony_ci .ret = -1, 131f08c3bdfSopenharmony_ci .err = EINTR, 132f08c3bdfSopenharmony_ci .nfds = 0, 133f08c3bdfSopenharmony_ci .sigmask = &sigmask_empty, 134f08c3bdfSopenharmony_ci .sigmask_cur = &sigmask_sigint, 135f08c3bdfSopenharmony_ci .ts = &ts_long, 136f08c3bdfSopenharmony_ci .fds = fds_good, 137f08c3bdfSopenharmony_ci .sigint_count = 1, 138f08c3bdfSopenharmony_ci .sigint_delay = 0, 139f08c3bdfSopenharmony_ci }, 140f08c3bdfSopenharmony_ci { 141f08c3bdfSopenharmony_ci TYPE_NAME(INVALID_NFDS), 142f08c3bdfSopenharmony_ci .ret = -1, 143f08c3bdfSopenharmony_ci .err = EINVAL, 144f08c3bdfSopenharmony_ci .nfds = -1, 145f08c3bdfSopenharmony_ci .ts = &ts_long, 146f08c3bdfSopenharmony_ci .fds = fds_good, 147f08c3bdfSopenharmony_ci }, 148f08c3bdfSopenharmony_ci { 149f08c3bdfSopenharmony_ci TYPE_NAME(INVALID_FDS), 150f08c3bdfSopenharmony_ci .ret = -1, 151f08c3bdfSopenharmony_ci .err = EFAULT, 152f08c3bdfSopenharmony_ci .nfds = 1, 153f08c3bdfSopenharmony_ci .ts = &ts_long, 154f08c3bdfSopenharmony_ci .fds = (struct pollfd *) -1, 155f08c3bdfSopenharmony_ci }, 156f08c3bdfSopenharmony_ci}; 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_cistatic inline int libc_ppoll(struct pollfd *fds, nfds_t nfds, void *tmo_p, 159f08c3bdfSopenharmony_ci const sigset_t *sigmask, 160f08c3bdfSopenharmony_ci size_t sigsetsize LTP_ATTRIBUTE_UNUSED) 161f08c3bdfSopenharmony_ci{ 162f08c3bdfSopenharmony_ci return ppoll(fds, nfds, tmo_p, sigmask); 163f08c3bdfSopenharmony_ci} 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_cistatic inline int sys_ppoll(struct pollfd *fds, nfds_t nfds, void *tmo_p, 166f08c3bdfSopenharmony_ci const sigset_t *sigmask, size_t sigsetsize) 167f08c3bdfSopenharmony_ci{ 168f08c3bdfSopenharmony_ci return tst_syscall(__NR_ppoll, fds, nfds, tmo_p, sigmask, sigsetsize); 169f08c3bdfSopenharmony_ci} 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_cistatic inline int sys_ppoll_time64(struct pollfd *fds, nfds_t nfds, void *tmo_p, 172f08c3bdfSopenharmony_ci const sigset_t *sigmask, size_t sigsetsize) 173f08c3bdfSopenharmony_ci{ 174f08c3bdfSopenharmony_ci return tst_syscall(__NR_ppoll_time64, fds, nfds, tmo_p, sigmask, 175f08c3bdfSopenharmony_ci sigsetsize); 176f08c3bdfSopenharmony_ci} 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_cistatic struct time64_variants variants[] = { 179f08c3bdfSopenharmony_ci { .ppoll = libc_ppoll, .ts_type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"}, 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci#if (__NR_ppoll != __LTP__NR_INVALID_SYSCALL) 182f08c3bdfSopenharmony_ci { .ppoll = sys_ppoll, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"}, 183f08c3bdfSopenharmony_ci#endif 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ci#if (__NR_ppoll_time64 != __LTP__NR_INVALID_SYSCALL) 186f08c3bdfSopenharmony_ci { .ppoll = sys_ppoll_time64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, 187f08c3bdfSopenharmony_ci#endif 188f08c3bdfSopenharmony_ci}; 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_cistatic void sighandler(int sig LTP_ATTRIBUTE_UNUSED) 191f08c3bdfSopenharmony_ci{ 192f08c3bdfSopenharmony_ci} 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_cistatic void setup(void) 195f08c3bdfSopenharmony_ci{ 196f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 197f08c3bdfSopenharmony_ci int fd2; 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", tv->desc); 200f08c3bdfSopenharmony_ci SAFE_SIGNAL(SIGINT, sighandler); 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ci if (sigemptyset(&sigmask_empty) == -1) 203f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigemptyset"); 204f08c3bdfSopenharmony_ci if (sigemptyset(&sigmask_sigint) == -1) 205f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigemptyset"); 206f08c3bdfSopenharmony_ci if (sigaddset(&sigmask_sigint, SIGINT) == -1) 207f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigaddset"); 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci fd1 = SAFE_OPEN("testfile1", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 210f08c3bdfSopenharmony_ci fds_good[0].fd = fd1; 211f08c3bdfSopenharmony_ci fds_good[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP; 212f08c3bdfSopenharmony_ci fds_good[0].revents = 0; 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci fd2 = SAFE_OPEN("testfile2", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 215f08c3bdfSopenharmony_ci fds_already_closed[0].fd = fd2; 216f08c3bdfSopenharmony_ci fds_already_closed[0].events = POLLIN | POLLPRI | POLLOUT | POLLRDHUP; 217f08c3bdfSopenharmony_ci fds_already_closed[0].revents = 0; 218f08c3bdfSopenharmony_ci SAFE_CLOSE(fd2); 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci ts_short.type = ts_long.type = tv->ts_type; 221f08c3bdfSopenharmony_ci tst_ts_set_sec(&ts_short, 0); 222f08c3bdfSopenharmony_ci tst_ts_set_nsec(&ts_short, 20000000); 223f08c3bdfSopenharmony_ci tst_ts_set_sec(&ts_long, 2); 224f08c3bdfSopenharmony_ci tst_ts_set_nsec(&ts_long, 0); 225f08c3bdfSopenharmony_ci} 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_cistatic void cleanup(void) 228f08c3bdfSopenharmony_ci{ 229f08c3bdfSopenharmony_ci if (fd1 != -1) 230f08c3bdfSopenharmony_ci SAFE_CLOSE(fd1); 231f08c3bdfSopenharmony_ci} 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_cistatic void do_test(unsigned int i) 234f08c3bdfSopenharmony_ci{ 235f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 236f08c3bdfSopenharmony_ci pid_t pid = 0; 237f08c3bdfSopenharmony_ci int sys_ret, sys_errno = 0, dummy; 238f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 239f08c3bdfSopenharmony_ci struct tst_ts ts, *tsp = NULL; 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci if (tc->ts) { 242f08c3bdfSopenharmony_ci memcpy(&ts, tc->ts, sizeof(ts)); 243f08c3bdfSopenharmony_ci tsp = &ts; 244f08c3bdfSopenharmony_ci } 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci tst_res(TINFO, "case %s", tc->desc); 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci /* setup */ 249f08c3bdfSopenharmony_ci if (tc->sigmask_cur) { 250f08c3bdfSopenharmony_ci if (sigprocmask(SIG_SETMASK, tc->sigmask_cur, NULL) == -1) 251f08c3bdfSopenharmony_ci tst_brk(TBROK, "sigprocmask"); 252f08c3bdfSopenharmony_ci } 253f08c3bdfSopenharmony_ci if (tc->sigint_count > 0) { 254f08c3bdfSopenharmony_ci pid = create_sig_proc(SIGINT, tc->sigint_count, 255f08c3bdfSopenharmony_ci tc->sigint_delay); 256f08c3bdfSopenharmony_ci } 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci /* test */ 259f08c3bdfSopenharmony_ci errno = 0; 260f08c3bdfSopenharmony_ci sys_ret = tv->ppoll(tc->fds, tc->nfds, tst_ts_get(tsp), tc->sigmask, 261f08c3bdfSopenharmony_ci SIGSETSIZE); 262f08c3bdfSopenharmony_ci sys_errno = errno; 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci /* cleanup */ 265f08c3bdfSopenharmony_ci if (tc->sigmask_cur) { 266f08c3bdfSopenharmony_ci if (sigprocmask(SIG_SETMASK, &sigmask_empty, NULL) == -1) 267f08c3bdfSopenharmony_ci tst_brk(TBROK, "sigprocmask"); 268f08c3bdfSopenharmony_ci } 269f08c3bdfSopenharmony_ci if (pid > 0) { 270f08c3bdfSopenharmony_ci kill(pid, SIGTERM); 271f08c3bdfSopenharmony_ci SAFE_WAIT(&dummy); 272f08c3bdfSopenharmony_ci } 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci /* result check */ 275f08c3bdfSopenharmony_ci if (tc->expect_revents) { 276f08c3bdfSopenharmony_ci if (tc->fds[0].revents == tc->expect_revents) 277f08c3bdfSopenharmony_ci tst_res(TPASS, "revents=0x%04x", tc->expect_revents); 278f08c3bdfSopenharmony_ci else 279f08c3bdfSopenharmony_ci tst_res(TFAIL, "revents=0x%04x, expected=0x%04x", 280f08c3bdfSopenharmony_ci tc->fds[0].revents, tc->expect_revents); 281f08c3bdfSopenharmony_ci } 282f08c3bdfSopenharmony_ci if (tc->ret >= 0 && tc->ret == sys_ret) { 283f08c3bdfSopenharmony_ci tst_res(TPASS, "ret: %d", sys_ret); 284f08c3bdfSopenharmony_ci } else if (tc->ret == -1 && sys_ret == -1 && sys_errno == tc->err) { 285f08c3bdfSopenharmony_ci tst_res(TPASS, "ret: %d, errno: %s (%d)", sys_ret, 286f08c3bdfSopenharmony_ci tst_strerrno(sys_errno), sys_errno); 287f08c3bdfSopenharmony_ci } else { 288f08c3bdfSopenharmony_ci tst_res(TFAIL, "ret: %d, exp: %d, ret_errno: %s (%d)," 289f08c3bdfSopenharmony_ci " exp_errno: %s (%d)", sys_ret, tc->ret, 290f08c3bdfSopenharmony_ci tst_strerrno(sys_errno), sys_errno, 291f08c3bdfSopenharmony_ci tst_strerrno(tc->err), tc->err); 292f08c3bdfSopenharmony_ci } 293f08c3bdfSopenharmony_ci} 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_cistatic struct tst_test test = { 296f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcase), 297f08c3bdfSopenharmony_ci .test = do_test, 298f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 299f08c3bdfSopenharmony_ci .setup = setup, 300f08c3bdfSopenharmony_ci .cleanup = cleanup, 301f08c3bdfSopenharmony_ci .forks_child = 1, 302f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 303f08c3bdfSopenharmony_ci}; 304