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 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 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 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 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(<ms32, 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(<ms32, 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 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 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 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 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 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 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 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 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), <s, sizeof lts))) 322 return error; 323 324 linux32_to_native_timespec(&ts, <s); 325 return clock_settime1(l->l_proc, id, &ts, true); 326 } 327 328 int 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(<s, &ts); 350 return copyout(<s, SCARG_P32(uap, tp), sizeof lts); 351 } 352 353 int 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(<s, &ts); 375 return copyout(<s, SCARG_P32(uap, tp), sizeof lts); 376 } 377 378 int 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 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 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 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 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 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