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