1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2014 Fujitsu Ltd.
4 * Author: Zeng Linggang <[email protected]>
5 *
6 * DESCRIPTION
7 * Verify that,
8 * 1. fd is not a valid file descriptor, EBADF would return.
9 * 2. old_value is not valid a pointer, EFAULT would return.
10 * 3. fd is not a valid timerfd file descriptor, EINVAL would return.
11 * 4. flags is invalid, EINVAL would return.
12 */
13
14 #define _GNU_SOURCE
15
16 #include "time64_variants.h"
17 #include "tst_timer.h"
18 #include "lapi/timerfd.h"
19
20 static int bad_clockfd = -1;
21 static int clockfd;
22 static int fd;
23 static void *bad_addr;
24
25 static struct test_case_t {
26 int *fd;
27 int flags;
28 struct tst_its *old_value;
29 int exp_errno;
30 } test_cases[] = {
31 {&bad_clockfd, 0, NULL, EBADF},
32 {&clockfd, 0, NULL, EFAULT},
33 {&fd, 0, NULL, EINVAL},
34 {&clockfd, -1, NULL, EINVAL},
35 };
36
37 static struct tst_its new_value;
38
39 static struct time64_variants variants[] = {
40 #if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
41 { .tfd_settime = sys_timerfd_settime, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
42 #endif
43
44 #if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
45 { .tfd_settime = sys_timerfd_settime64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
46 #endif
47 };
48
setup(void)49 static void setup(void)
50 {
51 struct time64_variants *tv = &variants[tst_variant];
52
53 tst_res(TINFO, "Testing variant: %s", tv->desc);
54 bad_addr = tst_get_bad_addr(NULL);
55 new_value.type = tv->ts_type;
56
57 clockfd = timerfd_create(CLOCK_REALTIME, 0);
58 if (clockfd == -1) {
59 tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
60 return;
61 }
62
63 fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
64 }
65
cleanup(void)66 static void cleanup(void)
67 {
68 if (clockfd > 0)
69 close(clockfd);
70
71 if (fd > 0)
72 close(fd);
73 }
74
run(unsigned int n)75 static void run(unsigned int n)
76 {
77 struct time64_variants *tv = &variants[tst_variant];
78 struct test_case_t *test = &test_cases[n];
79 void *its;
80
81 if (test->exp_errno == EFAULT)
82 its = bad_addr;
83 else
84 its = tst_its_get(test->old_value);
85
86 TEST(tv->tfd_settime(*test->fd, test->flags, tst_its_get(&new_value),
87 its));
88
89 if (TST_RET != -1) {
90 tst_res(TFAIL, "timerfd_settime() succeeded unexpectedly");
91 return;
92 }
93
94 if (TST_ERR == test->exp_errno) {
95 tst_res(TPASS | TTERRNO,
96 "timerfd_settime() failed as expected");
97 } else {
98 tst_res(TFAIL | TTERRNO,
99 "timerfd_settime() failed unexpectedly; expected: "
100 "%d - %s", test->exp_errno, strerror(test->exp_errno));
101 }
102 }
103
104 static struct tst_test test = {
105 .test = run,
106 .tcnt = ARRAY_SIZE(test_cases),
107 .test_variants = ARRAY_SIZE(variants),
108 .setup = setup,
109 .cleanup = cleanup,
110 .needs_tmpdir = 1,
111 };
112