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