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