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