1 /*	$NetBSD: linux32_time.c,v 1.40 2021/09/19 23:51:37 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Emmanuel Dreyfus
17  * 4. The name of the author may not be used to endorse or promote
18  *    products derived from this software without specific prior written
19  *    permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 
36 __KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.40 2021/09/19 23:51:37 thorpej Exp $");
37 
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/fstypes.h>
41 #include <sys/signal.h>
42 #include <sys/dirent.h>
43 #include <sys/kauth.h>
44 #include <sys/kernel.h>
45 #include <sys/fcntl.h>
46 #include <sys/namei.h>
47 #include <sys/select.h>
48 #include <sys/timerfd.h>
49 #include <sys/proc.h>
50 #include <sys/resourcevar.h>
51 #include <sys/ucred.h>
52 #include <sys/swap.h>
53 #include <sys/vfs_syscalls.h>
54 
55 #include <machine/types.h>
56 
57 #include <sys/syscallargs.h>
58 
59 #include <compat/netbsd32/netbsd32.h>
60 #include <compat/netbsd32/netbsd32_conv.h>
61 #include <compat/netbsd32/netbsd32_syscallargs.h>
62 
63 #include <compat/linux/common/linux_types.h>
64 #include <compat/linux/common/linux_signal.h>
65 #include <compat/linux/common/linux_machdep.h>
66 #include <compat/linux/common/linux_misc.h>
67 #include <compat/linux/common/linux_oldolduname.h>
68 #include <compat/linux/common/linux_sched.h>
69 #include <compat/linux/common/linux_ipc.h>
70 #include <compat/linux/common/linux_sem.h>
71 #include <compat/linux/linux_syscallargs.h>
72 
73 #include <compat/linux32/common/linux32_types.h>
74 #include <compat/linux32/common/linux32_signal.h>
75 #include <compat/linux32/common/linux32_machdep.h>
76 #include <compat/linux32/common/linux32_sysctl.h>
77 #include <compat/linux32/common/linux32_socketcall.h>
78 #include <compat/linux32/common/linux32_sched.h>
79 #include <compat/linux32/linux32_syscallargs.h>
80 
81 CTASSERT(LINUX_TIMER_ABSTIME == TIMER_ABSTIME);
82 
83 extern struct timezone linux_sys_tz;
84 
85 int
linux32_sys_gettimeofday(struct lwp * l,const struct linux32_sys_gettimeofday_args * uap,register_t * retval)86 linux32_sys_gettimeofday(struct lwp *l, const struct linux32_sys_gettimeofday_args *uap, register_t *retval)
87 {
88 	/* {
89 		syscallarg(netbsd32_timeval50p_t) tp;
90 		syscallarg(netbsd32_timezonep_t) tzp;
91 	} */
92 	struct timeval tv;
93 	struct netbsd32_timeval50 tv32;
94 	int error;
95 
96 	if (SCARG_P32(uap, tp) != NULL) {
97 		microtime(&tv);
98 		netbsd32_from_timeval50(&tv, &tv32);
99 		if ((error = copyout(&tv32, SCARG_P32(uap, tp),
100 		    sizeof(tv32))) != 0)
101 			return error;
102 	}
103 
104 	/* timezone size does not change */
105 	if (SCARG_P32(uap, tzp) != NULL) {
106 		if ((error = copyout(&linux_sys_tz, SCARG_P32(uap, tzp),
107 		    sizeof(linux_sys_tz))) != 0)
108 			return error;
109 	}
110 
111 	return 0;
112 }
113 
114 int
linux32_sys_settimeofday(struct lwp * l,const struct linux32_sys_settimeofday_args * uap,register_t * retval)115 linux32_sys_settimeofday(struct lwp *l, const struct linux32_sys_settimeofday_args *uap, register_t *retval)
116 {
117 	/* {
118 		syscallarg(netbsd32_timeval50p_t) tp;
119 		syscallarg(netbsd32_timezonep_t) tzp;
120 	} */
121 	struct linux_sys_settimeofday_args ua;
122 
123 	NETBSD32TOP_UAP(tp, struct timeval50);
124 	NETBSD32TOP_UAP(tzp, struct timezone);
125 
126 	return linux_sys_settimeofday(l, &ua, retval);
127 }
128 
129 int
linux32_sys_time(struct lwp * l,const struct linux32_sys_time_args * uap,register_t * retval)130 linux32_sys_time(struct lwp *l, const struct linux32_sys_time_args *uap, register_t *retval)
131 {
132 	/* {
133 		syscallarg(linux32_timep_t) t;
134 	} */
135         struct timeval atv;
136         linux32_time_t tt;
137         int error;
138 
139         microtime(&atv);
140 
141         tt = (linux32_time_t)atv.tv_sec;
142 
143         if (SCARG_P32(uap, t) && (error = copyout(&tt,
144 	    SCARG_P32(uap, t), sizeof(tt))))
145                 return error;
146 
147         retval[0] = tt;
148 
149         return 0;
150 }
151 
152 
153 #define	CONVTCK(r)	(r.tv_sec * hz + r.tv_usec / (1000000 / hz))
154 
155 int
linux32_sys_times(struct lwp * l,const struct linux32_sys_times_args * uap,register_t * retval)156 linux32_sys_times(struct lwp *l, const struct linux32_sys_times_args *uap, register_t *retval)
157 {
158 	/* {
159 		syscallarg(linux32_tmsp_t) tms;
160 	} */
161 	struct proc *p = l->l_proc;
162 	struct timeval t;
163 	int error;
164 
165 	if (SCARG_P32(uap, tms)) {
166 		struct linux32_tms ltms32;
167 		struct rusage ru;
168 
169 		memset(&ltms32, 0, sizeof(ltms32));
170 
171 		mutex_enter(p->p_lock);
172 		calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
173 		ltms32.ltms32_utime = CONVTCK(ru.ru_utime);
174 		ltms32.ltms32_stime = CONVTCK(ru.ru_stime);
175 		ltms32.ltms32_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
176 		ltms32.ltms32_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
177 		mutex_exit(p->p_lock);
178 
179 		error = copyout(&ltms32, SCARG_P32(uap, tms), sizeof(ltms32));
180 		if (error)
181 			return error;
182 	}
183 
184 	getmicrouptime(&t);
185 
186 	retval[0] = ((linux32_clock_t)(CONVTCK(t)));
187 	return 0;
188 }
189 
190 #undef CONVTCK
191 
192 int
linux32_sys_stime(struct lwp * l,const struct linux32_sys_stime_args * uap,register_t * retval)193 linux32_sys_stime(struct lwp *l, const struct linux32_sys_stime_args *uap, register_t *retval)
194 {
195 	/* {
196 		syscallarg(linux32_timep_t) t;
197 	} */
198 	struct timespec ts;
199 	linux32_time_t tt32;
200 	int error;
201 
202 	if ((error = copyin(SCARG_P32(uap, t), &tt32, sizeof tt32)) != 0)
203 		return error;
204 
205 	ts.tv_sec = (long)tt32;
206 	ts.tv_nsec = 0;
207 
208 	return settime(l->l_proc, &ts);
209 }
210 
211 int
linux32_sys_utime(struct lwp * l,const struct linux32_sys_utime_args * uap,register_t * retval)212 linux32_sys_utime(struct lwp *l, const struct linux32_sys_utime_args *uap, register_t *retval)
213 {
214 	/* {
215 		syscallarg(const netbsd32_charp) path;
216 		syscallarg(linux32_utimbufp_t) times;
217 	} */
218         struct timeval tv[2], *tvp;
219         struct linux32_utimbuf lut;
220         int error;
221 
222         if (SCARG_P32(uap, times) != NULL) {
223                 if ((error = copyin(SCARG_P32(uap, times), &lut, sizeof lut)))
224                         return error;
225 
226                 tv[0].tv_sec = (long)lut.l_actime;
227                 tv[0].tv_usec = 0;
228                 tv[1].tv_sec = (long)lut.l_modtime;
229 		tv[1].tv_usec = 0;
230                 tvp = tv;
231         } else {
232 		tvp = NULL;
233 	}
234 
235         return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
236 			    tvp, UIO_SYSSPACE);
237 }
238 
239 void
native_to_linux32_timespec(struct linux32_timespec * ltp,const struct timespec * ntp)240 native_to_linux32_timespec(struct linux32_timespec *ltp,
241     const struct timespec *ntp)
242 {
243 
244 	memset(ltp, 0, sizeof(*ltp));
245 	ltp->tv_sec = ntp->tv_sec;
246 	ltp->tv_nsec = ntp->tv_nsec;
247 }
248 
249 void
linux32_to_native_timespec(struct timespec * ntp,const struct linux32_timespec * ltp)250 linux32_to_native_timespec(struct timespec *ntp,
251     const struct linux32_timespec *ltp)
252 {
253 
254 	memset(ntp, 0, sizeof(*ntp));
255 	ntp->tv_sec = ltp->tv_sec;
256 	ntp->tv_nsec = ltp->tv_nsec;
257 }
258 
259 void
native_to_linux32_itimerspec(struct linux32_itimerspec * litp,const struct itimerspec * nitp)260 native_to_linux32_itimerspec(struct linux32_itimerspec *litp,
261     const struct itimerspec *nitp)
262 {
263 	memset(litp, 0, sizeof(*litp));
264 	native_to_linux32_timespec(&litp->it_interval, &nitp->it_interval);
265 	native_to_linux32_timespec(&litp->it_value, &nitp->it_value);
266 }
267 
268 void
linux32_to_native_itimerspec(struct itimerspec * nitp,const struct linux32_itimerspec * litp)269 linux32_to_native_itimerspec(struct itimerspec *nitp,
270     const struct linux32_itimerspec *litp)
271 {
272 	memset(nitp, 0, sizeof(*nitp));
273 	linux32_to_native_timespec(&nitp->it_interval, &litp->it_interval);
274 	linux32_to_native_timespec(&nitp->it_value, &litp->it_value);
275 }
276 
277 int
linux32_sys_nanosleep(struct lwp * l,const struct linux32_sys_nanosleep_args * uap,register_t * retval)278 linux32_sys_nanosleep(struct lwp *l,
279     const struct linux32_sys_nanosleep_args *uap, register_t *retval)
280 {
281 	/* {
282 		syscallarg(linux32_timespecp_t) rqtp;
283 		syscallarg(linux32_timespecp_t) rmtp;
284 	} */
285 	struct timespec rqts, rmts;
286 	struct linux32_timespec lrqts, lrmts;
287 	int error, error1;
288 
289 	error = copyin(SCARG_P32(uap, rqtp), &lrqts, sizeof(lrqts));
290 	if (error != 0)
291 		return error;
292 	linux32_to_native_timespec(&rqts, &lrqts);
293 
294 	error = nanosleep1(l, CLOCK_MONOTONIC, 0, &rqts,
295 	    SCARG_P32(uap, rmtp) ? &rmts : NULL);
296 	if (SCARG_P32(uap, rmtp) == NULL || (error != 0 && error != EINTR))
297 		return error;
298 
299 	native_to_linux32_timespec(&lrmts, &rmts);
300 	error1 = copyout(&lrmts, SCARG_P32(uap, rmtp), sizeof(lrmts));
301 	return error1 ? error1 : error;
302 }
303 
304 int
linux32_sys_clock_settime(struct lwp * l,const struct linux32_sys_clock_settime_args * uap,register_t * retval)305 linux32_sys_clock_settime(struct lwp *l,
306     const struct linux32_sys_clock_settime_args *uap, register_t *retval)
307 {
308 	/* {
309 		syscallarg(clockid_t) which;
310 		syscallarg(linux32_timespecp_t) tp;
311 	} */
312 	int error;
313 	struct timespec ts;
314 	struct linux32_timespec lts;
315 	clockid_t id;
316 
317 	error = linux_to_native_clockid(&id, SCARG(uap, which));
318 	if (error != 0)
319 		return error;
320 
321 	if ((error = copyin(SCARG_P32(uap, tp), &lts, sizeof lts)))
322 		return error;
323 
324 	linux32_to_native_timespec(&ts, &lts);
325 	return clock_settime1(l->l_proc, id, &ts, true);
326 }
327 
328 int
linux32_sys_clock_gettime(struct lwp * l,const struct linux32_sys_clock_gettime_args * uap,register_t * retval)329 linux32_sys_clock_gettime(struct lwp *l,
330     const struct linux32_sys_clock_gettime_args *uap, register_t *retval)
331 {
332 	/* {
333 		syscallarg(clockid_t) which;
334 		syscallarg(linux32_timespecp_t) tp;
335 	} */
336 	int error;
337 	clockid_t id;
338 	struct timespec ts;
339 	struct linux32_timespec lts;
340 
341 	error = linux_to_native_clockid(&id, SCARG(uap, which));
342 	if (error != 0)
343 		return error;
344 
345 	error = clock_gettime1(id, &ts);
346 	if (error != 0)
347 		return error;
348 
349 	native_to_linux32_timespec(&lts, &ts);
350 	return copyout(&lts, SCARG_P32(uap, tp), sizeof lts);
351 }
352 
353 int
linux32_sys_clock_getres(struct lwp * l,const struct linux32_sys_clock_getres_args * uap,register_t * retval)354 linux32_sys_clock_getres(struct lwp *l,
355     const struct linux32_sys_clock_getres_args *uap, register_t *retval)
356 {
357 	/* {
358 		syscallarg(clockid_t) which;
359 		syscallarg(linux32_timespecp_t) tp;
360 	} */
361 	int error;
362 	clockid_t id;
363 	struct timespec ts;
364 	struct linux32_timespec lts;
365 
366 	error = linux_to_native_clockid(&id, SCARG(uap, which));
367 	if (error != 0 || SCARG_P32(uap, tp) == NULL)
368 		return error;
369 
370 	error = clock_getres1(id, &ts);
371 	if (error != 0)
372 		return error;
373 
374 	native_to_linux32_timespec(&lts, &ts);
375 	return copyout(&lts, SCARG_P32(uap, tp), sizeof lts);
376 }
377 
378 int
linux32_sys_clock_nanosleep(struct lwp * l,const struct linux32_sys_clock_nanosleep_args * uap,register_t * retval)379 linux32_sys_clock_nanosleep(struct lwp *l,
380     const struct linux32_sys_clock_nanosleep_args *uap, register_t *retval)
381 {
382 	/* {
383 		syscallarg(clockid_t) which;
384 		syscallarg(int) flags;
385 		syscallarg(linux32_timespecp_t) rqtp;
386 		syscallarg(linux32_timespecp_t) rmtp;
387 	} */
388 	struct linux32_timespec lrqts, lrmts;
389 	struct timespec rqts, rmts;
390 	int error, error1, flags;
391 	clockid_t id;
392 
393 	flags = SCARG(uap, flags) != 0 ? TIMER_ABSTIME : 0;
394 
395 	error = linux_to_native_clockid(&id, SCARG(uap, which));
396 	if (error != 0)
397 		return error;
398 
399 	error = copyin(SCARG_P32(uap, rqtp), &lrqts, sizeof lrqts);
400 	if (error != 0)
401 		return error;
402 	linux32_to_native_timespec(&rqts, &lrqts);
403 
404 	error = nanosleep1(l, id, flags, &rqts,
405 	    SCARG_P32(uap, rmtp) ? &rmts : NULL);
406 	if (SCARG_P32(uap, rmtp) == NULL || (error != 0 && error != EINTR))
407 		return error;
408 
409 	native_to_linux32_timespec(&lrmts, &rmts);
410 	error1 = copyout(&lrmts, SCARG_P32(uap, rmtp), sizeof lrmts);
411 	return error1 ? error1 : error;
412 }
413 
414 int
linux32_sys_timer_create(struct lwp * l,const struct linux32_sys_timer_create_args * uap,register_t * retval)415 linux32_sys_timer_create(struct lwp *l,
416     const struct linux32_sys_timer_create_args *uap, register_t *retval)
417 {
418 	/* {
419 		syscallarg(clockid_t) clockid;
420 		syscallarg(struct linux32_sigevent *) evp;
421 		syscallarg(timer_t *) timerid;
422 	} */
423 	clockid_t id;
424 	int error;
425 
426 	error = linux_to_native_timer_create_clockid(&id, SCARG(uap, clockid));
427 	if (error == 0) {
428 		error = timer_create1(SCARG(uap, timerid), id,
429 		    (void *)SCARG(uap, evp), linux32_sigevent_copyin, l);
430 	}
431 
432 	return error;
433 }
434 
435 int
linux32_sys_timer_settime(struct lwp * l,const struct linux32_sys_timer_settime_args * uap,register_t * retval)436 linux32_sys_timer_settime(struct lwp *l,
437     const struct linux32_sys_timer_settime_args *uap, register_t *retval)
438 {
439 	/* {
440 		syscallarg(timer_t) timerid;
441 		syscallarg(int) flags;
442 		syscallarg(const struct linux32_itimerspec *) tim;
443 		syscallarg(struct linux32_itimerspec *) otim;
444 	} */
445 	struct itimerspec value, ovalue, *ovp = NULL;
446 	struct linux32_itimerspec tim, otim;
447 	int error;
448 
449 	error = copyin(SCARG(uap, tim), &tim, sizeof(tim));
450 	if (error) {
451 		return error;
452 	}
453 	linux32_to_native_itimerspec(&value, &tim);
454 
455 	if (SCARG(uap, otim)) {
456 		ovp = &ovalue;
457 	}
458 
459 	if (SCARG(uap, flags) & ~TIMER_ABSTIME) {
460 		return EINVAL;
461 	}
462 
463 	error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
464 	    SCARG(uap, flags), l->l_proc);
465 	if (error) {
466 		return error;
467 	}
468 
469 	if (ovp) {
470 		native_to_linux32_itimerspec(&otim, ovp);
471 		error = copyout(&otim, SCARG(uap, otim), sizeof(otim));
472 	}
473 
474 	return error;
475 }
476 
477 int
linux32_sys_timer_gettime(struct lwp * l,const struct linux32_sys_timer_gettime_args * uap,register_t * retval)478 linux32_sys_timer_gettime(struct lwp *l,
479     const struct linux32_sys_timer_gettime_args *uap, register_t *retval)
480 {
481 	/* {
482 		syscallarg(timer_t) timerid;
483 		syscallarg(struct linux32_itimerspec *) tim;
484 	} */
485 	struct itimerspec its;
486 	struct linux32_itimerspec lits;
487 	int error;
488 
489 	error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, &its);
490 	if (error == 0) {
491 		native_to_linux32_itimerspec(&lits, &its);
492 		error = copyout(&lits, SCARG(uap, tim), sizeof(lits));
493 	}
494 
495 	return error;
496 }
497 
498 /*
499  * timer_gettoverrun(2) and timer_delete(2) are handled directly
500  * by the native calls.
501  */
502 
503 /*
504  * timerfd_create() is handled by the standard COMPAT_LINUX call.
505  */
506 
507 int
linux32_sys_timerfd_gettime(struct lwp * l,const struct linux32_sys_timerfd_gettime_args * uap,register_t * retval)508 linux32_sys_timerfd_gettime(struct lwp *l,
509     const struct linux32_sys_timerfd_gettime_args *uap, register_t *retval)
510 {
511 	/* {
512 		syscallarg(int) fd;
513 		syscallarg(struct linux32_itimerspec *) tim;
514 	} */
515 	struct itimerspec its;
516 	struct linux32_itimerspec lits;
517 	int error;
518 
519 	error = do_timerfd_gettime(l, SCARG(uap, fd), &its, retval);
520 	if (error == 0) {
521 		native_to_linux32_itimerspec(&lits, &its);
522 		error = copyout(&lits, SCARG(uap, tim), sizeof(lits));
523 	}
524 
525 	return error;
526 }
527 
528 int
linux32_sys_timerfd_settime(struct lwp * l,const struct linux32_sys_timerfd_settime_args * uap,register_t * retval)529 linux32_sys_timerfd_settime(struct lwp *l,
530     const struct linux32_sys_timerfd_settime_args *uap, register_t *retval)
531 {
532 	/* {
533 		syscallarg(int) fd;
534 		syscallarg(int) flags;
535 		syscallarg(const struct linux32_itimerspec *) tim;
536 		syscallarg(struct linux32_itimerspec *) otim;
537 	} */
538 	struct itimerspec nits, oits, *oitsp = NULL;
539 	struct linux32_itimerspec lits;
540 	int nflags;
541 	int error;
542 
543 	error = copyin(SCARG(uap, tim), &lits, sizeof(lits));
544 	if (error) {
545 		return error;
546 	}
547 	linux32_to_native_itimerspec(&nits, &lits);
548 
549 	error = linux_to_native_timerfd_settime_flags(&nflags,
550 	    SCARG(uap, flags));
551 	if (error) {
552 		return error;
553 	}
554 
555 	if (SCARG(uap, otim)) {
556 		oitsp = &oits;
557 	}
558 
559 	error = do_timerfd_settime(l, SCARG(uap, fd), nflags,
560 	    &nits, oitsp, retval);
561 	if (error == 0 && oitsp != NULL) {
562 		native_to_linux32_itimerspec(&lits, oitsp);
563 		error = copyout(&lits, SCARG(uap, otim), sizeof(lits));
564 	}
565 
566 	return error;
567 }
568