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 = 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(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 = 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(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 = 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 = args->ptr; 331 return (linux_msgctl(td, &a)); 332 } 333 case LINUX_SHMAT: { 334 struct linux_shmat_args a; 335 336 a.shmid = args->arg1; 337 a.shmaddr = args->ptr; 338 a.shmflg = args->arg2; 339 a.raddr = PTRIN((l_uint)args->arg3); 340 return (linux_shmat(td, &a)); 341 } 342 case LINUX_SHMDT: { 343 struct linux_shmdt_args a; 344 345 a.shmaddr = args->ptr; 346 return (linux_shmdt(td, &a)); 347 } 348 case LINUX_SHMGET: { 349 struct linux_shmget_args a; 350 351 a.key = args->arg1; 352 a.size = args->arg2; 353 a.shmflg = args->arg3; 354 return (linux_shmget(td, &a)); 355 } 356 case LINUX_SHMCTL: { 357 struct linux_shmctl_args a; 358 359 a.shmid = args->arg1; 360 a.cmd = args->arg2; 361 a.buf = args->ptr; 362 return (linux_shmctl(td, &a)); 363 } 364 default: 365 break; 366 } 367 368 return (EINVAL); 369 } 370 371 int 372 linux_old_select(struct thread *td, struct linux_old_select_args *args) 373 { 374 struct l_old_select_argv linux_args; 375 struct linux_select_args newsel; 376 int error; 377 378 #ifdef DEBUG 379 if (ldebug(old_select)) 380 printf(ARGS(old_select, "%p"), args->ptr); 381 #endif 382 383 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 384 if (error) 385 return (error); 386 387 newsel.nfds = linux_args.nfds; 388 newsel.readfds = PTRIN(linux_args.readfds); 389 newsel.writefds = PTRIN(linux_args.writefds); 390 newsel.exceptfds = PTRIN(linux_args.exceptfds); 391 newsel.timeout = PTRIN(linux_args.timeout); 392 return (linux_select(td, &newsel)); 393 } 394 395 int 396 linux_set_cloned_tls(struct thread *td, void *desc) 397 { 398 struct user_segment_descriptor sd; 399 struct l_user_desc info; 400 struct pcb *pcb; 401 int error; 402 int a[2]; 403 404 error = copyin(desc, &info, sizeof(struct l_user_desc)); 405 if (error) { 406 printf(LMSG("copyin failed!")); 407 } else { 408 /* We might copy out the entry_number as GUGS32_SEL. */ 409 info.entry_number = GUGS32_SEL; 410 error = copyout(&info, desc, sizeof(struct l_user_desc)); 411 if (error) 412 printf(LMSG("copyout failed!")); 413 414 a[0] = LINUX_LDT_entry_a(&info); 415 a[1] = LINUX_LDT_entry_b(&info); 416 417 memcpy(&sd, &a, sizeof(a)); 418 #ifdef DEBUG 419 if (ldebug(clone)) 420 printf("Segment created in clone with " 421 "CLONE_SETTLS: lobase: %x, hibase: %x, " 422 "lolimit: %x, hilimit: %x, type: %i, " 423 "dpl: %i, p: %i, xx: %i, long: %i, " 424 "def32: %i, gran: %i\n", sd.sd_lobase, 425 sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, 426 sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, 427 sd.sd_long, sd.sd_def32, sd.sd_gran); 428 #endif 429 pcb = td->td_pcb; 430 pcb->pcb_gsbase = (register_t)info.base_addr; 431 td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); 432 set_pcb_flags(pcb, PCB_32BIT); 433 } 434 435 return (error); 436 } 437 438 int 439 linux_set_upcall_kse(struct thread *td, register_t stack) 440 { 441 442 if (stack) 443 td->td_frame->tf_rsp = stack; 444 445 /* 446 * The newly created Linux thread returns 447 * to the user space by the same path that a parent do. 448 */ 449 td->td_frame->tf_rax = 0; 450 return (0); 451 } 452 453 int 454 linux_mmap2(struct thread *td, struct linux_mmap2_args *args) 455 { 456 457 #ifdef DEBUG 458 if (ldebug(mmap2)) 459 printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"), 460 args->addr, args->len, args->prot, 461 args->flags, args->fd, args->pgoff); 462 #endif 463 464 return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, 465 args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * 466 PAGE_SIZE)); 467 } 468 469 int 470 linux_mmap(struct thread *td, struct linux_mmap_args *args) 471 { 472 int error; 473 struct l_mmap_argv linux_args; 474 475 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 476 if (error) 477 return (error); 478 479 #ifdef DEBUG 480 if (ldebug(mmap)) 481 printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"), 482 linux_args.addr, linux_args.len, linux_args.prot, 483 linux_args.flags, linux_args.fd, linux_args.pgoff); 484 #endif 485 486 return (linux_mmap_common(td, linux_args.addr, linux_args.len, 487 linux_args.prot, linux_args.flags, linux_args.fd, 488 (uint32_t)linux_args.pgoff)); 489 } 490 491 int 492 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 493 { 494 495 return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot)); 496 } 497 498 int 499 linux_iopl(struct thread *td, struct linux_iopl_args *args) 500 { 501 int error; 502 503 if (args->level < 0 || args->level > 3) 504 return (EINVAL); 505 if ((error = priv_check(td, PRIV_IO)) != 0) 506 return (error); 507 if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 508 return (error); 509 td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | 510 (args->level * (PSL_IOPL / 3)); 511 512 return (0); 513 } 514 515 int 516 linux_sigaction(struct thread *td, struct linux_sigaction_args *args) 517 { 518 l_osigaction_t osa; 519 l_sigaction_t act, oact; 520 int error; 521 522 #ifdef DEBUG 523 if (ldebug(sigaction)) 524 printf(ARGS(sigaction, "%d, %p, %p"), 525 args->sig, (void *)args->nsa, (void *)args->osa); 526 #endif 527 528 if (args->nsa != NULL) { 529 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 530 if (error) 531 return (error); 532 act.lsa_handler = osa.lsa_handler; 533 act.lsa_flags = osa.lsa_flags; 534 act.lsa_restorer = osa.lsa_restorer; 535 LINUX_SIGEMPTYSET(act.lsa_mask); 536 act.lsa_mask.__mask = osa.lsa_mask; 537 } 538 539 error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 540 args->osa ? &oact : NULL); 541 542 if (args->osa != NULL && !error) { 543 osa.lsa_handler = oact.lsa_handler; 544 osa.lsa_flags = oact.lsa_flags; 545 osa.lsa_restorer = oact.lsa_restorer; 546 osa.lsa_mask = oact.lsa_mask.__mask; 547 error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 548 } 549 550 return (error); 551 } 552 553 /* 554 * Linux has two extra args, restart and oldmask. We don't use these, 555 * but it seems that "restart" is actually a context pointer that 556 * enables the signal to happen with a different register set. 557 */ 558 int 559 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 560 { 561 sigset_t sigmask; 562 l_sigset_t mask; 563 564 #ifdef DEBUG 565 if (ldebug(sigsuspend)) 566 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 567 #endif 568 569 LINUX_SIGEMPTYSET(mask); 570 mask.__mask = args->mask; 571 linux_to_bsd_sigset(&mask, &sigmask); 572 return (kern_sigsuspend(td, sigmask)); 573 } 574 575 int 576 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 577 { 578 l_sigset_t lmask; 579 sigset_t sigmask; 580 int error; 581 582 #ifdef DEBUG 583 if (ldebug(rt_sigsuspend)) 584 printf(ARGS(rt_sigsuspend, "%p, %d"), 585 (void *)uap->newset, uap->sigsetsize); 586 #endif 587 588 if (uap->sigsetsize != sizeof(l_sigset_t)) 589 return (EINVAL); 590 591 error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 592 if (error) 593 return (error); 594 595 linux_to_bsd_sigset(&lmask, &sigmask); 596 return (kern_sigsuspend(td, sigmask)); 597 } 598 599 int 600 linux_pause(struct thread *td, struct linux_pause_args *args) 601 { 602 struct proc *p = td->td_proc; 603 sigset_t sigmask; 604 605 #ifdef DEBUG 606 if (ldebug(pause)) 607 printf(ARGS(pause, "")); 608 #endif 609 610 PROC_LOCK(p); 611 sigmask = td->td_sigmask; 612 PROC_UNLOCK(p); 613 return (kern_sigsuspend(td, sigmask)); 614 } 615 616 int 617 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 618 { 619 stack_t ss, oss; 620 l_stack_t lss; 621 int error; 622 623 #ifdef DEBUG 624 if (ldebug(sigaltstack)) 625 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 626 #endif 627 628 if (uap->uss != NULL) { 629 error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 630 if (error) 631 return (error); 632 633 ss.ss_sp = PTRIN(lss.ss_sp); 634 ss.ss_size = lss.ss_size; 635 ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 636 } 637 error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 638 (uap->uoss != NULL) ? &oss : NULL); 639 if (!error && uap->uoss != NULL) { 640 lss.ss_sp = PTROUT(oss.ss_sp); 641 lss.ss_size = oss.ss_size; 642 lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 643 error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 644 } 645 646 return (error); 647 } 648 649 int 650 linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 651 { 652 653 #ifdef DEBUG 654 if (ldebug(ftruncate64)) 655 printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 656 (intmax_t)args->length); 657 #endif 658 659 return (kern_ftruncate(td, args->fd, args->length)); 660 } 661 662 int 663 linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) 664 { 665 struct timeval atv; 666 l_timeval atv32; 667 struct timezone rtz; 668 int error = 0; 669 670 if (uap->tp) { 671 microtime(&atv); 672 atv32.tv_sec = atv.tv_sec; 673 atv32.tv_usec = atv.tv_usec; 674 error = copyout(&atv32, uap->tp, sizeof(atv32)); 675 } 676 if (error == 0 && uap->tzp != NULL) { 677 rtz.tz_minuteswest = tz_minuteswest; 678 rtz.tz_dsttime = tz_dsttime; 679 error = copyout(&rtz, uap->tzp, sizeof(rtz)); 680 } 681 return (error); 682 } 683 684 int 685 linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap) 686 { 687 l_timeval atv32; 688 struct timeval atv, *tvp; 689 struct timezone atz, *tzp; 690 int error; 691 692 if (uap->tp) { 693 error = copyin(uap->tp, &atv32, sizeof(atv32)); 694 if (error) 695 return (error); 696 atv.tv_sec = atv32.tv_sec; 697 atv.tv_usec = atv32.tv_usec; 698 tvp = &atv; 699 } else 700 tvp = NULL; 701 if (uap->tzp) { 702 error = copyin(uap->tzp, &atz, sizeof(atz)); 703 if (error) 704 return (error); 705 tzp = &atz; 706 } else 707 tzp = NULL; 708 return (kern_settimeofday(td, tvp, tzp)); 709 } 710 711 int 712 linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) 713 { 714 struct rusage s; 715 int error; 716 717 error = kern_getrusage(td, uap->who, &s); 718 if (error != 0) 719 return (error); 720 if (uap->rusage != NULL) 721 error = linux_copyout_rusage(&s, uap->rusage); 722 return (error); 723 } 724 725 int 726 linux_set_thread_area(struct thread *td, 727 struct linux_set_thread_area_args *args) 728 { 729 struct l_user_desc info; 730 struct user_segment_descriptor sd; 731 struct pcb *pcb; 732 int a[2]; 733 int error; 734 735 error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 736 if (error) 737 return (error); 738 739 #ifdef DEBUG 740 if (ldebug(set_thread_area)) 741 printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, " 742 "%i, %i, %i"), info.entry_number, info.base_addr, 743 info.limit, info.seg_32bit, info.contents, 744 info.read_exec_only, info.limit_in_pages, 745 info.seg_not_present, info.useable); 746 #endif 747 748 /* 749 * Semantics of Linux version: every thread in the system has array 750 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. 751 * This syscall loads one of the selected TLS decriptors with a value 752 * and also loads GDT descriptors 6, 7 and 8 with the content of 753 * the per-thread descriptors. 754 * 755 * Semantics of FreeBSD version: I think we can ignore that Linux has 756 * three per-thread descriptors and use just the first one. 757 * The tls_array[] is used only in [gs]et_thread_area() syscalls and 758 * for loading the GDT descriptors. We use just one GDT descriptor 759 * for TLS, so we will load just one. 760 * 761 * XXX: This doesn't work when a user space process tries to use more 762 * than one TLS segment. Comment in the Linux source says wine might 763 * do this. 764 */ 765 766 /* 767 * GLIBC reads current %gs and call set_thread_area() with it. 768 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because 769 * we use these segments. 770 */ 771 switch (info.entry_number) { 772 case GUGS32_SEL: 773 case GUDATA_SEL: 774 case 6: 775 case -1: 776 info.entry_number = GUGS32_SEL; 777 break; 778 default: 779 return (EINVAL); 780 } 781 782 /* 783 * We have to copy out the GDT entry we use. 784 * 785 * XXX: What if a user space program does not check the return value 786 * and tries to use 6, 7 or 8? 787 */ 788 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 789 if (error) 790 return (error); 791 792 if (LINUX_LDT_empty(&info)) { 793 a[0] = 0; 794 a[1] = 0; 795 } else { 796 a[0] = LINUX_LDT_entry_a(&info); 797 a[1] = LINUX_LDT_entry_b(&info); 798 } 799 800 memcpy(&sd, &a, sizeof(a)); 801 #ifdef DEBUG 802 if (ldebug(set_thread_area)) 803 printf("Segment created in set_thread_area: " 804 "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, " 805 "type: %i, dpl: %i, p: %i, xx: %i, long: %i, " 806 "def32: %i, gran: %i\n", 807 sd.sd_lobase, 808 sd.sd_hibase, 809 sd.sd_lolimit, 810 sd.sd_hilimit, 811 sd.sd_type, 812 sd.sd_dpl, 813 sd.sd_p, 814 sd.sd_xx, 815 sd.sd_long, 816 sd.sd_def32, 817 sd.sd_gran); 818 #endif 819 820 pcb = td->td_pcb; 821 pcb->pcb_gsbase = (register_t)info.base_addr; 822 set_pcb_flags(pcb, PCB_32BIT); 823 update_gdt_gsbase(td, info.base_addr); 824 825 return (0); 826 } 827 828 int futex_xchgl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 829 int futex_xchgl_smap(int oparg, uint32_t *uaddr, int *oldval); 830 DEFINE_IFUNC(, int, futex_xchgl, (int, uint32_t *, int *), static) 831 { 832 833 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 834 futex_xchgl_smap : futex_xchgl_nosmap); 835 } 836 837 int futex_addl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 838 int futex_addl_smap(int oparg, uint32_t *uaddr, int *oldval); 839 DEFINE_IFUNC(, int, futex_addl, (int, uint32_t *, int *), static) 840 { 841 842 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 843 futex_addl_smap : futex_addl_nosmap); 844 } 845 846 int futex_orl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 847 int futex_orl_smap(int oparg, uint32_t *uaddr, int *oldval); 848 DEFINE_IFUNC(, int, futex_orl, (int, uint32_t *, int *), static) 849 { 850 851 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 852 futex_orl_smap : futex_orl_nosmap); 853 } 854 855 int futex_andl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 856 int futex_andl_smap(int oparg, uint32_t *uaddr, int *oldval); 857 DEFINE_IFUNC(, int, futex_andl, (int, uint32_t *, int *), static) 858 { 859 860 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 861 futex_andl_smap : futex_andl_nosmap); 862 } 863 864 int futex_xorl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 865 int futex_xorl_smap(int oparg, uint32_t *uaddr, int *oldval); 866 DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *), static) 867 { 868 869 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 870 futex_xorl_smap : futex_xorl_nosmap); 871 } 872