1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2004 Tim J. Robbins 5 * Copyright (c) 2002 Doug Rabson 6 * Copyright (c) 2000 Marcel Moolenaar 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer 14 * in this position and unchanged. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include "opt_compat.h" 37 38 #include <sys/param.h> 39 #include <sys/capsicum.h> 40 #include <sys/clock.h> 41 #include <sys/fcntl.h> 42 #include <sys/file.h> 43 #include <sys/imgact.h> 44 #include <sys/kernel.h> 45 #include <sys/limits.h> 46 #include <sys/lock.h> 47 #include <sys/malloc.h> 48 #include <sys/mman.h> 49 #include <sys/mutex.h> 50 #include <sys/priv.h> 51 #include <sys/proc.h> 52 #include <sys/resource.h> 53 #include <sys/resourcevar.h> 54 #include <sys/syscallsubr.h> 55 #include <sys/sysproto.h> 56 #include <sys/systm.h> 57 #include <sys/unistd.h> 58 #include <sys/wait.h> 59 60 #include <machine/frame.h> 61 #include <machine/md_var.h> 62 #include <machine/pcb.h> 63 #include <machine/psl.h> 64 #include <machine/segments.h> 65 #include <machine/specialreg.h> 66 #include <x86/ifunc.h> 67 68 #include <vm/pmap.h> 69 #include <vm/vm.h> 70 #include <vm/vm_map.h> 71 72 #include <compat/freebsd32/freebsd32_util.h> 73 #include <amd64/linux32/linux.h> 74 #include <amd64/linux32/linux32_proto.h> 75 #include <compat/linux/linux_emul.h> 76 #include <compat/linux/linux_ipc.h> 77 #include <compat/linux/linux_misc.h> 78 #include <compat/linux/linux_mmap.h> 79 #include <compat/linux/linux_signal.h> 80 #include <compat/linux/linux_util.h> 81 82 static void bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru); 83 84 struct l_old_select_argv { 85 l_int nfds; 86 l_uintptr_t readfds; 87 l_uintptr_t writefds; 88 l_uintptr_t exceptfds; 89 l_uintptr_t timeout; 90 } __packed; 91 92 93 static void 94 bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru) 95 { 96 97 lru->ru_utime.tv_sec = ru->ru_utime.tv_sec; 98 lru->ru_utime.tv_usec = ru->ru_utime.tv_usec; 99 lru->ru_stime.tv_sec = ru->ru_stime.tv_sec; 100 lru->ru_stime.tv_usec = ru->ru_stime.tv_usec; 101 lru->ru_maxrss = ru->ru_maxrss; 102 lru->ru_ixrss = ru->ru_ixrss; 103 lru->ru_idrss = ru->ru_idrss; 104 lru->ru_isrss = ru->ru_isrss; 105 lru->ru_minflt = ru->ru_minflt; 106 lru->ru_majflt = ru->ru_majflt; 107 lru->ru_nswap = ru->ru_nswap; 108 lru->ru_inblock = ru->ru_inblock; 109 lru->ru_oublock = ru->ru_oublock; 110 lru->ru_msgsnd = ru->ru_msgsnd; 111 lru->ru_msgrcv = ru->ru_msgrcv; 112 lru->ru_nsignals = ru->ru_nsignals; 113 lru->ru_nvcsw = ru->ru_nvcsw; 114 lru->ru_nivcsw = ru->ru_nivcsw; 115 } 116 117 int 118 linux_copyout_rusage(struct rusage *ru, void *uaddr) 119 { 120 struct l_rusage lru; 121 122 bsd_to_linux_rusage(ru, &lru); 123 124 return (copyout(&lru, uaddr, sizeof(struct l_rusage))); 125 } 126 127 int 128 linux_execve(struct thread *td, struct linux_execve_args *args) 129 { 130 struct image_args eargs; 131 char *path; 132 int error; 133 134 LCONVPATHEXIST(td, args->path, &path); 135 136 #ifdef DEBUG 137 if (ldebug(execve)) 138 printf(ARGS(execve, "%s"), path); 139 #endif 140 141 error = freebsd32_exec_copyin_args(&eargs, path, UIO_SYSSPACE, 142 args->argp, args->envp); 143 free(path, M_TEMP); 144 if (error == 0) 145 error = linux_common_execve(td, &eargs); 146 return (error); 147 } 148 149 CTASSERT(sizeof(struct l_iovec32) == 8); 150 151 int 152 linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop) 153 { 154 struct l_iovec32 iov32; 155 struct iovec *iov; 156 struct uio *uio; 157 uint32_t iovlen; 158 int error, i; 159 160 *uiop = NULL; 161 if (iovcnt > UIO_MAXIOV) 162 return (EINVAL); 163 iovlen = iovcnt * sizeof(struct iovec); 164 uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK); 165 iov = (struct iovec *)(uio + 1); 166 for (i = 0; i < iovcnt; i++) { 167 error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32)); 168 if (error) { 169 free(uio, M_IOV); 170 return (error); 171 } 172 iov[i].iov_base = PTRIN(iov32.iov_base); 173 iov[i].iov_len = iov32.iov_len; 174 } 175 uio->uio_iov = iov; 176 uio->uio_iovcnt = iovcnt; 177 uio->uio_segflg = UIO_USERSPACE; 178 uio->uio_offset = -1; 179 uio->uio_resid = 0; 180 for (i = 0; i < iovcnt; i++) { 181 if (iov->iov_len > INT_MAX - uio->uio_resid) { 182 free(uio, M_IOV); 183 return (EINVAL); 184 } 185 uio->uio_resid += iov->iov_len; 186 iov++; 187 } 188 *uiop = uio; 189 return (0); 190 } 191 192 int 193 linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp, 194 int error) 195 { 196 struct l_iovec32 iov32; 197 struct iovec *iov; 198 uint32_t iovlen; 199 int i; 200 201 *iovp = NULL; 202 if (iovcnt > UIO_MAXIOV) 203 return (error); 204 iovlen = iovcnt * sizeof(struct iovec); 205 iov = malloc(iovlen, M_IOV, M_WAITOK); 206 for (i = 0; i < iovcnt; i++) { 207 error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32)); 208 if (error) { 209 free(iov, M_IOV); 210 return (error); 211 } 212 iov[i].iov_base = PTRIN(iov32.iov_base); 213 iov[i].iov_len = iov32.iov_len; 214 } 215 *iovp = iov; 216 return(0); 217 218 } 219 220 int 221 linux_readv(struct thread *td, struct linux_readv_args *uap) 222 { 223 struct uio *auio; 224 int error; 225 226 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 227 if (error) 228 return (error); 229 error = kern_readv(td, uap->fd, auio); 230 free(auio, M_IOV); 231 return (error); 232 } 233 234 int 235 linux_writev(struct thread *td, struct linux_writev_args *uap) 236 { 237 struct uio *auio; 238 int error; 239 240 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 241 if (error) 242 return (error); 243 error = kern_writev(td, uap->fd, auio); 244 free(auio, M_IOV); 245 return (error); 246 } 247 248 struct l_ipc_kludge { 249 l_uintptr_t msgp; 250 l_long msgtyp; 251 } __packed; 252 253 int 254 linux_ipc(struct thread *td, struct linux_ipc_args *args) 255 { 256 257 switch (args->what & 0xFFFF) { 258 case LINUX_SEMOP: { 259 struct linux_semop_args a; 260 261 a.semid = args->arg1; 262 a.tsops = PTRIN(args->ptr); 263 a.nsops = args->arg2; 264 return (linux_semop(td, &a)); 265 } 266 case LINUX_SEMGET: { 267 struct linux_semget_args a; 268 269 a.key = args->arg1; 270 a.nsems = args->arg2; 271 a.semflg = args->arg3; 272 return (linux_semget(td, &a)); 273 } 274 case LINUX_SEMCTL: { 275 struct linux_semctl_args a; 276 int error; 277 278 a.semid = args->arg1; 279 a.semnum = args->arg2; 280 a.cmd = args->arg3; 281 error = copyin(PTRIN(args->ptr), &a.arg, sizeof(a.arg)); 282 if (error) 283 return (error); 284 return (linux_semctl(td, &a)); 285 } 286 case LINUX_MSGSND: { 287 struct linux_msgsnd_args a; 288 289 a.msqid = args->arg1; 290 a.msgp = PTRIN(args->ptr); 291 a.msgsz = args->arg2; 292 a.msgflg = args->arg3; 293 return (linux_msgsnd(td, &a)); 294 } 295 case LINUX_MSGRCV: { 296 struct linux_msgrcv_args a; 297 298 a.msqid = args->arg1; 299 a.msgsz = args->arg2; 300 a.msgflg = args->arg3; 301 if ((args->what >> 16) == 0) { 302 struct l_ipc_kludge tmp; 303 int error; 304 305 if (args->ptr == 0) 306 return (EINVAL); 307 error = copyin(PTRIN(args->ptr), &tmp, sizeof(tmp)); 308 if (error) 309 return (error); 310 a.msgp = PTRIN(tmp.msgp); 311 a.msgtyp = tmp.msgtyp; 312 } else { 313 a.msgp = PTRIN(args->ptr); 314 a.msgtyp = args->arg5; 315 } 316 return (linux_msgrcv(td, &a)); 317 } 318 case LINUX_MSGGET: { 319 struct linux_msgget_args a; 320 321 a.key = args->arg1; 322 a.msgflg = args->arg2; 323 return (linux_msgget(td, &a)); 324 } 325 case LINUX_MSGCTL: { 326 struct linux_msgctl_args a; 327 328 a.msqid = args->arg1; 329 a.cmd = args->arg2; 330 a.buf = PTRIN(args->ptr); 331 return (linux_msgctl(td, &a)); 332 } 333 case LINUX_SHMAT: { 334 struct linux_shmat_args a; 335 l_uintptr_t addr; 336 int error; 337 338 a.shmid = args->arg1; 339 a.shmaddr = PTRIN(args->ptr); 340 a.shmflg = args->arg2; 341 error = linux_shmat(td, &a); 342 if (error != 0) 343 return (error); 344 addr = td->td_retval[0]; 345 error = copyout(&addr, PTRIN(args->arg3), sizeof(addr)); 346 td->td_retval[0] = 0; 347 return (error); 348 } 349 case LINUX_SHMDT: { 350 struct linux_shmdt_args a; 351 352 a.shmaddr = PTRIN(args->ptr); 353 return (linux_shmdt(td, &a)); 354 } 355 case LINUX_SHMGET: { 356 struct linux_shmget_args a; 357 358 a.key = args->arg1; 359 a.size = args->arg2; 360 a.shmflg = args->arg3; 361 return (linux_shmget(td, &a)); 362 } 363 case LINUX_SHMCTL: { 364 struct linux_shmctl_args a; 365 366 a.shmid = args->arg1; 367 a.cmd = args->arg2; 368 a.buf = PTRIN(args->ptr); 369 return (linux_shmctl(td, &a)); 370 } 371 default: 372 break; 373 } 374 375 return (EINVAL); 376 } 377 378 int 379 linux_old_select(struct thread *td, struct linux_old_select_args *args) 380 { 381 struct l_old_select_argv linux_args; 382 struct linux_select_args newsel; 383 int error; 384 385 #ifdef DEBUG 386 if (ldebug(old_select)) 387 printf(ARGS(old_select, "%p"), args->ptr); 388 #endif 389 390 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 391 if (error) 392 return (error); 393 394 newsel.nfds = linux_args.nfds; 395 newsel.readfds = PTRIN(linux_args.readfds); 396 newsel.writefds = PTRIN(linux_args.writefds); 397 newsel.exceptfds = PTRIN(linux_args.exceptfds); 398 newsel.timeout = PTRIN(linux_args.timeout); 399 return (linux_select(td, &newsel)); 400 } 401 402 int 403 linux_set_cloned_tls(struct thread *td, void *desc) 404 { 405 struct user_segment_descriptor sd; 406 struct l_user_desc info; 407 struct pcb *pcb; 408 int error; 409 int a[2]; 410 411 error = copyin(desc, &info, sizeof(struct l_user_desc)); 412 if (error) { 413 printf(LMSG("copyin failed!")); 414 } else { 415 /* We might copy out the entry_number as GUGS32_SEL. */ 416 info.entry_number = GUGS32_SEL; 417 error = copyout(&info, desc, sizeof(struct l_user_desc)); 418 if (error) 419 printf(LMSG("copyout failed!")); 420 421 a[0] = LINUX_LDT_entry_a(&info); 422 a[1] = LINUX_LDT_entry_b(&info); 423 424 memcpy(&sd, &a, sizeof(a)); 425 #ifdef DEBUG 426 if (ldebug(clone)) 427 printf("Segment created in clone with " 428 "CLONE_SETTLS: lobase: %x, hibase: %x, " 429 "lolimit: %x, hilimit: %x, type: %i, " 430 "dpl: %i, p: %i, xx: %i, long: %i, " 431 "def32: %i, gran: %i\n", sd.sd_lobase, 432 sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, 433 sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, 434 sd.sd_long, sd.sd_def32, sd.sd_gran); 435 #endif 436 pcb = td->td_pcb; 437 pcb->pcb_gsbase = (register_t)info.base_addr; 438 td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); 439 set_pcb_flags(pcb, PCB_32BIT); 440 } 441 442 return (error); 443 } 444 445 int 446 linux_set_upcall_kse(struct thread *td, register_t stack) 447 { 448 449 if (stack) 450 td->td_frame->tf_rsp = stack; 451 452 /* 453 * The newly created Linux thread returns 454 * to the user space by the same path that a parent do. 455 */ 456 td->td_frame->tf_rax = 0; 457 return (0); 458 } 459 460 int 461 linux_mmap2(struct thread *td, struct linux_mmap2_args *args) 462 { 463 464 #ifdef DEBUG 465 if (ldebug(mmap2)) 466 printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"), 467 args->addr, args->len, args->prot, 468 args->flags, args->fd, args->pgoff); 469 #endif 470 471 return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, 472 args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * 473 PAGE_SIZE)); 474 } 475 476 int 477 linux_mmap(struct thread *td, struct linux_mmap_args *args) 478 { 479 int error; 480 struct l_mmap_argv linux_args; 481 482 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 483 if (error) 484 return (error); 485 486 #ifdef DEBUG 487 if (ldebug(mmap)) 488 printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"), 489 linux_args.addr, linux_args.len, linux_args.prot, 490 linux_args.flags, linux_args.fd, linux_args.pgoff); 491 #endif 492 493 return (linux_mmap_common(td, linux_args.addr, linux_args.len, 494 linux_args.prot, linux_args.flags, linux_args.fd, 495 (uint32_t)linux_args.pgoff)); 496 } 497 498 int 499 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 500 { 501 502 return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot)); 503 } 504 505 int 506 linux_iopl(struct thread *td, struct linux_iopl_args *args) 507 { 508 int error; 509 510 if (args->level < 0 || args->level > 3) 511 return (EINVAL); 512 if ((error = priv_check(td, PRIV_IO)) != 0) 513 return (error); 514 if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 515 return (error); 516 td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | 517 (args->level * (PSL_IOPL / 3)); 518 519 return (0); 520 } 521 522 int 523 linux_sigaction(struct thread *td, struct linux_sigaction_args *args) 524 { 525 l_osigaction_t osa; 526 l_sigaction_t act, oact; 527 int error; 528 529 #ifdef DEBUG 530 if (ldebug(sigaction)) 531 printf(ARGS(sigaction, "%d, %p, %p"), 532 args->sig, (void *)args->nsa, (void *)args->osa); 533 #endif 534 535 if (args->nsa != NULL) { 536 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 537 if (error) 538 return (error); 539 act.lsa_handler = osa.lsa_handler; 540 act.lsa_flags = osa.lsa_flags; 541 act.lsa_restorer = osa.lsa_restorer; 542 LINUX_SIGEMPTYSET(act.lsa_mask); 543 act.lsa_mask.__mask = osa.lsa_mask; 544 } 545 546 error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 547 args->osa ? &oact : NULL); 548 549 if (args->osa != NULL && !error) { 550 osa.lsa_handler = oact.lsa_handler; 551 osa.lsa_flags = oact.lsa_flags; 552 osa.lsa_restorer = oact.lsa_restorer; 553 osa.lsa_mask = oact.lsa_mask.__mask; 554 error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 555 } 556 557 return (error); 558 } 559 560 /* 561 * Linux has two extra args, restart and oldmask. We don't use these, 562 * but it seems that "restart" is actually a context pointer that 563 * enables the signal to happen with a different register set. 564 */ 565 int 566 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 567 { 568 sigset_t sigmask; 569 l_sigset_t mask; 570 571 #ifdef DEBUG 572 if (ldebug(sigsuspend)) 573 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 574 #endif 575 576 LINUX_SIGEMPTYSET(mask); 577 mask.__mask = args->mask; 578 linux_to_bsd_sigset(&mask, &sigmask); 579 return (kern_sigsuspend(td, sigmask)); 580 } 581 582 int 583 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 584 { 585 l_sigset_t lmask; 586 sigset_t sigmask; 587 int error; 588 589 #ifdef DEBUG 590 if (ldebug(rt_sigsuspend)) 591 printf(ARGS(rt_sigsuspend, "%p, %d"), 592 (void *)uap->newset, uap->sigsetsize); 593 #endif 594 595 if (uap->sigsetsize != sizeof(l_sigset_t)) 596 return (EINVAL); 597 598 error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 599 if (error) 600 return (error); 601 602 linux_to_bsd_sigset(&lmask, &sigmask); 603 return (kern_sigsuspend(td, sigmask)); 604 } 605 606 int 607 linux_pause(struct thread *td, struct linux_pause_args *args) 608 { 609 struct proc *p = td->td_proc; 610 sigset_t sigmask; 611 612 #ifdef DEBUG 613 if (ldebug(pause)) 614 printf(ARGS(pause, "")); 615 #endif 616 617 PROC_LOCK(p); 618 sigmask = td->td_sigmask; 619 PROC_UNLOCK(p); 620 return (kern_sigsuspend(td, sigmask)); 621 } 622 623 int 624 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 625 { 626 stack_t ss, oss; 627 l_stack_t lss; 628 int error; 629 630 #ifdef DEBUG 631 if (ldebug(sigaltstack)) 632 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 633 #endif 634 635 if (uap->uss != NULL) { 636 error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 637 if (error) 638 return (error); 639 640 ss.ss_sp = PTRIN(lss.ss_sp); 641 ss.ss_size = lss.ss_size; 642 ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 643 } 644 error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 645 (uap->uoss != NULL) ? &oss : NULL); 646 if (!error && uap->uoss != NULL) { 647 lss.ss_sp = PTROUT(oss.ss_sp); 648 lss.ss_size = oss.ss_size; 649 lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 650 error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 651 } 652 653 return (error); 654 } 655 656 int 657 linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 658 { 659 660 #ifdef DEBUG 661 if (ldebug(ftruncate64)) 662 printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 663 (intmax_t)args->length); 664 #endif 665 666 return (kern_ftruncate(td, args->fd, args->length)); 667 } 668 669 int 670 linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) 671 { 672 struct timeval atv; 673 l_timeval atv32; 674 struct timezone rtz; 675 int error = 0; 676 677 if (uap->tp) { 678 microtime(&atv); 679 atv32.tv_sec = atv.tv_sec; 680 atv32.tv_usec = atv.tv_usec; 681 error = copyout(&atv32, uap->tp, sizeof(atv32)); 682 } 683 if (error == 0 && uap->tzp != NULL) { 684 rtz.tz_minuteswest = 0; 685 rtz.tz_dsttime = 0; 686 error = copyout(&rtz, uap->tzp, sizeof(rtz)); 687 } 688 return (error); 689 } 690 691 int 692 linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap) 693 { 694 l_timeval atv32; 695 struct timeval atv, *tvp; 696 struct timezone atz, *tzp; 697 int error; 698 699 if (uap->tp) { 700 error = copyin(uap->tp, &atv32, sizeof(atv32)); 701 if (error) 702 return (error); 703 atv.tv_sec = atv32.tv_sec; 704 atv.tv_usec = atv32.tv_usec; 705 tvp = &atv; 706 } else 707 tvp = NULL; 708 if (uap->tzp) { 709 error = copyin(uap->tzp, &atz, sizeof(atz)); 710 if (error) 711 return (error); 712 tzp = &atz; 713 } else 714 tzp = NULL; 715 return (kern_settimeofday(td, tvp, tzp)); 716 } 717 718 int 719 linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) 720 { 721 struct rusage s; 722 int error; 723 724 error = kern_getrusage(td, uap->who, &s); 725 if (error != 0) 726 return (error); 727 if (uap->rusage != NULL) 728 error = linux_copyout_rusage(&s, uap->rusage); 729 return (error); 730 } 731 732 int 733 linux_set_thread_area(struct thread *td, 734 struct linux_set_thread_area_args *args) 735 { 736 struct l_user_desc info; 737 struct user_segment_descriptor sd; 738 struct pcb *pcb; 739 int a[2]; 740 int error; 741 742 error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 743 if (error) 744 return (error); 745 746 #ifdef DEBUG 747 if (ldebug(set_thread_area)) 748 printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, " 749 "%i, %i, %i"), info.entry_number, info.base_addr, 750 info.limit, info.seg_32bit, info.contents, 751 info.read_exec_only, info.limit_in_pages, 752 info.seg_not_present, info.useable); 753 #endif 754 755 /* 756 * Semantics of Linux version: every thread in the system has array 757 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. 758 * This syscall loads one of the selected TLS decriptors with a value 759 * and also loads GDT descriptors 6, 7 and 8 with the content of 760 * the per-thread descriptors. 761 * 762 * Semantics of FreeBSD version: I think we can ignore that Linux has 763 * three per-thread descriptors and use just the first one. 764 * The tls_array[] is used only in [gs]et_thread_area() syscalls and 765 * for loading the GDT descriptors. We use just one GDT descriptor 766 * for TLS, so we will load just one. 767 * 768 * XXX: This doesn't work when a user space process tries to use more 769 * than one TLS segment. Comment in the Linux source says wine might 770 * do this. 771 */ 772 773 /* 774 * GLIBC reads current %gs and call set_thread_area() with it. 775 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because 776 * we use these segments. 777 */ 778 switch (info.entry_number) { 779 case GUGS32_SEL: 780 case GUDATA_SEL: 781 case 6: 782 case -1: 783 info.entry_number = GUGS32_SEL; 784 break; 785 default: 786 return (EINVAL); 787 } 788 789 /* 790 * We have to copy out the GDT entry we use. 791 * 792 * XXX: What if a user space program does not check the return value 793 * and tries to use 6, 7 or 8? 794 */ 795 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 796 if (error) 797 return (error); 798 799 if (LINUX_LDT_empty(&info)) { 800 a[0] = 0; 801 a[1] = 0; 802 } else { 803 a[0] = LINUX_LDT_entry_a(&info); 804 a[1] = LINUX_LDT_entry_b(&info); 805 } 806 807 memcpy(&sd, &a, sizeof(a)); 808 #ifdef DEBUG 809 if (ldebug(set_thread_area)) 810 printf("Segment created in set_thread_area: " 811 "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, " 812 "type: %i, dpl: %i, p: %i, xx: %i, long: %i, " 813 "def32: %i, gran: %i\n", 814 sd.sd_lobase, 815 sd.sd_hibase, 816 sd.sd_lolimit, 817 sd.sd_hilimit, 818 sd.sd_type, 819 sd.sd_dpl, 820 sd.sd_p, 821 sd.sd_xx, 822 sd.sd_long, 823 sd.sd_def32, 824 sd.sd_gran); 825 #endif 826 827 pcb = td->td_pcb; 828 pcb->pcb_gsbase = (register_t)info.base_addr; 829 set_pcb_flags(pcb, PCB_32BIT); 830 update_gdt_gsbase(td, info.base_addr); 831 832 return (0); 833 } 834 835 int futex_xchgl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 836 int futex_xchgl_smap(int oparg, uint32_t *uaddr, int *oldval); 837 DEFINE_IFUNC(, int, futex_xchgl, (int, uint32_t *, int *), static) 838 { 839 840 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 841 futex_xchgl_smap : futex_xchgl_nosmap); 842 } 843 844 int futex_addl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 845 int futex_addl_smap(int oparg, uint32_t *uaddr, int *oldval); 846 DEFINE_IFUNC(, int, futex_addl, (int, uint32_t *, int *), static) 847 { 848 849 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 850 futex_addl_smap : futex_addl_nosmap); 851 } 852 853 int futex_orl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 854 int futex_orl_smap(int oparg, uint32_t *uaddr, int *oldval); 855 DEFINE_IFUNC(, int, futex_orl, (int, uint32_t *, int *), static) 856 { 857 858 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 859 futex_orl_smap : futex_orl_nosmap); 860 } 861 862 int futex_andl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 863 int futex_andl_smap(int oparg, uint32_t *uaddr, int *oldval); 864 DEFINE_IFUNC(, int, futex_andl, (int, uint32_t *, int *), static) 865 { 866 867 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 868 futex_andl_smap : futex_andl_nosmap); 869 } 870 871 int futex_xorl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 872 int futex_xorl_smap(int oparg, uint32_t *uaddr, int *oldval); 873 DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *), static) 874 { 875 876 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 877 futex_xorl_smap : futex_xorl_nosmap); 878 } 879