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 <sys/param.h> 37 #include <sys/fcntl.h> 38 #include <sys/imgact.h> 39 #include <sys/limits.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mutex.h> 43 #include <sys/priv.h> 44 #include <sys/proc.h> 45 #include <sys/reg.h> 46 #include <sys/syscallsubr.h> 47 48 #include <machine/frame.h> 49 #include <machine/md_var.h> 50 #include <machine/pcb.h> 51 #include <machine/psl.h> 52 #include <machine/segments.h> 53 #include <machine/specialreg.h> 54 #include <x86/ifunc.h> 55 56 #include <vm/pmap.h> 57 #include <vm/vm.h> 58 #include <vm/vm_map.h> 59 60 #include <security/audit/audit.h> 61 62 #include <compat/freebsd32/freebsd32_util.h> 63 #include <amd64/linux32/linux.h> 64 #include <amd64/linux32/linux32_proto.h> 65 #include <compat/linux/linux_emul.h> 66 #include <compat/linux/linux_fork.h> 67 #include <compat/linux/linux_ipc.h> 68 #include <compat/linux/linux_misc.h> 69 #include <compat/linux/linux_mmap.h> 70 #include <compat/linux/linux_signal.h> 71 #include <compat/linux/linux_util.h> 72 73 static void bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru); 74 75 struct l_old_select_argv { 76 l_int nfds; 77 l_uintptr_t readfds; 78 l_uintptr_t writefds; 79 l_uintptr_t exceptfds; 80 l_uintptr_t timeout; 81 } __packed; 82 83 static void 84 bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru) 85 { 86 87 lru->ru_utime.tv_sec = ru->ru_utime.tv_sec; 88 lru->ru_utime.tv_usec = ru->ru_utime.tv_usec; 89 lru->ru_stime.tv_sec = ru->ru_stime.tv_sec; 90 lru->ru_stime.tv_usec = ru->ru_stime.tv_usec; 91 lru->ru_maxrss = ru->ru_maxrss; 92 lru->ru_ixrss = ru->ru_ixrss; 93 lru->ru_idrss = ru->ru_idrss; 94 lru->ru_isrss = ru->ru_isrss; 95 lru->ru_minflt = ru->ru_minflt; 96 lru->ru_majflt = ru->ru_majflt; 97 lru->ru_nswap = ru->ru_nswap; 98 lru->ru_inblock = ru->ru_inblock; 99 lru->ru_oublock = ru->ru_oublock; 100 lru->ru_msgsnd = ru->ru_msgsnd; 101 lru->ru_msgrcv = ru->ru_msgrcv; 102 lru->ru_nsignals = ru->ru_nsignals; 103 lru->ru_nvcsw = ru->ru_nvcsw; 104 lru->ru_nivcsw = ru->ru_nivcsw; 105 } 106 107 int 108 linux_copyout_rusage(struct rusage *ru, void *uaddr) 109 { 110 struct l_rusage lru; 111 112 bsd_to_linux_rusage(ru, &lru); 113 114 return (copyout(&lru, uaddr, sizeof(struct l_rusage))); 115 } 116 117 CTASSERT(sizeof(struct l_iovec32) == 8); 118 119 int 120 linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop) 121 { 122 struct l_iovec32 iov32; 123 struct iovec *iov; 124 struct uio *uio; 125 uint32_t iovlen; 126 int error, i; 127 128 *uiop = NULL; 129 if (iovcnt > UIO_MAXIOV) 130 return (EINVAL); 131 iovlen = iovcnt * sizeof(struct iovec); 132 uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK); 133 iov = (struct iovec *)(uio + 1); 134 for (i = 0; i < iovcnt; i++) { 135 error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32)); 136 if (error) { 137 free(uio, M_IOV); 138 return (error); 139 } 140 iov[i].iov_base = PTRIN(iov32.iov_base); 141 iov[i].iov_len = iov32.iov_len; 142 } 143 uio->uio_iov = iov; 144 uio->uio_iovcnt = iovcnt; 145 uio->uio_segflg = UIO_USERSPACE; 146 uio->uio_offset = -1; 147 uio->uio_resid = 0; 148 for (i = 0; i < iovcnt; i++) { 149 if (iov->iov_len > INT_MAX - uio->uio_resid) { 150 free(uio, M_IOV); 151 return (EINVAL); 152 } 153 uio->uio_resid += iov->iov_len; 154 iov++; 155 } 156 *uiop = uio; 157 return (0); 158 } 159 160 int 161 linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp, 162 int error) 163 { 164 struct l_iovec32 iov32; 165 struct iovec *iov; 166 uint32_t iovlen; 167 int i; 168 169 *iovp = NULL; 170 if (iovcnt > UIO_MAXIOV) 171 return (error); 172 iovlen = iovcnt * sizeof(struct iovec); 173 iov = malloc(iovlen, M_IOV, M_WAITOK); 174 for (i = 0; i < iovcnt; i++) { 175 error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32)); 176 if (error) { 177 free(iov, M_IOV); 178 return (error); 179 } 180 iov[i].iov_base = PTRIN(iov32.iov_base); 181 iov[i].iov_len = iov32.iov_len; 182 } 183 *iovp = iov; 184 return(0); 185 186 } 187 188 int 189 linux_readv(struct thread *td, struct linux_readv_args *uap) 190 { 191 struct uio *auio; 192 int error; 193 194 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 195 if (error) 196 return (error); 197 error = kern_readv(td, uap->fd, auio); 198 free(auio, M_IOV); 199 return (error); 200 } 201 202 int 203 linux_writev(struct thread *td, struct linux_writev_args *uap) 204 { 205 struct uio *auio; 206 int error; 207 208 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 209 if (error) 210 return (error); 211 error = kern_writev(td, uap->fd, auio); 212 free(auio, M_IOV); 213 return (error); 214 } 215 216 struct l_ipc_kludge { 217 l_uintptr_t msgp; 218 l_long msgtyp; 219 } __packed; 220 221 int 222 linux_ipc(struct thread *td, struct linux_ipc_args *args) 223 { 224 225 switch (args->what & 0xFFFF) { 226 case LINUX_SEMOP: { 227 228 return (kern_semop(td, args->arg1, PTRIN(args->ptr), 229 args->arg2, NULL)); 230 } 231 case LINUX_SEMGET: { 232 struct linux_semget_args a; 233 234 a.key = args->arg1; 235 a.nsems = args->arg2; 236 a.semflg = args->arg3; 237 return (linux_semget(td, &a)); 238 } 239 case LINUX_SEMCTL: { 240 struct linux_semctl_args a; 241 int error; 242 243 a.semid = args->arg1; 244 a.semnum = args->arg2; 245 a.cmd = args->arg3; 246 error = copyin(PTRIN(args->ptr), &a.arg, sizeof(a.arg)); 247 if (error) 248 return (error); 249 return (linux_semctl(td, &a)); 250 } 251 case LINUX_SEMTIMEDOP: { 252 struct linux_semtimedop_args a; 253 254 a.semid = args->arg1; 255 a.tsops = PTRIN(args->ptr); 256 a.nsops = args->arg2; 257 a.timeout = PTRIN(args->arg5); 258 return (linux_semtimedop(td, &a)); 259 } 260 case LINUX_MSGSND: { 261 struct linux_msgsnd_args a; 262 263 a.msqid = args->arg1; 264 a.msgp = PTRIN(args->ptr); 265 a.msgsz = args->arg2; 266 a.msgflg = args->arg3; 267 return (linux_msgsnd(td, &a)); 268 } 269 case LINUX_MSGRCV: { 270 struct linux_msgrcv_args a; 271 272 a.msqid = args->arg1; 273 a.msgsz = args->arg2; 274 a.msgflg = args->arg3; 275 if ((args->what >> 16) == 0) { 276 struct l_ipc_kludge tmp; 277 int error; 278 279 if (args->ptr == 0) 280 return (EINVAL); 281 error = copyin(PTRIN(args->ptr), &tmp, sizeof(tmp)); 282 if (error) 283 return (error); 284 a.msgp = PTRIN(tmp.msgp); 285 a.msgtyp = tmp.msgtyp; 286 } else { 287 a.msgp = PTRIN(args->ptr); 288 a.msgtyp = args->arg5; 289 } 290 return (linux_msgrcv(td, &a)); 291 } 292 case LINUX_MSGGET: { 293 struct linux_msgget_args a; 294 295 a.key = args->arg1; 296 a.msgflg = args->arg2; 297 return (linux_msgget(td, &a)); 298 } 299 case LINUX_MSGCTL: { 300 struct linux_msgctl_args a; 301 302 a.msqid = args->arg1; 303 a.cmd = args->arg2; 304 a.buf = PTRIN(args->ptr); 305 return (linux_msgctl(td, &a)); 306 } 307 case LINUX_SHMAT: { 308 struct linux_shmat_args a; 309 l_uintptr_t addr; 310 int error; 311 312 a.shmid = args->arg1; 313 a.shmaddr = PTRIN(args->ptr); 314 a.shmflg = args->arg2; 315 error = linux_shmat(td, &a); 316 if (error != 0) 317 return (error); 318 addr = td->td_retval[0]; 319 error = copyout(&addr, PTRIN(args->arg3), sizeof(addr)); 320 td->td_retval[0] = 0; 321 return (error); 322 } 323 case LINUX_SHMDT: { 324 struct linux_shmdt_args a; 325 326 a.shmaddr = PTRIN(args->ptr); 327 return (linux_shmdt(td, &a)); 328 } 329 case LINUX_SHMGET: { 330 struct linux_shmget_args a; 331 332 a.key = args->arg1; 333 a.size = args->arg2; 334 a.shmflg = args->arg3; 335 return (linux_shmget(td, &a)); 336 } 337 case LINUX_SHMCTL: { 338 struct linux_shmctl_args a; 339 340 a.shmid = args->arg1; 341 a.cmd = args->arg2; 342 a.buf = PTRIN(args->ptr); 343 return (linux_shmctl(td, &a)); 344 } 345 default: 346 break; 347 } 348 349 return (EINVAL); 350 } 351 352 int 353 linux_old_select(struct thread *td, struct linux_old_select_args *args) 354 { 355 struct l_old_select_argv linux_args; 356 struct linux_select_args newsel; 357 int error; 358 359 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 360 if (error) 361 return (error); 362 363 newsel.nfds = linux_args.nfds; 364 newsel.readfds = PTRIN(linux_args.readfds); 365 newsel.writefds = PTRIN(linux_args.writefds); 366 newsel.exceptfds = PTRIN(linux_args.exceptfds); 367 newsel.timeout = PTRIN(linux_args.timeout); 368 return (linux_select(td, &newsel)); 369 } 370 371 int 372 linux_set_cloned_tls(struct thread *td, void *desc) 373 { 374 struct l_user_desc info; 375 struct pcb *pcb; 376 int error; 377 378 error = copyin(desc, &info, sizeof(struct l_user_desc)); 379 if (error) { 380 linux_msg(td, "set_cloned_tls copyin info failed!"); 381 } else { 382 /* We might copy out the entry_number as GUGS32_SEL. */ 383 info.entry_number = GUGS32_SEL; 384 error = copyout(&info, desc, sizeof(struct l_user_desc)); 385 if (error) 386 linux_msg(td, "set_cloned_tls copyout info failed!"); 387 388 pcb = td->td_pcb; 389 update_pcb_bases(pcb); 390 pcb->pcb_gsbase = (register_t)info.base_addr; 391 td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); 392 } 393 394 return (error); 395 } 396 397 int 398 linux_set_upcall(struct thread *td, register_t stack) 399 { 400 401 if (stack) 402 td->td_frame->tf_rsp = stack; 403 404 /* 405 * The newly created Linux thread returns 406 * to the user space by the same path that a parent do. 407 */ 408 td->td_frame->tf_rax = 0; 409 return (0); 410 } 411 412 int 413 linux_mmap2(struct thread *td, struct linux_mmap2_args *args) 414 { 415 416 return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, 417 args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * 418 PAGE_SIZE)); 419 } 420 421 int 422 linux_mmap(struct thread *td, struct linux_mmap_args *args) 423 { 424 int error; 425 struct l_mmap_argv linux_args; 426 427 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 428 if (error) 429 return (error); 430 431 return (linux_mmap_common(td, linux_args.addr, linux_args.len, 432 linux_args.prot, linux_args.flags, linux_args.fd, 433 (uint32_t)linux_args.pgoff)); 434 } 435 436 int 437 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 438 { 439 440 return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot)); 441 } 442 443 int 444 linux_madvise(struct thread *td, struct linux_madvise_args *uap) 445 { 446 447 return (linux_madvise_common(td, PTROUT(uap->addr), uap->len, uap->behav)); 448 } 449 450 int 451 linux_iopl(struct thread *td, struct linux_iopl_args *args) 452 { 453 int error; 454 455 if (args->level < 0 || args->level > 3) 456 return (EINVAL); 457 if ((error = priv_check(td, PRIV_IO)) != 0) 458 return (error); 459 if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 460 return (error); 461 td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | 462 (args->level * (PSL_IOPL / 3)); 463 464 return (0); 465 } 466 467 int 468 linux_sigaction(struct thread *td, struct linux_sigaction_args *args) 469 { 470 l_osigaction_t osa; 471 l_sigaction_t act, oact; 472 int error; 473 474 if (args->nsa != NULL) { 475 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 476 if (error) 477 return (error); 478 act.lsa_handler = osa.lsa_handler; 479 act.lsa_flags = osa.lsa_flags; 480 act.lsa_restorer = osa.lsa_restorer; 481 LINUX_SIGEMPTYSET(act.lsa_mask); 482 act.lsa_mask.__mask = osa.lsa_mask; 483 } 484 485 error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 486 args->osa ? &oact : NULL); 487 488 if (args->osa != NULL && !error) { 489 osa.lsa_handler = oact.lsa_handler; 490 osa.lsa_flags = oact.lsa_flags; 491 osa.lsa_restorer = oact.lsa_restorer; 492 osa.lsa_mask = oact.lsa_mask.__mask; 493 error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 494 } 495 496 return (error); 497 } 498 499 /* 500 * Linux has two extra args, restart and oldmask. We don't use these, 501 * but it seems that "restart" is actually a context pointer that 502 * enables the signal to happen with a different register set. 503 */ 504 int 505 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 506 { 507 sigset_t sigmask; 508 l_sigset_t mask; 509 510 LINUX_SIGEMPTYSET(mask); 511 mask.__mask = args->mask; 512 linux_to_bsd_sigset(&mask, &sigmask); 513 return (kern_sigsuspend(td, sigmask)); 514 } 515 516 int 517 linux_pause(struct thread *td, struct linux_pause_args *args) 518 { 519 struct proc *p = td->td_proc; 520 sigset_t sigmask; 521 522 PROC_LOCK(p); 523 sigmask = td->td_sigmask; 524 PROC_UNLOCK(p); 525 return (kern_sigsuspend(td, sigmask)); 526 } 527 528 int 529 linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) 530 { 531 struct timeval atv; 532 l_timeval atv32; 533 struct timezone rtz; 534 int error = 0; 535 536 if (uap->tp) { 537 microtime(&atv); 538 atv32.tv_sec = atv.tv_sec; 539 atv32.tv_usec = atv.tv_usec; 540 error = copyout(&atv32, uap->tp, sizeof(atv32)); 541 } 542 if (error == 0 && uap->tzp != NULL) { 543 rtz.tz_minuteswest = 0; 544 rtz.tz_dsttime = 0; 545 error = copyout(&rtz, uap->tzp, sizeof(rtz)); 546 } 547 return (error); 548 } 549 550 int 551 linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap) 552 { 553 l_timeval atv32; 554 struct timeval atv, *tvp; 555 struct timezone atz, *tzp; 556 int error; 557 558 if (uap->tp) { 559 error = copyin(uap->tp, &atv32, sizeof(atv32)); 560 if (error) 561 return (error); 562 atv.tv_sec = atv32.tv_sec; 563 atv.tv_usec = atv32.tv_usec; 564 tvp = &atv; 565 } else 566 tvp = NULL; 567 if (uap->tzp) { 568 error = copyin(uap->tzp, &atz, sizeof(atz)); 569 if (error) 570 return (error); 571 tzp = &atz; 572 } else 573 tzp = NULL; 574 return (kern_settimeofday(td, tvp, tzp)); 575 } 576 577 int 578 linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) 579 { 580 struct rusage s; 581 int error; 582 583 error = kern_getrusage(td, uap->who, &s); 584 if (error != 0) 585 return (error); 586 if (uap->rusage != NULL) 587 error = linux_copyout_rusage(&s, uap->rusage); 588 return (error); 589 } 590 591 int 592 linux_set_thread_area(struct thread *td, 593 struct linux_set_thread_area_args *args) 594 { 595 struct l_user_desc info; 596 struct pcb *pcb; 597 int error; 598 599 error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 600 if (error) 601 return (error); 602 603 /* 604 * Semantics of Linux version: every thread in the system has array 605 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. 606 * This syscall loads one of the selected TLS decriptors with a value 607 * and also loads GDT descriptors 6, 7 and 8 with the content of 608 * the per-thread descriptors. 609 * 610 * Semantics of FreeBSD version: I think we can ignore that Linux has 611 * three per-thread descriptors and use just the first one. 612 * The tls_array[] is used only in [gs]et_thread_area() syscalls and 613 * for loading the GDT descriptors. We use just one GDT descriptor 614 * for TLS, so we will load just one. 615 * 616 * XXX: This doesn't work when a user space process tries to use more 617 * than one TLS segment. Comment in the Linux source says wine might 618 * do this. 619 */ 620 621 /* 622 * GLIBC reads current %gs and call set_thread_area() with it. 623 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because 624 * we use these segments. 625 */ 626 switch (info.entry_number) { 627 case GUGS32_SEL: 628 case GUDATA_SEL: 629 case 6: 630 case -1: 631 info.entry_number = GUGS32_SEL; 632 break; 633 default: 634 return (EINVAL); 635 } 636 637 /* 638 * We have to copy out the GDT entry we use. 639 * 640 * XXX: What if a user space program does not check the return value 641 * and tries to use 6, 7 or 8? 642 */ 643 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 644 if (error) 645 return (error); 646 647 pcb = td->td_pcb; 648 update_pcb_bases(pcb); 649 pcb->pcb_gsbase = (register_t)info.base_addr; 650 update_gdt_gsbase(td, info.base_addr); 651 652 return (0); 653 } 654 655 void 656 bsd_to_linux_regset32(const struct reg32 *b_reg, 657 struct linux_pt_regset32 *l_regset) 658 { 659 660 l_regset->ebx = b_reg->r_ebx; 661 l_regset->ecx = b_reg->r_ecx; 662 l_regset->edx = b_reg->r_edx; 663 l_regset->esi = b_reg->r_esi; 664 l_regset->edi = b_reg->r_edi; 665 l_regset->ebp = b_reg->r_ebp; 666 l_regset->eax = b_reg->r_eax; 667 l_regset->ds = b_reg->r_ds; 668 l_regset->es = b_reg->r_es; 669 l_regset->fs = b_reg->r_fs; 670 l_regset->gs = b_reg->r_gs; 671 l_regset->orig_eax = b_reg->r_eax; 672 l_regset->eip = b_reg->r_eip; 673 l_regset->cs = b_reg->r_cs; 674 l_regset->eflags = b_reg->r_eflags; 675 l_regset->esp = b_reg->r_esp; 676 l_regset->ss = b_reg->r_ss; 677 } 678 679 int futex_xchgl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 680 int futex_xchgl_smap(int oparg, uint32_t *uaddr, int *oldval); 681 DEFINE_IFUNC(, int, futex_xchgl, (int, uint32_t *, int *)) 682 { 683 684 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 685 futex_xchgl_smap : futex_xchgl_nosmap); 686 } 687 688 int futex_addl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 689 int futex_addl_smap(int oparg, uint32_t *uaddr, int *oldval); 690 DEFINE_IFUNC(, int, futex_addl, (int, uint32_t *, int *)) 691 { 692 693 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 694 futex_addl_smap : futex_addl_nosmap); 695 } 696 697 int futex_orl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 698 int futex_orl_smap(int oparg, uint32_t *uaddr, int *oldval); 699 DEFINE_IFUNC(, int, futex_orl, (int, uint32_t *, int *)) 700 { 701 702 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 703 futex_orl_smap : futex_orl_nosmap); 704 } 705 706 int futex_andl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 707 int futex_andl_smap(int oparg, uint32_t *uaddr, int *oldval); 708 DEFINE_IFUNC(, int, futex_andl, (int, uint32_t *, int *)) 709 { 710 711 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 712 futex_andl_smap : futex_andl_nosmap); 713 } 714 715 int futex_xorl_nosmap(int oparg, uint32_t *uaddr, int *oldval); 716 int futex_xorl_smap(int oparg, uint32_t *uaddr, int *oldval); 717 DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *)) 718 { 719 720 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 721 futex_xorl_smap : futex_xorl_nosmap); 722 } 723 724 int 725 linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data) 726 { 727 728 LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; " 729 "returning EINVAL", (uintptr_t)addr); 730 return (EINVAL); 731 } 732 733 int 734 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data) 735 { 736 737 LINUX_RATELIMIT_MSG_OPT1("PTRACE_POKEUSER offset %ld " 738 "not implemented; returning EINVAL", (uintptr_t)addr); 739 return (EINVAL); 740 } 741