1 /*- 2 * Copyright (c) 2002 Doug Rabson 3 * Copyright (c) 1994-1995 Søren Schmidt 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer 11 * in this position and unchanged. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_compat.h" 34 35 #include <sys/param.h> 36 #include <sys/blist.h> 37 #include <sys/fcntl.h> 38 #if defined(__i386__) 39 #include <sys/imgact_aout.h> 40 #endif 41 #include <sys/jail.h> 42 #include <sys/kernel.h> 43 #include <sys/limits.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mman.h> 47 #include <sys/mount.h> 48 #include <sys/mutex.h> 49 #include <sys/namei.h> 50 #include <sys/priv.h> 51 #include <sys/proc.h> 52 #include <sys/reboot.h> 53 #include <sys/racct.h> 54 #include <sys/resourcevar.h> 55 #include <sys/sched.h> 56 #include <sys/signalvar.h> 57 #include <sys/stat.h> 58 #include <sys/syscallsubr.h> 59 #include <sys/sysctl.h> 60 #include <sys/sysproto.h> 61 #include <sys/systm.h> 62 #include <sys/time.h> 63 #include <sys/vmmeter.h> 64 #include <sys/vnode.h> 65 #include <sys/wait.h> 66 #include <sys/cpuset.h> 67 68 #include <security/mac/mac_framework.h> 69 70 #include <vm/vm.h> 71 #include <vm/pmap.h> 72 #include <vm/vm_kern.h> 73 #include <vm/vm_map.h> 74 #include <vm/vm_extern.h> 75 #include <vm/vm_object.h> 76 #include <vm/swap_pager.h> 77 78 #ifdef COMPAT_LINUX32 79 #include <machine/../linux32/linux.h> 80 #include <machine/../linux32/linux32_proto.h> 81 #else 82 #include <machine/../linux/linux.h> 83 #include <machine/../linux/linux_proto.h> 84 #endif 85 86 #include <compat/linux/linux_file.h> 87 #include <compat/linux/linux_mib.h> 88 #include <compat/linux/linux_signal.h> 89 #include <compat/linux/linux_util.h> 90 #include <compat/linux/linux_sysproto.h> 91 #include <compat/linux/linux_emul.h> 92 #include <compat/linux/linux_misc.h> 93 94 int stclohz; /* Statistics clock frequency */ 95 96 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { 97 RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 98 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 99 RLIMIT_MEMLOCK, RLIMIT_AS 100 }; 101 102 struct l_sysinfo { 103 l_long uptime; /* Seconds since boot */ 104 l_ulong loads[3]; /* 1, 5, and 15 minute load averages */ 105 #define LINUX_SYSINFO_LOADS_SCALE 65536 106 l_ulong totalram; /* Total usable main memory size */ 107 l_ulong freeram; /* Available memory size */ 108 l_ulong sharedram; /* Amount of shared memory */ 109 l_ulong bufferram; /* Memory used by buffers */ 110 l_ulong totalswap; /* Total swap space size */ 111 l_ulong freeswap; /* swap space still available */ 112 l_ushort procs; /* Number of current processes */ 113 l_ushort pads; 114 l_ulong totalbig; 115 l_ulong freebig; 116 l_uint mem_unit; 117 char _f[20-2*sizeof(l_long)-sizeof(l_int)]; /* padding */ 118 }; 119 120 struct l_pselect6arg { 121 l_uintptr_t ss; 122 l_size_t ss_len; 123 }; 124 125 int 126 linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args) 127 { 128 struct l_sysinfo sysinfo; 129 vm_object_t object; 130 int i, j; 131 struct timespec ts; 132 133 getnanouptime(&ts); 134 if (ts.tv_nsec != 0) 135 ts.tv_sec++; 136 sysinfo.uptime = ts.tv_sec; 137 138 /* Use the information from the mib to get our load averages */ 139 for (i = 0; i < 3; i++) 140 sysinfo.loads[i] = averunnable.ldavg[i] * 141 LINUX_SYSINFO_LOADS_SCALE / averunnable.fscale; 142 143 sysinfo.totalram = physmem * PAGE_SIZE; 144 sysinfo.freeram = sysinfo.totalram - vm_cnt.v_wire_count * PAGE_SIZE; 145 146 sysinfo.sharedram = 0; 147 mtx_lock(&vm_object_list_mtx); 148 TAILQ_FOREACH(object, &vm_object_list, object_list) 149 if (object->shadow_count > 1) 150 sysinfo.sharedram += object->resident_page_count; 151 mtx_unlock(&vm_object_list_mtx); 152 153 sysinfo.sharedram *= PAGE_SIZE; 154 sysinfo.bufferram = 0; 155 156 swap_pager_status(&i, &j); 157 sysinfo.totalswap = i * PAGE_SIZE; 158 sysinfo.freeswap = (i - j) * PAGE_SIZE; 159 160 sysinfo.procs = nprocs; 161 162 /* The following are only present in newer Linux kernels. */ 163 sysinfo.totalbig = 0; 164 sysinfo.freebig = 0; 165 sysinfo.mem_unit = 1; 166 167 return (copyout(&sysinfo, args->info, sizeof(sysinfo))); 168 } 169 170 int 171 linux_alarm(struct thread *td, struct linux_alarm_args *args) 172 { 173 struct itimerval it, old_it; 174 u_int secs; 175 int error; 176 177 #ifdef DEBUG 178 if (ldebug(alarm)) 179 printf(ARGS(alarm, "%u"), args->secs); 180 #endif 181 182 secs = args->secs; 183 184 if (secs > INT_MAX) 185 secs = INT_MAX; 186 187 it.it_value.tv_sec = (long) secs; 188 it.it_value.tv_usec = 0; 189 it.it_interval.tv_sec = 0; 190 it.it_interval.tv_usec = 0; 191 error = kern_setitimer(td, ITIMER_REAL, &it, &old_it); 192 if (error) 193 return (error); 194 if (timevalisset(&old_it.it_value)) { 195 if (old_it.it_value.tv_usec != 0) 196 old_it.it_value.tv_sec++; 197 td->td_retval[0] = old_it.it_value.tv_sec; 198 } 199 return (0); 200 } 201 202 int 203 linux_brk(struct thread *td, struct linux_brk_args *args) 204 { 205 struct vmspace *vm = td->td_proc->p_vmspace; 206 vm_offset_t new, old; 207 struct obreak_args /* { 208 char * nsize; 209 } */ tmp; 210 211 #ifdef DEBUG 212 if (ldebug(brk)) 213 printf(ARGS(brk, "%p"), (void *)(uintptr_t)args->dsend); 214 #endif 215 old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); 216 new = (vm_offset_t)args->dsend; 217 tmp.nsize = (char *)new; 218 if (((caddr_t)new > vm->vm_daddr) && !sys_obreak(td, &tmp)) 219 td->td_retval[0] = (long)new; 220 else 221 td->td_retval[0] = (long)old; 222 223 return (0); 224 } 225 226 #if defined(__i386__) 227 /* XXX: what about amd64/linux32? */ 228 229 int 230 linux_uselib(struct thread *td, struct linux_uselib_args *args) 231 { 232 struct nameidata ni; 233 struct vnode *vp; 234 struct exec *a_out; 235 struct vattr attr; 236 vm_offset_t vmaddr; 237 unsigned long file_offset; 238 unsigned long bss_size; 239 char *library; 240 ssize_t aresid; 241 int error, locked, writecount; 242 243 LCONVPATHEXIST(td, args->library, &library); 244 245 #ifdef DEBUG 246 if (ldebug(uselib)) 247 printf(ARGS(uselib, "%s"), library); 248 #endif 249 250 a_out = NULL; 251 locked = 0; 252 vp = NULL; 253 254 NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, 255 UIO_SYSSPACE, library, td); 256 error = namei(&ni); 257 LFREEPATH(library); 258 if (error) 259 goto cleanup; 260 261 vp = ni.ni_vp; 262 NDFREE(&ni, NDF_ONLY_PNBUF); 263 264 /* 265 * From here on down, we have a locked vnode that must be unlocked. 266 * XXX: The code below largely duplicates exec_check_permissions(). 267 */ 268 locked = 1; 269 270 /* Writable? */ 271 error = VOP_GET_WRITECOUNT(vp, &writecount); 272 if (error != 0) 273 goto cleanup; 274 if (writecount != 0) { 275 error = ETXTBSY; 276 goto cleanup; 277 } 278 279 /* Executable? */ 280 error = VOP_GETATTR(vp, &attr, td->td_ucred); 281 if (error) 282 goto cleanup; 283 284 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 285 ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { 286 /* EACCESS is what exec(2) returns. */ 287 error = ENOEXEC; 288 goto cleanup; 289 } 290 291 /* Sensible size? */ 292 if (attr.va_size == 0) { 293 error = ENOEXEC; 294 goto cleanup; 295 } 296 297 /* Can we access it? */ 298 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 299 if (error) 300 goto cleanup; 301 302 /* 303 * XXX: This should use vn_open() so that it is properly authorized, 304 * and to reduce code redundancy all over the place here. 305 * XXX: Not really, it duplicates far more of exec_check_permissions() 306 * than vn_open(). 307 */ 308 #ifdef MAC 309 error = mac_vnode_check_open(td->td_ucred, vp, VREAD); 310 if (error) 311 goto cleanup; 312 #endif 313 error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL); 314 if (error) 315 goto cleanup; 316 317 /* Pull in executable header into exec_map */ 318 error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE, 319 VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); 320 if (error) 321 goto cleanup; 322 323 /* Is it a Linux binary ? */ 324 if (((a_out->a_magic >> 16) & 0xff) != 0x64) { 325 error = ENOEXEC; 326 goto cleanup; 327 } 328 329 /* 330 * While we are here, we should REALLY do some more checks 331 */ 332 333 /* Set file/virtual offset based on a.out variant. */ 334 switch ((int)(a_out->a_magic & 0xffff)) { 335 case 0413: /* ZMAGIC */ 336 file_offset = 1024; 337 break; 338 case 0314: /* QMAGIC */ 339 file_offset = 0; 340 break; 341 default: 342 error = ENOEXEC; 343 goto cleanup; 344 } 345 346 bss_size = round_page(a_out->a_bss); 347 348 /* Check various fields in header for validity/bounds. */ 349 if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { 350 error = ENOEXEC; 351 goto cleanup; 352 } 353 354 /* text + data can't exceed file size */ 355 if (a_out->a_data + a_out->a_text > attr.va_size) { 356 error = EFAULT; 357 goto cleanup; 358 } 359 360 /* 361 * text/data/bss must not exceed limits 362 * XXX - this is not complete. it should check current usage PLUS 363 * the resources needed by this library. 364 */ 365 PROC_LOCK(td->td_proc); 366 if (a_out->a_text > maxtsiz || 367 a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA) || 368 racct_set(td->td_proc, RACCT_DATA, a_out->a_data + 369 bss_size) != 0) { 370 PROC_UNLOCK(td->td_proc); 371 error = ENOMEM; 372 goto cleanup; 373 } 374 PROC_UNLOCK(td->td_proc); 375 376 /* 377 * Prevent more writers. 378 * XXX: Note that if any of the VM operations fail below we don't 379 * clear this flag. 380 */ 381 VOP_SET_TEXT(vp); 382 383 /* 384 * Lock no longer needed 385 */ 386 locked = 0; 387 VOP_UNLOCK(vp, 0); 388 389 /* 390 * Check if file_offset page aligned. Currently we cannot handle 391 * misalinged file offsets, and so we read in the entire image 392 * (what a waste). 393 */ 394 if (file_offset & PAGE_MASK) { 395 #ifdef DEBUG 396 printf("uselib: Non page aligned binary %lu\n", file_offset); 397 #endif 398 /* Map text+data read/write/execute */ 399 400 /* a_entry is the load address and is page aligned */ 401 vmaddr = trunc_page(a_out->a_entry); 402 403 /* get anon user mapping, read+write+execute */ 404 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, 405 &vmaddr, a_out->a_text + a_out->a_data, 0, VMFS_NO_SPACE, 406 VM_PROT_ALL, VM_PROT_ALL, 0); 407 if (error) 408 goto cleanup; 409 410 error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset, 411 a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, 412 td->td_ucred, NOCRED, &aresid, td); 413 if (error != 0) 414 goto cleanup; 415 if (aresid != 0) { 416 error = ENOEXEC; 417 goto cleanup; 418 } 419 } else { 420 #ifdef DEBUG 421 printf("uselib: Page aligned binary %lu\n", file_offset); 422 #endif 423 /* 424 * for QMAGIC, a_entry is 20 bytes beyond the load address 425 * to skip the executable header 426 */ 427 vmaddr = trunc_page(a_out->a_entry); 428 429 /* 430 * Map it all into the process's space as a single 431 * copy-on-write "data" segment. 432 */ 433 error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr, 434 a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, 435 MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); 436 if (error) 437 goto cleanup; 438 } 439 #ifdef DEBUG 440 printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long *)vmaddr)[0], 441 ((long *)vmaddr)[1]); 442 #endif 443 if (bss_size != 0) { 444 /* Calculate BSS start address */ 445 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + 446 a_out->a_data; 447 448 /* allocate some 'anon' space */ 449 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, 450 &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, 451 VM_PROT_ALL, 0); 452 if (error) 453 goto cleanup; 454 } 455 456 cleanup: 457 /* Unlock vnode if needed */ 458 if (locked) 459 VOP_UNLOCK(vp, 0); 460 461 /* Release the temporary mapping. */ 462 if (a_out) 463 kmap_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE); 464 465 return (error); 466 } 467 468 #endif /* __i386__ */ 469 470 int 471 linux_select(struct thread *td, struct linux_select_args *args) 472 { 473 l_timeval ltv; 474 struct timeval tv0, tv1, utv, *tvp; 475 int error; 476 477 #ifdef DEBUG 478 if (ldebug(select)) 479 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, 480 (void *)args->readfds, (void *)args->writefds, 481 (void *)args->exceptfds, (void *)args->timeout); 482 #endif 483 484 /* 485 * Store current time for computation of the amount of 486 * time left. 487 */ 488 if (args->timeout) { 489 if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 490 goto select_out; 491 utv.tv_sec = ltv.tv_sec; 492 utv.tv_usec = ltv.tv_usec; 493 #ifdef DEBUG 494 if (ldebug(select)) 495 printf(LMSG("incoming timeout (%jd/%ld)"), 496 (intmax_t)utv.tv_sec, utv.tv_usec); 497 #endif 498 499 if (itimerfix(&utv)) { 500 /* 501 * The timeval was invalid. Convert it to something 502 * valid that will act as it does under Linux. 503 */ 504 utv.tv_sec += utv.tv_usec / 1000000; 505 utv.tv_usec %= 1000000; 506 if (utv.tv_usec < 0) { 507 utv.tv_sec -= 1; 508 utv.tv_usec += 1000000; 509 } 510 if (utv.tv_sec < 0) 511 timevalclear(&utv); 512 } 513 microtime(&tv0); 514 tvp = &utv; 515 } else 516 tvp = NULL; 517 518 error = kern_select(td, args->nfds, args->readfds, args->writefds, 519 args->exceptfds, tvp, sizeof(l_int) * 8); 520 521 #ifdef DEBUG 522 if (ldebug(select)) 523 printf(LMSG("real select returns %d"), error); 524 #endif 525 if (error) 526 goto select_out; 527 528 if (args->timeout) { 529 if (td->td_retval[0]) { 530 /* 531 * Compute how much time was left of the timeout, 532 * by subtracting the current time and the time 533 * before we started the call, and subtracting 534 * that result from the user-supplied value. 535 */ 536 microtime(&tv1); 537 timevalsub(&tv1, &tv0); 538 timevalsub(&utv, &tv1); 539 if (utv.tv_sec < 0) 540 timevalclear(&utv); 541 } else 542 timevalclear(&utv); 543 #ifdef DEBUG 544 if (ldebug(select)) 545 printf(LMSG("outgoing timeout (%jd/%ld)"), 546 (intmax_t)utv.tv_sec, utv.tv_usec); 547 #endif 548 ltv.tv_sec = utv.tv_sec; 549 ltv.tv_usec = utv.tv_usec; 550 if ((error = copyout(<v, args->timeout, sizeof(ltv)))) 551 goto select_out; 552 } 553 554 select_out: 555 #ifdef DEBUG 556 if (ldebug(select)) 557 printf(LMSG("select_out -> %d"), error); 558 #endif 559 return (error); 560 } 561 562 int 563 linux_mremap(struct thread *td, struct linux_mremap_args *args) 564 { 565 struct munmap_args /* { 566 void *addr; 567 size_t len; 568 } */ bsd_args; 569 int error = 0; 570 571 #ifdef DEBUG 572 if (ldebug(mremap)) 573 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), 574 (void *)(uintptr_t)args->addr, 575 (unsigned long)args->old_len, 576 (unsigned long)args->new_len, 577 (unsigned long)args->flags); 578 #endif 579 580 if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) { 581 td->td_retval[0] = 0; 582 return (EINVAL); 583 } 584 585 /* 586 * Check for the page alignment. 587 * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK. 588 */ 589 if (args->addr & PAGE_MASK) { 590 td->td_retval[0] = 0; 591 return (EINVAL); 592 } 593 594 args->new_len = round_page(args->new_len); 595 args->old_len = round_page(args->old_len); 596 597 if (args->new_len > args->old_len) { 598 td->td_retval[0] = 0; 599 return (ENOMEM); 600 } 601 602 if (args->new_len < args->old_len) { 603 bsd_args.addr = 604 (caddr_t)((uintptr_t)args->addr + args->new_len); 605 bsd_args.len = args->old_len - args->new_len; 606 error = sys_munmap(td, &bsd_args); 607 } 608 609 td->td_retval[0] = error ? 0 : (uintptr_t)args->addr; 610 return (error); 611 } 612 613 #define LINUX_MS_ASYNC 0x0001 614 #define LINUX_MS_INVALIDATE 0x0002 615 #define LINUX_MS_SYNC 0x0004 616 617 int 618 linux_msync(struct thread *td, struct linux_msync_args *args) 619 { 620 struct msync_args bsd_args; 621 622 bsd_args.addr = (caddr_t)(uintptr_t)args->addr; 623 bsd_args.len = (uintptr_t)args->len; 624 bsd_args.flags = args->fl & ~LINUX_MS_SYNC; 625 626 return (sys_msync(td, &bsd_args)); 627 } 628 629 int 630 linux_time(struct thread *td, struct linux_time_args *args) 631 { 632 struct timeval tv; 633 l_time_t tm; 634 int error; 635 636 #ifdef DEBUG 637 if (ldebug(time)) 638 printf(ARGS(time, "*")); 639 #endif 640 641 microtime(&tv); 642 tm = tv.tv_sec; 643 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) 644 return (error); 645 td->td_retval[0] = tm; 646 return (0); 647 } 648 649 struct l_times_argv { 650 l_clock_t tms_utime; 651 l_clock_t tms_stime; 652 l_clock_t tms_cutime; 653 l_clock_t tms_cstime; 654 }; 655 656 657 /* 658 * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value. 659 * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK 660 * auxiliary vector entry. 661 */ 662 #define CLK_TCK 100 663 664 #define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 665 #define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz)) 666 667 #define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER_2004000 ? \ 668 CONVNTCK(r) : CONVOTCK(r)) 669 670 int 671 linux_times(struct thread *td, struct linux_times_args *args) 672 { 673 struct timeval tv, utime, stime, cutime, cstime; 674 struct l_times_argv tms; 675 struct proc *p; 676 int error; 677 678 #ifdef DEBUG 679 if (ldebug(times)) 680 printf(ARGS(times, "*")); 681 #endif 682 683 if (args->buf != NULL) { 684 p = td->td_proc; 685 PROC_LOCK(p); 686 PROC_STATLOCK(p); 687 calcru(p, &utime, &stime); 688 PROC_STATUNLOCK(p); 689 calccru(p, &cutime, &cstime); 690 PROC_UNLOCK(p); 691 692 tms.tms_utime = CONVTCK(utime); 693 tms.tms_stime = CONVTCK(stime); 694 695 tms.tms_cutime = CONVTCK(cutime); 696 tms.tms_cstime = CONVTCK(cstime); 697 698 if ((error = copyout(&tms, args->buf, sizeof(tms)))) 699 return (error); 700 } 701 702 microuptime(&tv); 703 td->td_retval[0] = (int)CONVTCK(tv); 704 return (0); 705 } 706 707 int 708 linux_newuname(struct thread *td, struct linux_newuname_args *args) 709 { 710 struct l_new_utsname utsname; 711 char osname[LINUX_MAX_UTSNAME]; 712 char osrelease[LINUX_MAX_UTSNAME]; 713 char *p; 714 715 #ifdef DEBUG 716 if (ldebug(newuname)) 717 printf(ARGS(newuname, "*")); 718 #endif 719 720 linux_get_osname(td, osname); 721 linux_get_osrelease(td, osrelease); 722 723 bzero(&utsname, sizeof(utsname)); 724 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); 725 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); 726 getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME); 727 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); 728 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); 729 for (p = utsname.version; *p != '\0'; ++p) 730 if (*p == '\n') { 731 *p = '\0'; 732 break; 733 } 734 strlcpy(utsname.machine, linux_kplatform, LINUX_MAX_UTSNAME); 735 736 return (copyout(&utsname, args->buf, sizeof(utsname))); 737 } 738 739 struct l_utimbuf { 740 l_time_t l_actime; 741 l_time_t l_modtime; 742 }; 743 744 int 745 linux_utime(struct thread *td, struct linux_utime_args *args) 746 { 747 struct timeval tv[2], *tvp; 748 struct l_utimbuf lut; 749 char *fname; 750 int error; 751 752 LCONVPATHEXIST(td, args->fname, &fname); 753 754 #ifdef DEBUG 755 if (ldebug(utime)) 756 printf(ARGS(utime, "%s, *"), fname); 757 #endif 758 759 if (args->times) { 760 if ((error = copyin(args->times, &lut, sizeof lut))) { 761 LFREEPATH(fname); 762 return (error); 763 } 764 tv[0].tv_sec = lut.l_actime; 765 tv[0].tv_usec = 0; 766 tv[1].tv_sec = lut.l_modtime; 767 tv[1].tv_usec = 0; 768 tvp = tv; 769 } else 770 tvp = NULL; 771 772 error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, tvp, 773 UIO_SYSSPACE); 774 LFREEPATH(fname); 775 return (error); 776 } 777 778 int 779 linux_utimes(struct thread *td, struct linux_utimes_args *args) 780 { 781 l_timeval ltv[2]; 782 struct timeval tv[2], *tvp = NULL; 783 char *fname; 784 int error; 785 786 LCONVPATHEXIST(td, args->fname, &fname); 787 788 #ifdef DEBUG 789 if (ldebug(utimes)) 790 printf(ARGS(utimes, "%s, *"), fname); 791 #endif 792 793 if (args->tptr != NULL) { 794 if ((error = copyin(args->tptr, ltv, sizeof ltv))) { 795 LFREEPATH(fname); 796 return (error); 797 } 798 tv[0].tv_sec = ltv[0].tv_sec; 799 tv[0].tv_usec = ltv[0].tv_usec; 800 tv[1].tv_sec = ltv[1].tv_sec; 801 tv[1].tv_usec = ltv[1].tv_usec; 802 tvp = tv; 803 } 804 805 error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, 806 tvp, UIO_SYSSPACE); 807 LFREEPATH(fname); 808 return (error); 809 } 810 811 int 812 linux_futimesat(struct thread *td, struct linux_futimesat_args *args) 813 { 814 l_timeval ltv[2]; 815 struct timeval tv[2], *tvp = NULL; 816 char *fname; 817 int error, dfd; 818 819 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 820 LCONVPATHEXIST_AT(td, args->filename, &fname, dfd); 821 822 #ifdef DEBUG 823 if (ldebug(futimesat)) 824 printf(ARGS(futimesat, "%s, *"), fname); 825 #endif 826 827 if (args->utimes != NULL) { 828 if ((error = copyin(args->utimes, ltv, sizeof ltv))) { 829 LFREEPATH(fname); 830 return (error); 831 } 832 tv[0].tv_sec = ltv[0].tv_sec; 833 tv[0].tv_usec = ltv[0].tv_usec; 834 tv[1].tv_sec = ltv[1].tv_sec; 835 tv[1].tv_usec = ltv[1].tv_usec; 836 tvp = tv; 837 } 838 839 error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 840 LFREEPATH(fname); 841 return (error); 842 } 843 844 int 845 linux_common_wait(struct thread *td, int pid, int *status, 846 int options, struct rusage *ru) 847 { 848 int error, tmpstat; 849 850 error = kern_wait(td, pid, &tmpstat, options, ru); 851 if (error) 852 return (error); 853 854 if (status) { 855 tmpstat &= 0xffff; 856 if (WIFSIGNALED(tmpstat)) 857 tmpstat = (tmpstat & 0xffffff80) | 858 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 859 else if (WIFSTOPPED(tmpstat)) 860 tmpstat = (tmpstat & 0xffff00ff) | 861 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 862 error = copyout(&tmpstat, status, sizeof(int)); 863 } 864 865 return (error); 866 } 867 868 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 869 int 870 linux_waitpid(struct thread *td, struct linux_waitpid_args *args) 871 { 872 int options; 873 874 #ifdef DEBUG 875 if (ldebug(waitpid)) 876 printf(ARGS(waitpid, "%d, %p, %d"), 877 args->pid, (void *)args->status, args->options); 878 #endif 879 /* 880 * this is necessary because the test in kern_wait doesn't work 881 * because we mess with the options here 882 */ 883 if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE)) 884 return (EINVAL); 885 886 options = (args->options & (WNOHANG | WUNTRACED)); 887 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 888 if (args->options & __WCLONE) 889 options |= WLINUXCLONE; 890 891 return (linux_common_wait(td, args->pid, args->status, options, NULL)); 892 } 893 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 894 895 int 896 linux_wait4(struct thread *td, struct linux_wait4_args *args) 897 { 898 int error, options; 899 struct rusage ru, *rup; 900 901 #ifdef DEBUG 902 if (ldebug(wait4)) 903 printf(ARGS(wait4, "%d, %p, %d, %p"), 904 args->pid, (void *)args->status, args->options, 905 (void *)args->rusage); 906 #endif 907 908 options = (args->options & (WNOHANG | WUNTRACED)); 909 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 910 if (args->options & __WCLONE) 911 options |= WLINUXCLONE; 912 913 if (args->rusage != NULL) 914 rup = &ru; 915 else 916 rup = NULL; 917 error = linux_common_wait(td, args->pid, args->status, options, rup); 918 if (error != 0) 919 return (error); 920 if (args->rusage != NULL) 921 error = linux_copyout_rusage(&ru, args->rusage); 922 return (error); 923 } 924 925 int 926 linux_waitid(struct thread *td, struct linux_waitid_args *args) 927 { 928 int status, options, sig; 929 struct __wrusage wru; 930 siginfo_t siginfo; 931 l_siginfo_t lsi; 932 idtype_t idtype; 933 struct proc *p; 934 int error; 935 936 options = 0; 937 linux_to_bsd_waitopts(args->options, &options); 938 939 if (options & ~(WNOHANG | WNOWAIT | WEXITED | WUNTRACED | WCONTINUED)) 940 return (EINVAL); 941 if (!(options & (WEXITED | WUNTRACED | WCONTINUED))) 942 return (EINVAL); 943 944 switch (args->idtype) { 945 case LINUX_P_ALL: 946 idtype = P_ALL; 947 break; 948 case LINUX_P_PID: 949 if (args->id <= 0) 950 return (EINVAL); 951 idtype = P_PID; 952 break; 953 case LINUX_P_PGID: 954 if (args->id <= 0) 955 return (EINVAL); 956 idtype = P_PGID; 957 break; 958 default: 959 return (EINVAL); 960 } 961 962 error = kern_wait6(td, idtype, args->id, &status, options, 963 &wru, &siginfo); 964 if (error != 0) 965 return (error); 966 if (args->rusage != NULL) { 967 error = linux_copyout_rusage(&wru.wru_children, 968 args->rusage); 969 if (error != 0) 970 return (error); 971 } 972 if (args->info != NULL) { 973 p = td->td_proc; 974 if (td->td_retval[0] == 0) 975 bzero(&lsi, sizeof(lsi)); 976 else { 977 sig = BSD_TO_LINUX_SIGNAL(siginfo.si_signo); 978 siginfo_to_lsiginfo(&siginfo, &lsi, sig); 979 } 980 error = copyout(&lsi, args->info, sizeof(lsi)); 981 } 982 td->td_retval[0] = 0; 983 984 return (error); 985 } 986 987 int 988 linux_mknod(struct thread *td, struct linux_mknod_args *args) 989 { 990 char *path; 991 int error; 992 993 LCONVPATHCREAT(td, args->path, &path); 994 995 #ifdef DEBUG 996 if (ldebug(mknod)) 997 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); 998 #endif 999 1000 switch (args->mode & S_IFMT) { 1001 case S_IFIFO: 1002 case S_IFSOCK: 1003 error = kern_mkfifoat(td, AT_FDCWD, path, UIO_SYSSPACE, 1004 args->mode); 1005 break; 1006 1007 case S_IFCHR: 1008 case S_IFBLK: 1009 error = kern_mknodat(td, AT_FDCWD, path, UIO_SYSSPACE, 1010 args->mode, args->dev); 1011 break; 1012 1013 case S_IFDIR: 1014 error = EPERM; 1015 break; 1016 1017 case 0: 1018 args->mode |= S_IFREG; 1019 /* FALLTHROUGH */ 1020 case S_IFREG: 1021 error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE, 1022 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 1023 if (error == 0) 1024 kern_close(td, td->td_retval[0]); 1025 break; 1026 1027 default: 1028 error = EINVAL; 1029 break; 1030 } 1031 LFREEPATH(path); 1032 return (error); 1033 } 1034 1035 int 1036 linux_mknodat(struct thread *td, struct linux_mknodat_args *args) 1037 { 1038 char *path; 1039 int error, dfd; 1040 1041 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 1042 LCONVPATHCREAT_AT(td, args->filename, &path, dfd); 1043 1044 #ifdef DEBUG 1045 if (ldebug(mknodat)) 1046 printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev); 1047 #endif 1048 1049 switch (args->mode & S_IFMT) { 1050 case S_IFIFO: 1051 case S_IFSOCK: 1052 error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode); 1053 break; 1054 1055 case S_IFCHR: 1056 case S_IFBLK: 1057 error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode, 1058 args->dev); 1059 break; 1060 1061 case S_IFDIR: 1062 error = EPERM; 1063 break; 1064 1065 case 0: 1066 args->mode |= S_IFREG; 1067 /* FALLTHROUGH */ 1068 case S_IFREG: 1069 error = kern_openat(td, dfd, path, UIO_SYSSPACE, 1070 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 1071 if (error == 0) 1072 kern_close(td, td->td_retval[0]); 1073 break; 1074 1075 default: 1076 error = EINVAL; 1077 break; 1078 } 1079 LFREEPATH(path); 1080 return (error); 1081 } 1082 1083 /* 1084 * UGH! This is just about the dumbest idea I've ever heard!! 1085 */ 1086 int 1087 linux_personality(struct thread *td, struct linux_personality_args *args) 1088 { 1089 #ifdef DEBUG 1090 if (ldebug(personality)) 1091 printf(ARGS(personality, "%lu"), (unsigned long)args->per); 1092 #endif 1093 if (args->per != 0) 1094 return (EINVAL); 1095 1096 /* Yes Jim, it's still a Linux... */ 1097 td->td_retval[0] = 0; 1098 return (0); 1099 } 1100 1101 struct l_itimerval { 1102 l_timeval it_interval; 1103 l_timeval it_value; 1104 }; 1105 1106 #define B2L_ITIMERVAL(bip, lip) \ 1107 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ 1108 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ 1109 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ 1110 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; 1111 1112 int 1113 linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) 1114 { 1115 int error; 1116 struct l_itimerval ls; 1117 struct itimerval aitv, oitv; 1118 1119 #ifdef DEBUG 1120 if (ldebug(setitimer)) 1121 printf(ARGS(setitimer, "%p, %p"), 1122 (void *)uap->itv, (void *)uap->oitv); 1123 #endif 1124 1125 if (uap->itv == NULL) { 1126 uap->itv = uap->oitv; 1127 return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); 1128 } 1129 1130 error = copyin(uap->itv, &ls, sizeof(ls)); 1131 if (error != 0) 1132 return (error); 1133 B2L_ITIMERVAL(&aitv, &ls); 1134 #ifdef DEBUG 1135 if (ldebug(setitimer)) { 1136 printf("setitimer: value: sec: %jd, usec: %ld\n", 1137 (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); 1138 printf("setitimer: interval: sec: %jd, usec: %ld\n", 1139 (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); 1140 } 1141 #endif 1142 error = kern_setitimer(td, uap->which, &aitv, &oitv); 1143 if (error != 0 || uap->oitv == NULL) 1144 return (error); 1145 B2L_ITIMERVAL(&ls, &oitv); 1146 1147 return (copyout(&ls, uap->oitv, sizeof(ls))); 1148 } 1149 1150 int 1151 linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) 1152 { 1153 int error; 1154 struct l_itimerval ls; 1155 struct itimerval aitv; 1156 1157 #ifdef DEBUG 1158 if (ldebug(getitimer)) 1159 printf(ARGS(getitimer, "%p"), (void *)uap->itv); 1160 #endif 1161 error = kern_getitimer(td, uap->which, &aitv); 1162 if (error != 0) 1163 return (error); 1164 B2L_ITIMERVAL(&ls, &aitv); 1165 return (copyout(&ls, uap->itv, sizeof(ls))); 1166 } 1167 1168 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1169 int 1170 linux_nice(struct thread *td, struct linux_nice_args *args) 1171 { 1172 struct setpriority_args bsd_args; 1173 1174 bsd_args.which = PRIO_PROCESS; 1175 bsd_args.who = 0; /* current process */ 1176 bsd_args.prio = args->inc; 1177 return (sys_setpriority(td, &bsd_args)); 1178 } 1179 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1180 1181 int 1182 linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 1183 { 1184 struct ucred *newcred, *oldcred; 1185 l_gid_t *linux_gidset; 1186 gid_t *bsd_gidset; 1187 int ngrp, error; 1188 struct proc *p; 1189 1190 ngrp = args->gidsetsize; 1191 if (ngrp < 0 || ngrp >= ngroups_max + 1) 1192 return (EINVAL); 1193 linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); 1194 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); 1195 if (error) 1196 goto out; 1197 newcred = crget(); 1198 p = td->td_proc; 1199 PROC_LOCK(p); 1200 oldcred = crcopysafe(p, newcred); 1201 1202 /* 1203 * cr_groups[0] holds egid. Setting the whole set from 1204 * the supplied set will cause egid to be changed too. 1205 * Keep cr_groups[0] unchanged to prevent that. 1206 */ 1207 1208 if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { 1209 PROC_UNLOCK(p); 1210 crfree(newcred); 1211 goto out; 1212 } 1213 1214 if (ngrp > 0) { 1215 newcred->cr_ngroups = ngrp + 1; 1216 1217 bsd_gidset = newcred->cr_groups; 1218 ngrp--; 1219 while (ngrp >= 0) { 1220 bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 1221 ngrp--; 1222 } 1223 } else 1224 newcred->cr_ngroups = 1; 1225 1226 setsugid(p); 1227 proc_set_cred(p, newcred); 1228 PROC_UNLOCK(p); 1229 crfree(oldcred); 1230 error = 0; 1231 out: 1232 free(linux_gidset, M_TEMP); 1233 return (error); 1234 } 1235 1236 int 1237 linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 1238 { 1239 struct ucred *cred; 1240 l_gid_t *linux_gidset; 1241 gid_t *bsd_gidset; 1242 int bsd_gidsetsz, ngrp, error; 1243 1244 cred = td->td_ucred; 1245 bsd_gidset = cred->cr_groups; 1246 bsd_gidsetsz = cred->cr_ngroups - 1; 1247 1248 /* 1249 * cr_groups[0] holds egid. Returning the whole set 1250 * here will cause a duplicate. Exclude cr_groups[0] 1251 * to prevent that. 1252 */ 1253 1254 if ((ngrp = args->gidsetsize) == 0) { 1255 td->td_retval[0] = bsd_gidsetsz; 1256 return (0); 1257 } 1258 1259 if (ngrp < bsd_gidsetsz) 1260 return (EINVAL); 1261 1262 ngrp = 0; 1263 linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), 1264 M_TEMP, M_WAITOK); 1265 while (ngrp < bsd_gidsetsz) { 1266 linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 1267 ngrp++; 1268 } 1269 1270 error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); 1271 free(linux_gidset, M_TEMP); 1272 if (error) 1273 return (error); 1274 1275 td->td_retval[0] = ngrp; 1276 return (0); 1277 } 1278 1279 int 1280 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) 1281 { 1282 struct rlimit bsd_rlim; 1283 struct l_rlimit rlim; 1284 u_int which; 1285 int error; 1286 1287 #ifdef DEBUG 1288 if (ldebug(setrlimit)) 1289 printf(ARGS(setrlimit, "%d, %p"), 1290 args->resource, (void *)args->rlim); 1291 #endif 1292 1293 if (args->resource >= LINUX_RLIM_NLIMITS) 1294 return (EINVAL); 1295 1296 which = linux_to_bsd_resource[args->resource]; 1297 if (which == -1) 1298 return (EINVAL); 1299 1300 error = copyin(args->rlim, &rlim, sizeof(rlim)); 1301 if (error) 1302 return (error); 1303 1304 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; 1305 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; 1306 return (kern_setrlimit(td, which, &bsd_rlim)); 1307 } 1308 1309 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1310 int 1311 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) 1312 { 1313 struct l_rlimit rlim; 1314 struct proc *p = td->td_proc; 1315 struct rlimit bsd_rlim; 1316 u_int which; 1317 1318 #ifdef DEBUG 1319 if (ldebug(old_getrlimit)) 1320 printf(ARGS(old_getrlimit, "%d, %p"), 1321 args->resource, (void *)args->rlim); 1322 #endif 1323 1324 if (args->resource >= LINUX_RLIM_NLIMITS) 1325 return (EINVAL); 1326 1327 which = linux_to_bsd_resource[args->resource]; 1328 if (which == -1) 1329 return (EINVAL); 1330 1331 PROC_LOCK(p); 1332 lim_rlimit(p, which, &bsd_rlim); 1333 PROC_UNLOCK(p); 1334 1335 #ifdef COMPAT_LINUX32 1336 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; 1337 if (rlim.rlim_cur == UINT_MAX) 1338 rlim.rlim_cur = INT_MAX; 1339 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; 1340 if (rlim.rlim_max == UINT_MAX) 1341 rlim.rlim_max = INT_MAX; 1342 #else 1343 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; 1344 if (rlim.rlim_cur == ULONG_MAX) 1345 rlim.rlim_cur = LONG_MAX; 1346 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; 1347 if (rlim.rlim_max == ULONG_MAX) 1348 rlim.rlim_max = LONG_MAX; 1349 #endif 1350 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1351 } 1352 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1353 1354 int 1355 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) 1356 { 1357 struct l_rlimit rlim; 1358 struct proc *p = td->td_proc; 1359 struct rlimit bsd_rlim; 1360 u_int which; 1361 1362 #ifdef DEBUG 1363 if (ldebug(getrlimit)) 1364 printf(ARGS(getrlimit, "%d, %p"), 1365 args->resource, (void *)args->rlim); 1366 #endif 1367 1368 if (args->resource >= LINUX_RLIM_NLIMITS) 1369 return (EINVAL); 1370 1371 which = linux_to_bsd_resource[args->resource]; 1372 if (which == -1) 1373 return (EINVAL); 1374 1375 PROC_LOCK(p); 1376 lim_rlimit(p, which, &bsd_rlim); 1377 PROC_UNLOCK(p); 1378 1379 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; 1380 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; 1381 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1382 } 1383 1384 int 1385 linux_sched_setscheduler(struct thread *td, 1386 struct linux_sched_setscheduler_args *args) 1387 { 1388 struct sched_param sched_param; 1389 struct thread *tdt; 1390 int error, policy; 1391 1392 #ifdef DEBUG 1393 if (ldebug(sched_setscheduler)) 1394 printf(ARGS(sched_setscheduler, "%d, %d, %p"), 1395 args->pid, args->policy, (const void *)args->param); 1396 #endif 1397 1398 switch (args->policy) { 1399 case LINUX_SCHED_OTHER: 1400 policy = SCHED_OTHER; 1401 break; 1402 case LINUX_SCHED_FIFO: 1403 policy = SCHED_FIFO; 1404 break; 1405 case LINUX_SCHED_RR: 1406 policy = SCHED_RR; 1407 break; 1408 default: 1409 return (EINVAL); 1410 } 1411 1412 error = copyin(args->param, &sched_param, sizeof(sched_param)); 1413 if (error) 1414 return (error); 1415 1416 tdt = linux_tdfind(td, args->pid, -1); 1417 if (tdt == NULL) 1418 return (ESRCH); 1419 1420 error = kern_sched_setscheduler(td, tdt, policy, &sched_param); 1421 PROC_UNLOCK(tdt->td_proc); 1422 return (error); 1423 } 1424 1425 int 1426 linux_sched_getscheduler(struct thread *td, 1427 struct linux_sched_getscheduler_args *args) 1428 { 1429 struct thread *tdt; 1430 int error, policy; 1431 1432 #ifdef DEBUG 1433 if (ldebug(sched_getscheduler)) 1434 printf(ARGS(sched_getscheduler, "%d"), args->pid); 1435 #endif 1436 1437 tdt = linux_tdfind(td, args->pid, -1); 1438 if (tdt == NULL) 1439 return (ESRCH); 1440 1441 error = kern_sched_getscheduler(td, tdt, &policy); 1442 PROC_UNLOCK(tdt->td_proc); 1443 1444 switch (policy) { 1445 case SCHED_OTHER: 1446 td->td_retval[0] = LINUX_SCHED_OTHER; 1447 break; 1448 case SCHED_FIFO: 1449 td->td_retval[0] = LINUX_SCHED_FIFO; 1450 break; 1451 case SCHED_RR: 1452 td->td_retval[0] = LINUX_SCHED_RR; 1453 break; 1454 } 1455 return (error); 1456 } 1457 1458 int 1459 linux_sched_get_priority_max(struct thread *td, 1460 struct linux_sched_get_priority_max_args *args) 1461 { 1462 struct sched_get_priority_max_args bsd; 1463 1464 #ifdef DEBUG 1465 if (ldebug(sched_get_priority_max)) 1466 printf(ARGS(sched_get_priority_max, "%d"), args->policy); 1467 #endif 1468 1469 switch (args->policy) { 1470 case LINUX_SCHED_OTHER: 1471 bsd.policy = SCHED_OTHER; 1472 break; 1473 case LINUX_SCHED_FIFO: 1474 bsd.policy = SCHED_FIFO; 1475 break; 1476 case LINUX_SCHED_RR: 1477 bsd.policy = SCHED_RR; 1478 break; 1479 default: 1480 return (EINVAL); 1481 } 1482 return (sys_sched_get_priority_max(td, &bsd)); 1483 } 1484 1485 int 1486 linux_sched_get_priority_min(struct thread *td, 1487 struct linux_sched_get_priority_min_args *args) 1488 { 1489 struct sched_get_priority_min_args bsd; 1490 1491 #ifdef DEBUG 1492 if (ldebug(sched_get_priority_min)) 1493 printf(ARGS(sched_get_priority_min, "%d"), args->policy); 1494 #endif 1495 1496 switch (args->policy) { 1497 case LINUX_SCHED_OTHER: 1498 bsd.policy = SCHED_OTHER; 1499 break; 1500 case LINUX_SCHED_FIFO: 1501 bsd.policy = SCHED_FIFO; 1502 break; 1503 case LINUX_SCHED_RR: 1504 bsd.policy = SCHED_RR; 1505 break; 1506 default: 1507 return (EINVAL); 1508 } 1509 return (sys_sched_get_priority_min(td, &bsd)); 1510 } 1511 1512 #define REBOOT_CAD_ON 0x89abcdef 1513 #define REBOOT_CAD_OFF 0 1514 #define REBOOT_HALT 0xcdef0123 1515 #define REBOOT_RESTART 0x01234567 1516 #define REBOOT_RESTART2 0xA1B2C3D4 1517 #define REBOOT_POWEROFF 0x4321FEDC 1518 #define REBOOT_MAGIC1 0xfee1dead 1519 #define REBOOT_MAGIC2 0x28121969 1520 #define REBOOT_MAGIC2A 0x05121996 1521 #define REBOOT_MAGIC2B 0x16041998 1522 1523 int 1524 linux_reboot(struct thread *td, struct linux_reboot_args *args) 1525 { 1526 struct reboot_args bsd_args; 1527 1528 #ifdef DEBUG 1529 if (ldebug(reboot)) 1530 printf(ARGS(reboot, "0x%x"), args->cmd); 1531 #endif 1532 1533 if (args->magic1 != REBOOT_MAGIC1) 1534 return (EINVAL); 1535 1536 switch (args->magic2) { 1537 case REBOOT_MAGIC2: 1538 case REBOOT_MAGIC2A: 1539 case REBOOT_MAGIC2B: 1540 break; 1541 default: 1542 return (EINVAL); 1543 } 1544 1545 switch (args->cmd) { 1546 case REBOOT_CAD_ON: 1547 case REBOOT_CAD_OFF: 1548 return (priv_check(td, PRIV_REBOOT)); 1549 case REBOOT_HALT: 1550 bsd_args.opt = RB_HALT; 1551 break; 1552 case REBOOT_RESTART: 1553 case REBOOT_RESTART2: 1554 bsd_args.opt = 0; 1555 break; 1556 case REBOOT_POWEROFF: 1557 bsd_args.opt = RB_POWEROFF; 1558 break; 1559 default: 1560 return (EINVAL); 1561 } 1562 return (sys_reboot(td, &bsd_args)); 1563 } 1564 1565 1566 /* 1567 * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify 1568 * td->td_retval[1] when COMPAT_43 is defined. This clobbers registers that 1569 * are assumed to be preserved. The following lightweight syscalls fixes 1570 * this. See also linux_getgid16() and linux_getuid16() in linux_uid16.c 1571 * 1572 * linux_getpid() - MP SAFE 1573 * linux_getgid() - MP SAFE 1574 * linux_getuid() - MP SAFE 1575 */ 1576 1577 int 1578 linux_getpid(struct thread *td, struct linux_getpid_args *args) 1579 { 1580 1581 #ifdef DEBUG 1582 if (ldebug(getpid)) 1583 printf(ARGS(getpid, "")); 1584 #endif 1585 td->td_retval[0] = td->td_proc->p_pid; 1586 1587 return (0); 1588 } 1589 1590 int 1591 linux_gettid(struct thread *td, struct linux_gettid_args *args) 1592 { 1593 struct linux_emuldata *em; 1594 1595 #ifdef DEBUG 1596 if (ldebug(gettid)) 1597 printf(ARGS(gettid, "")); 1598 #endif 1599 1600 em = em_find(td); 1601 KASSERT(em != NULL, ("gettid: emuldata not found.\n")); 1602 1603 td->td_retval[0] = em->em_tid; 1604 1605 return (0); 1606 } 1607 1608 1609 int 1610 linux_getppid(struct thread *td, struct linux_getppid_args *args) 1611 { 1612 1613 #ifdef DEBUG 1614 if (ldebug(getppid)) 1615 printf(ARGS(getppid, "")); 1616 #endif 1617 1618 PROC_LOCK(td->td_proc); 1619 td->td_retval[0] = td->td_proc->p_pptr->p_pid; 1620 PROC_UNLOCK(td->td_proc); 1621 return (0); 1622 } 1623 1624 int 1625 linux_getgid(struct thread *td, struct linux_getgid_args *args) 1626 { 1627 1628 #ifdef DEBUG 1629 if (ldebug(getgid)) 1630 printf(ARGS(getgid, "")); 1631 #endif 1632 1633 td->td_retval[0] = td->td_ucred->cr_rgid; 1634 return (0); 1635 } 1636 1637 int 1638 linux_getuid(struct thread *td, struct linux_getuid_args *args) 1639 { 1640 1641 #ifdef DEBUG 1642 if (ldebug(getuid)) 1643 printf(ARGS(getuid, "")); 1644 #endif 1645 1646 td->td_retval[0] = td->td_ucred->cr_ruid; 1647 return (0); 1648 } 1649 1650 1651 int 1652 linux_getsid(struct thread *td, struct linux_getsid_args *args) 1653 { 1654 struct getsid_args bsd; 1655 1656 #ifdef DEBUG 1657 if (ldebug(getsid)) 1658 printf(ARGS(getsid, "%i"), args->pid); 1659 #endif 1660 1661 bsd.pid = args->pid; 1662 return (sys_getsid(td, &bsd)); 1663 } 1664 1665 int 1666 linux_nosys(struct thread *td, struct nosys_args *ignore) 1667 { 1668 1669 return (ENOSYS); 1670 } 1671 1672 int 1673 linux_getpriority(struct thread *td, struct linux_getpriority_args *args) 1674 { 1675 struct getpriority_args bsd_args; 1676 int error; 1677 1678 #ifdef DEBUG 1679 if (ldebug(getpriority)) 1680 printf(ARGS(getpriority, "%i, %i"), args->which, args->who); 1681 #endif 1682 1683 bsd_args.which = args->which; 1684 bsd_args.who = args->who; 1685 error = sys_getpriority(td, &bsd_args); 1686 td->td_retval[0] = 20 - td->td_retval[0]; 1687 return (error); 1688 } 1689 1690 int 1691 linux_sethostname(struct thread *td, struct linux_sethostname_args *args) 1692 { 1693 int name[2]; 1694 1695 #ifdef DEBUG 1696 if (ldebug(sethostname)) 1697 printf(ARGS(sethostname, "*, %i"), args->len); 1698 #endif 1699 1700 name[0] = CTL_KERN; 1701 name[1] = KERN_HOSTNAME; 1702 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, 1703 args->len, 0, 0)); 1704 } 1705 1706 int 1707 linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args) 1708 { 1709 int name[2]; 1710 1711 #ifdef DEBUG 1712 if (ldebug(setdomainname)) 1713 printf(ARGS(setdomainname, "*, %i"), args->len); 1714 #endif 1715 1716 name[0] = CTL_KERN; 1717 name[1] = KERN_NISDOMAINNAME; 1718 return (userland_sysctl(td, name, 2, 0, 0, 0, args->name, 1719 args->len, 0, 0)); 1720 } 1721 1722 int 1723 linux_exit_group(struct thread *td, struct linux_exit_group_args *args) 1724 { 1725 1726 #ifdef DEBUG 1727 if (ldebug(exit_group)) 1728 printf(ARGS(exit_group, "%i"), args->error_code); 1729 #endif 1730 1731 LINUX_CTR2(exit_group, "thread(%d) (%d)", td->td_tid, 1732 args->error_code); 1733 1734 /* 1735 * XXX: we should send a signal to the parent if 1736 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?) 1737 * as it doesnt occur often. 1738 */ 1739 exit1(td, W_EXITCODE(args->error_code, 0)); 1740 /* NOTREACHED */ 1741 } 1742 1743 #define _LINUX_CAPABILITY_VERSION 0x19980330 1744 1745 struct l_user_cap_header { 1746 l_int version; 1747 l_int pid; 1748 }; 1749 1750 struct l_user_cap_data { 1751 l_int effective; 1752 l_int permitted; 1753 l_int inheritable; 1754 }; 1755 1756 int 1757 linux_capget(struct thread *td, struct linux_capget_args *args) 1758 { 1759 struct l_user_cap_header luch; 1760 struct l_user_cap_data lucd; 1761 int error; 1762 1763 if (args->hdrp == NULL) 1764 return (EFAULT); 1765 1766 error = copyin(args->hdrp, &luch, sizeof(luch)); 1767 if (error != 0) 1768 return (error); 1769 1770 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1771 luch.version = _LINUX_CAPABILITY_VERSION; 1772 error = copyout(&luch, args->hdrp, sizeof(luch)); 1773 if (error) 1774 return (error); 1775 return (EINVAL); 1776 } 1777 1778 if (luch.pid) 1779 return (EPERM); 1780 1781 if (args->datap) { 1782 /* 1783 * The current implementation doesn't support setting 1784 * a capability (it's essentially a stub) so indicate 1785 * that no capabilities are currently set or available 1786 * to request. 1787 */ 1788 bzero (&lucd, sizeof(lucd)); 1789 error = copyout(&lucd, args->datap, sizeof(lucd)); 1790 } 1791 1792 return (error); 1793 } 1794 1795 int 1796 linux_capset(struct thread *td, struct linux_capset_args *args) 1797 { 1798 struct l_user_cap_header luch; 1799 struct l_user_cap_data lucd; 1800 int error; 1801 1802 if (args->hdrp == NULL || args->datap == NULL) 1803 return (EFAULT); 1804 1805 error = copyin(args->hdrp, &luch, sizeof(luch)); 1806 if (error != 0) 1807 return (error); 1808 1809 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1810 luch.version = _LINUX_CAPABILITY_VERSION; 1811 error = copyout(&luch, args->hdrp, sizeof(luch)); 1812 if (error) 1813 return (error); 1814 return (EINVAL); 1815 } 1816 1817 if (luch.pid) 1818 return (EPERM); 1819 1820 error = copyin(args->datap, &lucd, sizeof(lucd)); 1821 if (error != 0) 1822 return (error); 1823 1824 /* We currently don't support setting any capabilities. */ 1825 if (lucd.effective || lucd.permitted || lucd.inheritable) { 1826 linux_msg(td, 1827 "capset effective=0x%x, permitted=0x%x, " 1828 "inheritable=0x%x is not implemented", 1829 (int)lucd.effective, (int)lucd.permitted, 1830 (int)lucd.inheritable); 1831 return (EPERM); 1832 } 1833 1834 return (0); 1835 } 1836 1837 int 1838 linux_prctl(struct thread *td, struct linux_prctl_args *args) 1839 { 1840 int error = 0, max_size; 1841 struct proc *p = td->td_proc; 1842 char comm[LINUX_MAX_COMM_LEN]; 1843 struct linux_emuldata *em; 1844 int pdeath_signal; 1845 1846 #ifdef DEBUG 1847 if (ldebug(prctl)) 1848 printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option, 1849 args->arg2, args->arg3, args->arg4, args->arg5); 1850 #endif 1851 1852 switch (args->option) { 1853 case LINUX_PR_SET_PDEATHSIG: 1854 if (!LINUX_SIG_VALID(args->arg2)) 1855 return (EINVAL); 1856 em = em_find(td); 1857 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1858 em->pdeath_signal = args->arg2; 1859 break; 1860 case LINUX_PR_GET_PDEATHSIG: 1861 em = em_find(td); 1862 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1863 pdeath_signal = em->pdeath_signal; 1864 error = copyout(&pdeath_signal, 1865 (void *)(register_t)args->arg2, 1866 sizeof(pdeath_signal)); 1867 break; 1868 case LINUX_PR_GET_KEEPCAPS: 1869 /* 1870 * Indicate that we always clear the effective and 1871 * permitted capability sets when the user id becomes 1872 * non-zero (actually the capability sets are simply 1873 * always zero in the current implementation). 1874 */ 1875 td->td_retval[0] = 0; 1876 break; 1877 case LINUX_PR_SET_KEEPCAPS: 1878 /* 1879 * Ignore requests to keep the effective and permitted 1880 * capability sets when the user id becomes non-zero. 1881 */ 1882 break; 1883 case LINUX_PR_SET_NAME: 1884 /* 1885 * To be on the safe side we need to make sure to not 1886 * overflow the size a linux program expects. We already 1887 * do this here in the copyin, so that we don't need to 1888 * check on copyout. 1889 */ 1890 max_size = MIN(sizeof(comm), sizeof(p->p_comm)); 1891 error = copyinstr((void *)(register_t)args->arg2, comm, 1892 max_size, NULL); 1893 1894 /* Linux silently truncates the name if it is too long. */ 1895 if (error == ENAMETOOLONG) { 1896 /* 1897 * XXX: copyinstr() isn't documented to populate the 1898 * array completely, so do a copyin() to be on the 1899 * safe side. This should be changed in case 1900 * copyinstr() is changed to guarantee this. 1901 */ 1902 error = copyin((void *)(register_t)args->arg2, comm, 1903 max_size - 1); 1904 comm[max_size - 1] = '\0'; 1905 } 1906 if (error) 1907 return (error); 1908 1909 PROC_LOCK(p); 1910 strlcpy(p->p_comm, comm, sizeof(p->p_comm)); 1911 PROC_UNLOCK(p); 1912 break; 1913 case LINUX_PR_GET_NAME: 1914 PROC_LOCK(p); 1915 strlcpy(comm, p->p_comm, sizeof(comm)); 1916 PROC_UNLOCK(p); 1917 error = copyout(comm, (void *)(register_t)args->arg2, 1918 strlen(comm) + 1); 1919 break; 1920 default: 1921 error = EINVAL; 1922 break; 1923 } 1924 1925 return (error); 1926 } 1927 1928 int 1929 linux_sched_setparam(struct thread *td, 1930 struct linux_sched_setparam_args *uap) 1931 { 1932 struct sched_param sched_param; 1933 struct thread *tdt; 1934 int error; 1935 1936 #ifdef DEBUG 1937 if (ldebug(sched_setparam)) 1938 printf(ARGS(sched_setparam, "%d, *"), uap->pid); 1939 #endif 1940 1941 error = copyin(uap->param, &sched_param, sizeof(sched_param)); 1942 if (error) 1943 return (error); 1944 1945 tdt = linux_tdfind(td, uap->pid, -1); 1946 if (tdt == NULL) 1947 return (ESRCH); 1948 1949 error = kern_sched_setparam(td, tdt, &sched_param); 1950 PROC_UNLOCK(tdt->td_proc); 1951 return (error); 1952 } 1953 1954 int 1955 linux_sched_getparam(struct thread *td, 1956 struct linux_sched_getparam_args *uap) 1957 { 1958 struct sched_param sched_param; 1959 struct thread *tdt; 1960 int error; 1961 1962 #ifdef DEBUG 1963 if (ldebug(sched_getparam)) 1964 printf(ARGS(sched_getparam, "%d, *"), uap->pid); 1965 #endif 1966 1967 tdt = linux_tdfind(td, uap->pid, -1); 1968 if (tdt == NULL) 1969 return (ESRCH); 1970 1971 error = kern_sched_getparam(td, tdt, &sched_param); 1972 PROC_UNLOCK(tdt->td_proc); 1973 if (error == 0) 1974 error = copyout(&sched_param, uap->param, 1975 sizeof(sched_param)); 1976 return (error); 1977 } 1978 1979 /* 1980 * Get affinity of a process. 1981 */ 1982 int 1983 linux_sched_getaffinity(struct thread *td, 1984 struct linux_sched_getaffinity_args *args) 1985 { 1986 int error; 1987 struct thread *tdt; 1988 struct cpuset_getaffinity_args cga; 1989 1990 #ifdef DEBUG 1991 if (ldebug(sched_getaffinity)) 1992 printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid, 1993 args->len); 1994 #endif 1995 if (args->len < sizeof(cpuset_t)) 1996 return (EINVAL); 1997 1998 tdt = linux_tdfind(td, args->pid, -1); 1999 if (tdt == NULL) 2000 return (ESRCH); 2001 2002 PROC_UNLOCK(tdt->td_proc); 2003 cga.level = CPU_LEVEL_WHICH; 2004 cga.which = CPU_WHICH_TID; 2005 cga.id = tdt->td_tid; 2006 cga.cpusetsize = sizeof(cpuset_t); 2007 cga.mask = (cpuset_t *) args->user_mask_ptr; 2008 2009 if ((error = sys_cpuset_getaffinity(td, &cga)) == 0) 2010 td->td_retval[0] = sizeof(cpuset_t); 2011 2012 return (error); 2013 } 2014 2015 /* 2016 * Set affinity of a process. 2017 */ 2018 int 2019 linux_sched_setaffinity(struct thread *td, 2020 struct linux_sched_setaffinity_args *args) 2021 { 2022 struct cpuset_setaffinity_args csa; 2023 struct thread *tdt; 2024 2025 #ifdef DEBUG 2026 if (ldebug(sched_setaffinity)) 2027 printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid, 2028 args->len); 2029 #endif 2030 if (args->len < sizeof(cpuset_t)) 2031 return (EINVAL); 2032 2033 tdt = linux_tdfind(td, args->pid, -1); 2034 if (tdt == NULL) 2035 return (ESRCH); 2036 2037 PROC_UNLOCK(tdt->td_proc); 2038 csa.level = CPU_LEVEL_WHICH; 2039 csa.which = CPU_WHICH_TID; 2040 csa.id = tdt->td_tid; 2041 csa.cpusetsize = sizeof(cpuset_t); 2042 csa.mask = (cpuset_t *) args->user_mask_ptr; 2043 2044 return (sys_cpuset_setaffinity(td, &csa)); 2045 } 2046 2047 struct linux_rlimit64 { 2048 uint64_t rlim_cur; 2049 uint64_t rlim_max; 2050 }; 2051 2052 int 2053 linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args) 2054 { 2055 struct rlimit rlim, nrlim; 2056 struct linux_rlimit64 lrlim; 2057 struct proc *p; 2058 u_int which; 2059 int flags; 2060 int error; 2061 2062 #ifdef DEBUG 2063 if (ldebug(prlimit64)) 2064 printf(ARGS(prlimit64, "%d, %d, %p, %p"), args->pid, 2065 args->resource, (void *)args->new, (void *)args->old); 2066 #endif 2067 2068 if (args->resource >= LINUX_RLIM_NLIMITS) 2069 return (EINVAL); 2070 2071 which = linux_to_bsd_resource[args->resource]; 2072 if (which == -1) 2073 return (EINVAL); 2074 2075 if (args->new != NULL) { 2076 /* 2077 * Note. Unlike FreeBSD where rlim is signed 64-bit Linux 2078 * rlim is unsigned 64-bit. FreeBSD treats negative limits 2079 * as INFINITY so we do not need a conversion even. 2080 */ 2081 error = copyin(args->new, &nrlim, sizeof(nrlim)); 2082 if (error != 0) 2083 return (error); 2084 } 2085 2086 flags = PGET_HOLD | PGET_NOTWEXIT; 2087 if (args->new != NULL) 2088 flags |= PGET_CANDEBUG; 2089 else 2090 flags |= PGET_CANSEE; 2091 error = pget(args->pid, flags, &p); 2092 if (error != 0) 2093 return (error); 2094 2095 if (args->old != NULL) { 2096 PROC_LOCK(p); 2097 lim_rlimit(p, which, &rlim); 2098 PROC_UNLOCK(p); 2099 if (rlim.rlim_cur == RLIM_INFINITY) 2100 lrlim.rlim_cur = LINUX_RLIM_INFINITY; 2101 else 2102 lrlim.rlim_cur = rlim.rlim_cur; 2103 if (rlim.rlim_max == RLIM_INFINITY) 2104 lrlim.rlim_max = LINUX_RLIM_INFINITY; 2105 else 2106 lrlim.rlim_max = rlim.rlim_max; 2107 error = copyout(&lrlim, args->old, sizeof(lrlim)); 2108 if (error != 0) 2109 goto out; 2110 } 2111 2112 if (args->new != NULL) 2113 error = kern_proc_setrlimit(td, p, which, &nrlim); 2114 2115 out: 2116 PRELE(p); 2117 return (error); 2118 } 2119 2120 int 2121 linux_pselect6(struct thread *td, struct linux_pselect6_args *args) 2122 { 2123 struct timeval utv, tv0, tv1, *tvp; 2124 struct l_pselect6arg lpse6; 2125 struct l_timespec lts; 2126 struct timespec uts; 2127 l_sigset_t l_ss; 2128 sigset_t *ssp; 2129 sigset_t ss; 2130 int error; 2131 2132 ssp = NULL; 2133 if (args->sig != NULL) { 2134 error = copyin(args->sig, &lpse6, sizeof(lpse6)); 2135 if (error != 0) 2136 return (error); 2137 if (lpse6.ss_len != sizeof(l_ss)) 2138 return (EINVAL); 2139 if (lpse6.ss != 0) { 2140 error = copyin(PTRIN(lpse6.ss), &l_ss, 2141 sizeof(l_ss)); 2142 if (error != 0) 2143 return (error); 2144 linux_to_bsd_sigset(&l_ss, &ss); 2145 ssp = &ss; 2146 } 2147 } 2148 2149 /* 2150 * Currently glibc changes nanosecond number to microsecond. 2151 * This mean losing precision but for now it is hardly seen. 2152 */ 2153 if (args->tsp != NULL) { 2154 error = copyin(args->tsp, <s, sizeof(lts)); 2155 if (error != 0) 2156 return (error); 2157 uts.tv_sec = lts.tv_sec; 2158 uts.tv_nsec = lts.tv_nsec; 2159 2160 TIMESPEC_TO_TIMEVAL(&utv, &uts); 2161 if (itimerfix(&utv)) 2162 return (EINVAL); 2163 2164 microtime(&tv0); 2165 tvp = &utv; 2166 } else 2167 tvp = NULL; 2168 2169 error = kern_pselect(td, args->nfds, args->readfds, args->writefds, 2170 args->exceptfds, tvp, ssp, sizeof(l_int) * 8); 2171 2172 if (error == 0 && args->tsp != NULL) { 2173 if (td->td_retval[0] != 0) { 2174 /* 2175 * Compute how much time was left of the timeout, 2176 * by subtracting the current time and the time 2177 * before we started the call, and subtracting 2178 * that result from the user-supplied value. 2179 */ 2180 2181 microtime(&tv1); 2182 timevalsub(&tv1, &tv0); 2183 timevalsub(&utv, &tv1); 2184 if (utv.tv_sec < 0) 2185 timevalclear(&utv); 2186 } else 2187 timevalclear(&utv); 2188 2189 TIMEVAL_TO_TIMESPEC(&utv, &uts); 2190 lts.tv_sec = uts.tv_sec; 2191 lts.tv_nsec = uts.tv_nsec; 2192 error = copyout(<s, args->tsp, sizeof(lts)); 2193 } 2194 2195 return (error); 2196 } 2197 2198 int 2199 linux_sched_rr_get_interval(struct thread *td, 2200 struct linux_sched_rr_get_interval_args *uap) 2201 { 2202 struct timespec ts; 2203 struct l_timespec lts; 2204 struct thread *tdt; 2205 int error; 2206 2207 /* 2208 * According to man in case the invalid pid specified 2209 * EINVAL should be returned. 2210 */ 2211 if (uap->pid < 0) 2212 return (EINVAL); 2213 2214 tdt = linux_tdfind(td, uap->pid, -1); 2215 if (tdt == NULL) 2216 return (ESRCH); 2217 2218 error = kern_sched_rr_get_interval_td(td, tdt, &ts); 2219 PROC_UNLOCK(tdt->td_proc); 2220 if (error != 0) 2221 return (error); 2222 lts.tv_sec = ts.tv_sec; 2223 lts.tv_nsec = ts.tv_nsec; 2224 return (copyout(<s, uap->interval, sizeof(lts))); 2225 } 2226 2227 /* 2228 * In case when the Linux thread is the initial thread in 2229 * the thread group thread id is equal to the process id. 2230 * Glibc depends on this magic (assert in pthread_getattr_np.c). 2231 */ 2232 struct thread * 2233 linux_tdfind(struct thread *td, lwpid_t tid, pid_t pid) 2234 { 2235 struct linux_emuldata *em; 2236 struct thread *tdt; 2237 struct proc *p; 2238 2239 tdt = NULL; 2240 if (tid == 0 || tid == td->td_tid) { 2241 tdt = td; 2242 PROC_LOCK(tdt->td_proc); 2243 } else if (tid > PID_MAX) 2244 tdt = tdfind(tid, pid); 2245 else { 2246 /* 2247 * Initial thread where the tid equal to the pid. 2248 */ 2249 p = pfind(tid); 2250 if (p != NULL) { 2251 if (SV_PROC_ABI(p) != SV_ABI_LINUX) { 2252 /* 2253 * p is not a Linuxulator process. 2254 */ 2255 PROC_UNLOCK(p); 2256 return (NULL); 2257 } 2258 FOREACH_THREAD_IN_PROC(p, tdt) { 2259 em = em_find(tdt); 2260 if (tid == em->em_tid) 2261 return (tdt); 2262 } 2263 PROC_UNLOCK(p); 2264 } 2265 return (NULL); 2266 } 2267 2268 return (tdt); 2269 } 2270 2271 void 2272 linux_to_bsd_waitopts(int options, int *bsdopts) 2273 { 2274 2275 if (options & LINUX_WNOHANG) 2276 *bsdopts |= WNOHANG; 2277 if (options & LINUX_WUNTRACED) 2278 *bsdopts |= WUNTRACED; 2279 if (options & LINUX_WEXITED) 2280 *bsdopts |= WEXITED; 2281 if (options & LINUX_WCONTINUED) 2282 *bsdopts |= WCONTINUED; 2283 if (options & LINUX_WNOWAIT) 2284 *bsdopts |= WNOWAIT; 2285 2286 if (options & __WCLONE) 2287 *bsdopts |= WLINUXCLONE; 2288 } 2289