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