1 /*
2 * Check decoding of clock_nanosleep and clock_gettime syscalls.
3 *
4 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #ifdef __NR_clock_nanosleep
15
16 # include <assert.h>
17 # include <stdio.h>
18 # include <stdint.h>
19 # include <signal.h>
20 # include <time.h>
21 # include <unistd.h>
22 # include <sys/time.h>
23
24 static void
25 handler(int signo)
26 {
27 }
28
29 int
30 main(void)
31 {
32 struct {
33 kernel_old_timespec_t ts;
34 uint32_t pad[2];
35 } req = {
36 .ts.tv_nsec = 0xc0de1,
37 .pad = { 0xdeadbeef, 0xbadc0ded }
38 }, rem = {
39 .ts = { .tv_sec = 0xc0de2, .tv_nsec = 0xc0de3 },
40 .pad = { 0xdeadbeef, 0xbadc0ded }
41 };
42 const sigset_t set = {};
43 const struct sigaction act = { .sa_handler = handler };
44 const struct itimerval itv = {
45 .it_interval.tv_usec = 222222,
46 .it_value.tv_usec = 111111
47 };
48
49 if (syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0, &req.ts, NULL))
50 perror_msg_and_skip("clock_nanosleep CLOCK_REALTIME");
51 printf("clock_nanosleep(CLOCK_REALTIME, 0"
52 ", {tv_sec=%lld, tv_nsec=%llu}, NULL) = 0\n",
53 (long long) req.ts.tv_sec,
54 zero_extend_signed_to_ull(req.ts.tv_nsec));
55
56 assert(syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0,
57 NULL, &rem.ts) == -1);
58 printf("clock_nanosleep(CLOCK_REALTIME, 0, NULL, %p)"
59 " = -1 EFAULT (%m)\n", &rem.ts);
60
61 assert(syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0,
62 &req.ts, &rem.ts) == 0);
63 printf("clock_nanosleep(CLOCK_REALTIME, 0"
64 ", {tv_sec=%lld, tv_nsec=%llu}, %p) = 0\n",
65 (long long) req.ts.tv_sec,
66 zero_extend_signed_to_ull(req.ts.tv_nsec), &rem.ts);
67
68 req.ts.tv_nsec = 999999999 + 1;
69 assert(syscall(__NR_clock_nanosleep, CLOCK_MONOTONIC, 0,
70 &req.ts, &rem.ts) == -1);
71 printf("clock_nanosleep(CLOCK_MONOTONIC, 0"
72 ", {tv_sec=%lld, tv_nsec=%llu}, %p) = -1 EINVAL (%m)\n",
73 (long long) req.ts.tv_sec,
74 zero_extend_signed_to_ull(req.ts.tv_nsec), &rem.ts);
75
76 req.ts.tv_sec = 0xdeadbeefU;
77 req.ts.tv_nsec = 0xfacefeedU;
78 assert(syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0,
79 &req.ts, &rem.ts) == -1);
80 printf("clock_nanosleep(CLOCK_REALTIME, 0"
81 ", {tv_sec=%lld, tv_nsec=%llu}, %p) = -1 EINVAL (%m)\n",
82 (long long) req.ts.tv_sec,
83 zero_extend_signed_to_ull(req.ts.tv_nsec), &rem.ts);
84
85 req.ts.tv_sec = (typeof(req.ts.tv_sec)) 0xcafef00ddeadbeefLL;
86 req.ts.tv_nsec = (long) 0xbadc0dedfacefeedLL;
87 assert(syscall(__NR_clock_nanosleep, CLOCK_MONOTONIC, 0,
88 &req.ts, &rem.ts) == -1);
89 printf("clock_nanosleep(CLOCK_MONOTONIC, 0"
90 ", {tv_sec=%lld, tv_nsec=%llu}, %p) = -1 EINVAL (%m)\n",
91 (long long) req.ts.tv_sec,
92 zero_extend_signed_to_ull(req.ts.tv_nsec), &rem.ts);
93
94 assert(sigaction(SIGALRM, &act, NULL) == 0);
95 assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0);
96
97 if (setitimer(ITIMER_REAL, &itv, NULL))
98 perror_msg_and_skip("setitimer");
99
100 req.ts.tv_sec = 0;
101 req.ts.tv_nsec = 999999999;
102 assert(syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0,
103 &req.ts, &rem.ts) == -1);
104 printf("clock_nanosleep(CLOCK_REALTIME, 0"
105 ", {tv_sec=%lld, tv_nsec=%llu}, {tv_sec=%lld, tv_nsec=%llu})"
106 " = ? ERESTART_RESTARTBLOCK (Interrupted by signal)\n",
107 (long long) req.ts.tv_sec,
108 zero_extend_signed_to_ull(req.ts.tv_nsec),
109 (long long) rem.ts.tv_sec,
110 zero_extend_signed_to_ull(rem.ts.tv_nsec));
111 puts("--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---");
112
113 assert(syscall(__NR_clock_gettime, CLOCK_REALTIME, &req.ts) == 0);
114 printf("clock_gettime(CLOCK_REALTIME, {tv_sec=%lld, tv_nsec=%llu}) = 0\n",
115 (long long) req.ts.tv_sec,
116 zero_extend_signed_to_ull(req.ts.tv_nsec));
117
118 /* If time_t is 32 bit, it is no longer possible to represent post-2038 times
119 * via the clock_nanosleep syscall so we should simply stop and exit.
120 * It is not a failure. */
121 if (sizeof(req.ts.tv_sec) < 8)
122 goto exit;
123
124 ++req.ts.tv_sec;
125 rem.ts.tv_sec = 0xc0de4;
126 rem.ts.tv_nsec = 0xc0de5;
127 assert(syscall(__NR_clock_nanosleep, CLOCK_REALTIME, TIMER_ABSTIME,
128 &req.ts, &rem.ts) == -1);
129 printf("clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME"
130 ", {tv_sec=%lld, tv_nsec=%llu}, %p)"
131 " = ? ERESTARTNOHAND (To be restarted if no handler)\n",
132 (long long) req.ts.tv_sec,
133 zero_extend_signed_to_ull(req.ts.tv_nsec), &rem.ts);
134 puts("--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---");
135
136 exit:
137 puts("+++ exited with 0 +++");
138 return 0;
139 }
140
141 #else
142
143 SKIP_MAIN_UNDEFINED("__NR_clock_nanosleep")
144
145 #endif