1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-2018 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "defs.h"
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <sys/timex.h>
35 
36 static void
print_timezone(struct tcb * const tcp,const kernel_ulong_t addr)37 print_timezone(struct tcb *const tcp, const kernel_ulong_t addr)
38 {
39 	struct timezone tz;
40 
41 	if (umove_or_printaddr(tcp, addr, &tz))
42 		return;
43 
44 	tprintf("{tz_minuteswest=%d, tz_dsttime=%d}",
45 		tz.tz_minuteswest, tz.tz_dsttime);
46 }
47 
SYS_FUNC(gettimeofday)48 SYS_FUNC(gettimeofday)
49 {
50 	if (exiting(tcp)) {
51 		print_timeval(tcp, tcp->u_arg[0]);
52 		tprints(", ");
53 		print_timezone(tcp, tcp->u_arg[1]);
54 	}
55 	return 0;
56 }
57 
58 #ifdef ALPHA
SYS_FUNC(osf_gettimeofday)59 SYS_FUNC(osf_gettimeofday)
60 {
61 	if (exiting(tcp)) {
62 		print_timeval32(tcp, tcp->u_arg[0]);
63 		tprints(", ");
64 		print_timezone(tcp, tcp->u_arg[1]);
65 	}
66 	return 0;
67 }
68 #endif
69 
SYS_FUNC(settimeofday)70 SYS_FUNC(settimeofday)
71 {
72 	print_timeval(tcp, tcp->u_arg[0]);
73 	tprints(", ");
74 	print_timezone(tcp, tcp->u_arg[1]);
75 
76 	return RVAL_DECODED;
77 }
78 
79 #ifdef ALPHA
SYS_FUNC(osf_settimeofday)80 SYS_FUNC(osf_settimeofday)
81 {
82 	print_timeval32(tcp, tcp->u_arg[0]);
83 	tprints(", ");
84 	print_timezone(tcp, tcp->u_arg[1]);
85 
86 	return RVAL_DECODED;
87 }
88 #endif
89 
SYS_FUNC(nanosleep)90 SYS_FUNC(nanosleep)
91 {
92 	if (entering(tcp)) {
93 		print_timespec(tcp, tcp->u_arg[0]);
94 		tprints(", ");
95 	} else {
96 
97 		/*
98 		 * Second (returned) timespec is only significant if syscall
99 		 * was interrupted.  On success and in case of other errors we
100 		 * print only its address, since kernel doesn't modify it,
101 		 * and printing the value may show uninitialized data.
102 		 */
103 		if (is_erestart(tcp)) {
104 			temporarily_clear_syserror(tcp);
105 			print_timespec(tcp, tcp->u_arg[1]);
106 			restore_cleared_syserror(tcp);
107 		} else {
108 			printaddr(tcp->u_arg[1]);
109 		}
110 	}
111 	return 0;
112 }
113 
114 #include "xlat/itimer_which.h"
115 
SYS_FUNC(getitimer)116 SYS_FUNC(getitimer)
117 {
118 	if (entering(tcp)) {
119 		printxval_index(itimer_which, (unsigned int) tcp->u_arg[0],
120 				"ITIMER_???");
121 		tprints(", ");
122 	} else {
123 		print_itimerval(tcp, tcp->u_arg[1]);
124 	}
125 	return 0;
126 }
127 
128 #ifdef ALPHA
SYS_FUNC(osf_getitimer)129 SYS_FUNC(osf_getitimer)
130 {
131 	if (entering(tcp)) {
132 		printxval_index(itimer_which, (unsigned int) tcp->u_arg[0],
133 				"ITIMER_???");
134 		tprints(", ");
135 	} else {
136 		print_itimerval32(tcp, tcp->u_arg[1]);
137 	}
138 	return 0;
139 }
140 #endif
141 
SYS_FUNC(setitimer)142 SYS_FUNC(setitimer)
143 {
144 	if (entering(tcp)) {
145 		printxval_index(itimer_which, (unsigned int) tcp->u_arg[0],
146 				"ITIMER_???");
147 		tprints(", ");
148 		print_itimerval(tcp, tcp->u_arg[1]);
149 		tprints(", ");
150 	} else {
151 		print_itimerval(tcp, tcp->u_arg[2]);
152 	}
153 	return 0;
154 }
155 
156 #ifdef ALPHA
SYS_FUNC(osf_setitimer)157 SYS_FUNC(osf_setitimer)
158 {
159 	if (entering(tcp)) {
160 		printxval_index(itimer_which, (unsigned int) tcp->u_arg[0],
161 				"ITIMER_???");
162 		tprints(", ");
163 		print_itimerval32(tcp, tcp->u_arg[1]);
164 		tprints(", ");
165 	} else {
166 		print_itimerval32(tcp, tcp->u_arg[2]);
167 	}
168 	return 0;
169 }
170 #endif
171 
172 #include "xlat/adjtimex_state.h"
173 
174 static int
do_adjtimex(struct tcb * const tcp,const kernel_ulong_t addr)175 do_adjtimex(struct tcb *const tcp, const kernel_ulong_t addr)
176 {
177 	if (print_timex(tcp, addr))
178 		return 0;
179 	tcp->auxstr = xlat_idx(adjtimex_state, ARRAY_SIZE(adjtimex_state) - 1,
180 			       (kernel_ulong_t) tcp->u_rval);
181 	return RVAL_STR;
182 }
183 
SYS_FUNC(adjtimex)184 SYS_FUNC(adjtimex)
185 {
186 	if (exiting(tcp))
187 		return do_adjtimex(tcp, tcp->u_arg[0]);
188 	return 0;
189 }
190 
191 #include "xlat/clockflags.h"
192 #include "xlat/clocknames.h"
193 
194 static void
printclockname(int clockid)195 printclockname(int clockid)
196 {
197 #ifdef CLOCKID_TO_FD
198 # include "xlat/cpuclocknames.h"
199 
200 	if (clockid < 0) {
201 		if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
202 			tprintf("%d", clockid);
203 
204 		if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
205 			return;
206 
207 		if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
208 			tprints(" /* ");
209 
210 		if ((clockid & CLOCKFD_MASK) == CLOCKFD)
211 			tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid));
212 		else {
213 			tprintf("%s(%d,",
214 				CPUCLOCK_PERTHREAD(clockid) ?
215 					"MAKE_THREAD_CPUCLOCK" :
216 					"MAKE_PROCESS_CPUCLOCK",
217 				CPUCLOCK_PID(clockid));
218 			printxval_index(cpuclocknames,
219 					(unsigned int) clockid & CLOCKFD_MASK,
220 					"CPUCLOCK_???");
221 			tprints(")");
222 		}
223 
224 		if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
225 			tprints(" */");
226 	} else
227 #endif
228 		printxval_index(clocknames, clockid, "CLOCK_???");
229 }
230 
SYS_FUNC(clock_settime)231 SYS_FUNC(clock_settime)
232 {
233 	printclockname(tcp->u_arg[0]);
234 	tprints(", ");
235 	print_timespec(tcp, tcp->u_arg[1]);
236 
237 	return RVAL_DECODED;
238 }
239 
SYS_FUNC(clock_gettime)240 SYS_FUNC(clock_gettime)
241 {
242 	if (entering(tcp)) {
243 		printclockname(tcp->u_arg[0]);
244 		tprints(", ");
245 	} else {
246 		print_timespec(tcp, tcp->u_arg[1]);
247 	}
248 	return 0;
249 }
250 
SYS_FUNC(clock_nanosleep)251 SYS_FUNC(clock_nanosleep)
252 {
253 	if (entering(tcp)) {
254 		printclockname(tcp->u_arg[0]);
255 		tprints(", ");
256 		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
257 		tprints(", ");
258 		print_timespec(tcp, tcp->u_arg[2]);
259 		tprints(", ");
260 	} else {
261 		/*
262 		 * Second (returned) timespec is only significant
263 		 * if syscall was interrupted and flags is not TIMER_ABSTIME.
264 		 */
265 		if (!tcp->u_arg[1] && is_erestart(tcp)) {
266 			temporarily_clear_syserror(tcp);
267 			print_timespec(tcp, tcp->u_arg[3]);
268 			restore_cleared_syserror(tcp);
269 		} else {
270 			printaddr(tcp->u_arg[3]);
271 		}
272 	}
273 	return 0;
274 }
275 
SYS_FUNC(clock_adjtime)276 SYS_FUNC(clock_adjtime)
277 {
278 	if (exiting(tcp))
279 		return do_adjtimex(tcp, tcp->u_arg[1]);
280 	printclockname(tcp->u_arg[0]);
281 	tprints(", ");
282 	return 0;
283 }
284 
SYS_FUNC(timer_create)285 SYS_FUNC(timer_create)
286 {
287 	if (entering(tcp)) {
288 		printclockname(tcp->u_arg[0]);
289 		tprints(", ");
290 		print_sigevent(tcp, tcp->u_arg[1]);
291 		tprints(", ");
292 	} else {
293 		printnum_int(tcp, tcp->u_arg[2], "%d");
294 	}
295 	return 0;
296 }
297 
SYS_FUNC(timer_settime)298 SYS_FUNC(timer_settime)
299 {
300 	if (entering(tcp)) {
301 		tprintf("%d, ", (int) tcp->u_arg[0]);
302 		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
303 		tprints(", ");
304 		print_itimerspec(tcp, tcp->u_arg[2]);
305 		tprints(", ");
306 	} else {
307 		print_itimerspec(tcp, tcp->u_arg[3]);
308 	}
309 	return 0;
310 }
311 
SYS_FUNC(timer_gettime)312 SYS_FUNC(timer_gettime)
313 {
314 	if (entering(tcp)) {
315 		tprintf("%d, ", (int) tcp->u_arg[0]);
316 	} else {
317 		print_itimerspec(tcp, tcp->u_arg[1]);
318 	}
319 	return 0;
320 }
321 
322 #include "xlat/timerfdflags.h"
323 
SYS_FUNC(timerfd_create)324 SYS_FUNC(timerfd_create)
325 {
326 	printclockname(tcp->u_arg[0]);
327 	tprints(", ");
328 	printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
329 
330 	return RVAL_DECODED | RVAL_FD;
331 }
332 
SYS_FUNC(timerfd_settime)333 SYS_FUNC(timerfd_settime)
334 {
335 	if (entering(tcp)) {
336 		printfd(tcp, tcp->u_arg[0]);
337 		tprints(", ");
338 		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
339 		tprints(", ");
340 		print_itimerspec(tcp, tcp->u_arg[2]);
341 		tprints(", ");
342 	} else {
343 		print_itimerspec(tcp, tcp->u_arg[3]);
344 	}
345 	return 0;
346 }
347 
SYS_FUNC(timerfd_gettime)348 SYS_FUNC(timerfd_gettime)
349 {
350 	if (entering(tcp)) {
351 		printfd(tcp, tcp->u_arg[0]);
352 		tprints(", ");
353 	} else {
354 		print_itimerspec(tcp, tcp->u_arg[1]);
355 	}
356 	return 0;
357 }
358