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 #include "opt_mac.h" 35 36 #include <sys/param.h> 37 #include <sys/blist.h> 38 #include <sys/fcntl.h> 39 #if defined(__i386__) 40 #include <sys/imgact_aout.h> 41 #endif 42 #include <sys/jail.h> 43 #include <sys/kernel.h> 44 #include <sys/limits.h> 45 #include <sys/lock.h> 46 #include <sys/malloc.h> 47 #include <sys/mman.h> 48 #include <sys/mount.h> 49 #include <sys/mutex.h> 50 #include <sys/namei.h> 51 #include <sys/priv.h> 52 #include <sys/proc.h> 53 #include <sys/reboot.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 #include <sys/vimage.h> 68 69 #include <security/mac/mac_framework.h> 70 71 #include <vm/vm.h> 72 #include <vm/pmap.h> 73 #include <vm/vm_kern.h> 74 #include <vm/vm_map.h> 75 #include <vm/vm_extern.h> 76 #include <vm/vm_object.h> 77 #include <vm/swap_pager.h> 78 79 #ifdef COMPAT_LINUX32 80 #include <machine/../linux32/linux.h> 81 #include <machine/../linux32/linux32_proto.h> 82 #else 83 #include <machine/../linux/linux.h> 84 #include <machine/../linux/linux_proto.h> 85 #endif 86 87 #include <compat/linux/linux_file.h> 88 #include <compat/linux/linux_mib.h> 89 #include <compat/linux/linux_signal.h> 90 #include <compat/linux/linux_util.h> 91 #include <compat/linux/linux_sysproto.h> 92 #include <compat/linux/linux_emul.h> 93 #include <compat/linux/linux_misc.h> 94 95 #ifdef __i386__ 96 #include <machine/cputypes.h> 97 #endif 98 99 #define BSD_TO_LINUX_SIGNAL(sig) \ 100 (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) 101 102 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { 103 RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 104 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 105 RLIMIT_MEMLOCK, RLIMIT_AS 106 }; 107 108 struct l_sysinfo { 109 l_long uptime; /* Seconds since boot */ 110 l_ulong loads[3]; /* 1, 5, and 15 minute load averages */ 111 #define LINUX_SYSINFO_LOADS_SCALE 65536 112 l_ulong totalram; /* Total usable main memory size */ 113 l_ulong freeram; /* Available memory size */ 114 l_ulong sharedram; /* Amount of shared memory */ 115 l_ulong bufferram; /* Memory used by buffers */ 116 l_ulong totalswap; /* Total swap space size */ 117 l_ulong freeswap; /* swap space still available */ 118 l_ushort procs; /* Number of current processes */ 119 l_ushort pads; 120 l_ulong totalbig; 121 l_ulong freebig; 122 l_uint mem_unit; 123 char _f[20-2*sizeof(l_long)-sizeof(l_int)]; /* padding */ 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 - 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) && !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 vm_offset_t buffer; 239 unsigned long bss_size; 240 char *library; 241 int error; 242 int locked, vfslocked; 243 244 LCONVPATHEXIST(td, args->library, &library); 245 246 #ifdef DEBUG 247 if (ldebug(uselib)) 248 printf(ARGS(uselib, "%s"), library); 249 #endif 250 251 a_out = NULL; 252 vfslocked = 0; 253 locked = 0; 254 vp = NULL; 255 256 NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 257 UIO_SYSSPACE, library, td); 258 error = namei(&ni); 259 LFREEPATH(library); 260 if (error) 261 goto cleanup; 262 263 vp = ni.ni_vp; 264 vfslocked = NDHASGIANT(&ni); 265 NDFREE(&ni, NDF_ONLY_PNBUF); 266 267 /* 268 * From here on down, we have a locked vnode that must be unlocked. 269 * XXX: The code below largely duplicates exec_check_permissions(). 270 */ 271 locked = 1; 272 273 /* Writable? */ 274 if (vp->v_writecount) { 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, FREAD); 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 kernel_map */ 318 error = vm_mmap(kernel_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 PROC_UNLOCK(td->td_proc); 369 error = ENOMEM; 370 goto cleanup; 371 } 372 PROC_UNLOCK(td->td_proc); 373 374 /* 375 * Prevent more writers. 376 * XXX: Note that if any of the VM operations fail below we don't 377 * clear this flag. 378 */ 379 vp->v_vflag |= VV_TEXT; 380 381 /* 382 * Lock no longer needed 383 */ 384 locked = 0; 385 VOP_UNLOCK(vp, 0); 386 VFS_UNLOCK_GIANT(vfslocked); 387 388 /* 389 * Check if file_offset page aligned. Currently we cannot handle 390 * misalinged file offsets, and so we read in the entire image 391 * (what a waste). 392 */ 393 if (file_offset & PAGE_MASK) { 394 #ifdef DEBUG 395 printf("uselib: Non page aligned binary %lu\n", file_offset); 396 #endif 397 /* Map text+data read/write/execute */ 398 399 /* a_entry is the load address and is page aligned */ 400 vmaddr = trunc_page(a_out->a_entry); 401 402 /* get anon user mapping, read+write+execute */ 403 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, 404 &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, 405 VM_PROT_ALL, 0); 406 if (error) 407 goto cleanup; 408 409 /* map file into kernel_map */ 410 error = vm_mmap(kernel_map, &buffer, 411 round_page(a_out->a_text + a_out->a_data + file_offset), 412 VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 413 trunc_page(file_offset)); 414 if (error) 415 goto cleanup; 416 417 /* copy from kernel VM space to user space */ 418 error = copyout(PTRIN(buffer + file_offset), 419 (void *)vmaddr, a_out->a_text + a_out->a_data); 420 421 /* release temporary kernel space */ 422 vm_map_remove(kernel_map, buffer, buffer + 423 round_page(a_out->a_text + a_out->a_data + file_offset)); 424 425 if (error) 426 goto cleanup; 427 } else { 428 #ifdef DEBUG 429 printf("uselib: Page aligned binary %lu\n", file_offset); 430 #endif 431 /* 432 * for QMAGIC, a_entry is 20 bytes beyond the load address 433 * to skip the executable header 434 */ 435 vmaddr = trunc_page(a_out->a_entry); 436 437 /* 438 * Map it all into the process's space as a single 439 * copy-on-write "data" segment. 440 */ 441 error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr, 442 a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, 443 MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); 444 if (error) 445 goto cleanup; 446 } 447 #ifdef DEBUG 448 printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long *)vmaddr)[0], 449 ((long *)vmaddr)[1]); 450 #endif 451 if (bss_size != 0) { 452 /* Calculate BSS start address */ 453 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + 454 a_out->a_data; 455 456 /* allocate some 'anon' space */ 457 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, 458 &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 459 if (error) 460 goto cleanup; 461 } 462 463 cleanup: 464 /* Unlock vnode if needed */ 465 if (locked) { 466 VOP_UNLOCK(vp, 0); 467 VFS_UNLOCK_GIANT(vfslocked); 468 } 469 470 /* Release the kernel mapping. */ 471 if (a_out) 472 vm_map_remove(kernel_map, (vm_offset_t)a_out, 473 (vm_offset_t)a_out + PAGE_SIZE); 474 475 return error; 476 } 477 478 #endif /* __i386__ */ 479 480 int 481 linux_select(struct thread *td, struct linux_select_args *args) 482 { 483 l_timeval ltv; 484 struct timeval tv0, tv1, utv, *tvp; 485 int error; 486 487 #ifdef DEBUG 488 if (ldebug(select)) 489 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, 490 (void *)args->readfds, (void *)args->writefds, 491 (void *)args->exceptfds, (void *)args->timeout); 492 #endif 493 494 /* 495 * Store current time for computation of the amount of 496 * time left. 497 */ 498 if (args->timeout) { 499 if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 500 goto select_out; 501 utv.tv_sec = ltv.tv_sec; 502 utv.tv_usec = ltv.tv_usec; 503 #ifdef DEBUG 504 if (ldebug(select)) 505 printf(LMSG("incoming timeout (%jd/%ld)"), 506 (intmax_t)utv.tv_sec, utv.tv_usec); 507 #endif 508 509 if (itimerfix(&utv)) { 510 /* 511 * The timeval was invalid. Convert it to something 512 * valid that will act as it does under Linux. 513 */ 514 utv.tv_sec += utv.tv_usec / 1000000; 515 utv.tv_usec %= 1000000; 516 if (utv.tv_usec < 0) { 517 utv.tv_sec -= 1; 518 utv.tv_usec += 1000000; 519 } 520 if (utv.tv_sec < 0) 521 timevalclear(&utv); 522 } 523 microtime(&tv0); 524 tvp = &utv; 525 } else 526 tvp = NULL; 527 528 error = kern_select(td, args->nfds, args->readfds, args->writefds, 529 args->exceptfds, tvp); 530 531 #ifdef DEBUG 532 if (ldebug(select)) 533 printf(LMSG("real select returns %d"), error); 534 #endif 535 if (error) { 536 /* 537 * See fs/select.c in the Linux kernel. Without this, 538 * Maelstrom doesn't work. 539 */ 540 if (error == ERESTART) 541 error = EINTR; 542 goto select_out; 543 } 544 545 if (args->timeout) { 546 if (td->td_retval[0]) { 547 /* 548 * Compute how much time was left of the timeout, 549 * by subtracting the current time and the time 550 * before we started the call, and subtracting 551 * that result from the user-supplied value. 552 */ 553 microtime(&tv1); 554 timevalsub(&tv1, &tv0); 555 timevalsub(&utv, &tv1); 556 if (utv.tv_sec < 0) 557 timevalclear(&utv); 558 } else 559 timevalclear(&utv); 560 #ifdef DEBUG 561 if (ldebug(select)) 562 printf(LMSG("outgoing timeout (%jd/%ld)"), 563 (intmax_t)utv.tv_sec, utv.tv_usec); 564 #endif 565 ltv.tv_sec = utv.tv_sec; 566 ltv.tv_usec = utv.tv_usec; 567 if ((error = copyout(<v, args->timeout, sizeof(ltv)))) 568 goto select_out; 569 } 570 571 select_out: 572 #ifdef DEBUG 573 if (ldebug(select)) 574 printf(LMSG("select_out -> %d"), error); 575 #endif 576 return error; 577 } 578 579 int 580 linux_mremap(struct thread *td, struct linux_mremap_args *args) 581 { 582 struct munmap_args /* { 583 void *addr; 584 size_t len; 585 } */ bsd_args; 586 int error = 0; 587 588 #ifdef DEBUG 589 if (ldebug(mremap)) 590 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), 591 (void *)(uintptr_t)args->addr, 592 (unsigned long)args->old_len, 593 (unsigned long)args->new_len, 594 (unsigned long)args->flags); 595 #endif 596 597 if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) { 598 td->td_retval[0] = 0; 599 return (EINVAL); 600 } 601 602 /* 603 * Check for the page alignment. 604 * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK. 605 */ 606 if (args->addr & PAGE_MASK) { 607 td->td_retval[0] = 0; 608 return (EINVAL); 609 } 610 611 args->new_len = round_page(args->new_len); 612 args->old_len = round_page(args->old_len); 613 614 if (args->new_len > args->old_len) { 615 td->td_retval[0] = 0; 616 return ENOMEM; 617 } 618 619 if (args->new_len < args->old_len) { 620 bsd_args.addr = 621 (caddr_t)((uintptr_t)args->addr + args->new_len); 622 bsd_args.len = args->old_len - args->new_len; 623 error = munmap(td, &bsd_args); 624 } 625 626 td->td_retval[0] = error ? 0 : (uintptr_t)args->addr; 627 return error; 628 } 629 630 #define LINUX_MS_ASYNC 0x0001 631 #define LINUX_MS_INVALIDATE 0x0002 632 #define LINUX_MS_SYNC 0x0004 633 634 int 635 linux_msync(struct thread *td, struct linux_msync_args *args) 636 { 637 struct msync_args bsd_args; 638 639 bsd_args.addr = (caddr_t)(uintptr_t)args->addr; 640 bsd_args.len = (uintptr_t)args->len; 641 bsd_args.flags = args->fl & ~LINUX_MS_SYNC; 642 643 return msync(td, &bsd_args); 644 } 645 646 int 647 linux_time(struct thread *td, struct linux_time_args *args) 648 { 649 struct timeval tv; 650 l_time_t tm; 651 int error; 652 653 #ifdef DEBUG 654 if (ldebug(time)) 655 printf(ARGS(time, "*")); 656 #endif 657 658 microtime(&tv); 659 tm = tv.tv_sec; 660 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) 661 return error; 662 td->td_retval[0] = tm; 663 return 0; 664 } 665 666 struct l_times_argv { 667 l_long tms_utime; 668 l_long tms_stime; 669 l_long tms_cutime; 670 l_long tms_cstime; 671 }; 672 673 #define CLK_TCK 100 /* Linux uses 100 */ 674 675 #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 676 677 int 678 linux_times(struct thread *td, struct linux_times_args *args) 679 { 680 struct timeval tv, utime, stime, cutime, cstime; 681 struct l_times_argv tms; 682 struct proc *p; 683 int error; 684 685 #ifdef DEBUG 686 if (ldebug(times)) 687 printf(ARGS(times, "*")); 688 #endif 689 690 if (args->buf != NULL) { 691 p = td->td_proc; 692 PROC_LOCK(p); 693 PROC_SLOCK(p); 694 calcru(p, &utime, &stime); 695 PROC_SUNLOCK(p); 696 calccru(p, &cutime, &cstime); 697 PROC_UNLOCK(p); 698 699 tms.tms_utime = CONVTCK(utime); 700 tms.tms_stime = CONVTCK(stime); 701 702 tms.tms_cutime = CONVTCK(cutime); 703 tms.tms_cstime = CONVTCK(cstime); 704 705 if ((error = copyout(&tms, args->buf, sizeof(tms)))) 706 return error; 707 } 708 709 microuptime(&tv); 710 td->td_retval[0] = (int)CONVTCK(tv); 711 return 0; 712 } 713 714 int 715 linux_newuname(struct thread *td, struct linux_newuname_args *args) 716 { 717 struct l_new_utsname utsname; 718 char osname[LINUX_MAX_UTSNAME]; 719 char osrelease[LINUX_MAX_UTSNAME]; 720 char *p; 721 722 #ifdef DEBUG 723 if (ldebug(newuname)) 724 printf(ARGS(newuname, "*")); 725 #endif 726 727 linux_get_osname(td, osname); 728 linux_get_osrelease(td, osrelease); 729 730 bzero(&utsname, sizeof(utsname)); 731 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); 732 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); 733 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); 734 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); 735 for (p = utsname.version; *p != '\0'; ++p) 736 if (*p == '\n') { 737 *p = '\0'; 738 break; 739 } 740 #ifdef __i386__ 741 { 742 const char *class; 743 744 switch (cpu_class) { 745 case CPUCLASS_686: 746 class = "i686"; 747 break; 748 case CPUCLASS_586: 749 class = "i586"; 750 break; 751 case CPUCLASS_486: 752 class = "i486"; 753 break; 754 default: 755 class = "i386"; 756 } 757 strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME); 758 } 759 #elif defined(__amd64__) /* XXX: Linux can change 'personality'. */ 760 #ifdef COMPAT_LINUX32 761 strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME); 762 #else 763 strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME); 764 #endif /* COMPAT_LINUX32 */ 765 #else /* something other than i386 or amd64 - assume we and Linux agree */ 766 strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME); 767 #endif /* __i386__ */ 768 mtx_lock(&hostname_mtx); 769 strlcpy(utsname.domainname, V_domainname, LINUX_MAX_UTSNAME); 770 mtx_unlock(&hostname_mtx); 771 772 return (copyout(&utsname, args->buf, sizeof(utsname))); 773 } 774 775 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 776 struct l_utimbuf { 777 l_time_t l_actime; 778 l_time_t l_modtime; 779 }; 780 781 int 782 linux_utime(struct thread *td, struct linux_utime_args *args) 783 { 784 struct timeval tv[2], *tvp; 785 struct l_utimbuf lut; 786 char *fname; 787 int error; 788 789 LCONVPATHEXIST(td, args->fname, &fname); 790 791 #ifdef DEBUG 792 if (ldebug(utime)) 793 printf(ARGS(utime, "%s, *"), fname); 794 #endif 795 796 if (args->times) { 797 if ((error = copyin(args->times, &lut, sizeof lut))) { 798 LFREEPATH(fname); 799 return error; 800 } 801 tv[0].tv_sec = lut.l_actime; 802 tv[0].tv_usec = 0; 803 tv[1].tv_sec = lut.l_modtime; 804 tv[1].tv_usec = 0; 805 tvp = tv; 806 } else 807 tvp = NULL; 808 809 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 810 LFREEPATH(fname); 811 return (error); 812 } 813 814 int 815 linux_utimes(struct thread *td, struct linux_utimes_args *args) 816 { 817 l_timeval ltv[2]; 818 struct timeval tv[2], *tvp = NULL; 819 char *fname; 820 int error; 821 822 LCONVPATHEXIST(td, args->fname, &fname); 823 824 #ifdef DEBUG 825 if (ldebug(utimes)) 826 printf(ARGS(utimes, "%s, *"), fname); 827 #endif 828 829 if (args->tptr != NULL) { 830 if ((error = copyin(args->tptr, ltv, sizeof ltv))) { 831 LFREEPATH(fname); 832 return (error); 833 } 834 tv[0].tv_sec = ltv[0].tv_sec; 835 tv[0].tv_usec = ltv[0].tv_usec; 836 tv[1].tv_sec = ltv[1].tv_sec; 837 tv[1].tv_usec = ltv[1].tv_usec; 838 tvp = tv; 839 } 840 841 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 842 LFREEPATH(fname); 843 return (error); 844 } 845 846 int 847 linux_futimesat(struct thread *td, struct linux_futimesat_args *args) 848 { 849 l_timeval ltv[2]; 850 struct timeval tv[2], *tvp = NULL; 851 char *fname; 852 int error, dfd; 853 854 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 855 LCONVPATHEXIST_AT(td, args->filename, &fname, dfd); 856 857 #ifdef DEBUG 858 if (ldebug(futimesat)) 859 printf(ARGS(futimesat, "%s, *"), fname); 860 #endif 861 862 if (args->utimes != NULL) { 863 if ((error = copyin(args->utimes, ltv, sizeof ltv))) { 864 LFREEPATH(fname); 865 return (error); 866 } 867 tv[0].tv_sec = ltv[0].tv_sec; 868 tv[0].tv_usec = ltv[0].tv_usec; 869 tv[1].tv_sec = ltv[1].tv_sec; 870 tv[1].tv_usec = ltv[1].tv_usec; 871 tvp = tv; 872 } 873 874 error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 875 LFREEPATH(fname); 876 return (error); 877 } 878 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 879 880 #define __WCLONE 0x80000000 881 882 int 883 linux_waitpid(struct thread *td, struct linux_waitpid_args *args) 884 { 885 int error, options, tmpstat; 886 887 #ifdef DEBUG 888 if (ldebug(waitpid)) 889 printf(ARGS(waitpid, "%d, %p, %d"), 890 args->pid, (void *)args->status, args->options); 891 #endif 892 /* 893 * this is necessary because the test in kern_wait doesn't work 894 * because we mess with the options here 895 */ 896 if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE)) 897 return (EINVAL); 898 899 options = (args->options & (WNOHANG | WUNTRACED)); 900 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 901 if (args->options & __WCLONE) 902 options |= WLINUXCLONE; 903 904 error = kern_wait(td, args->pid, &tmpstat, options, NULL); 905 if (error) 906 return error; 907 908 if (args->status) { 909 tmpstat &= 0xffff; 910 if (WIFSIGNALED(tmpstat)) 911 tmpstat = (tmpstat & 0xffffff80) | 912 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 913 else if (WIFSTOPPED(tmpstat)) 914 tmpstat = (tmpstat & 0xffff00ff) | 915 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 916 return copyout(&tmpstat, args->status, sizeof(int)); 917 } 918 919 return 0; 920 } 921 922 int 923 linux_wait4(struct thread *td, struct linux_wait4_args *args) 924 { 925 int error, options, tmpstat; 926 struct rusage ru, *rup; 927 struct proc *p; 928 929 #ifdef DEBUG 930 if (ldebug(wait4)) 931 printf(ARGS(wait4, "%d, %p, %d, %p"), 932 args->pid, (void *)args->status, args->options, 933 (void *)args->rusage); 934 #endif 935 936 options = (args->options & (WNOHANG | WUNTRACED)); 937 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 938 if (args->options & __WCLONE) 939 options |= WLINUXCLONE; 940 941 if (args->rusage != NULL) 942 rup = &ru; 943 else 944 rup = NULL; 945 error = kern_wait(td, args->pid, &tmpstat, options, rup); 946 if (error) 947 return error; 948 949 p = td->td_proc; 950 PROC_LOCK(p); 951 sigqueue_delete(&p->p_sigqueue, SIGCHLD); 952 PROC_UNLOCK(p); 953 954 if (args->status) { 955 tmpstat &= 0xffff; 956 if (WIFSIGNALED(tmpstat)) 957 tmpstat = (tmpstat & 0xffffff80) | 958 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 959 else if (WIFSTOPPED(tmpstat)) 960 tmpstat = (tmpstat & 0xffff00ff) | 961 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 962 error = copyout(&tmpstat, args->status, sizeof(int)); 963 } 964 if (args->rusage != NULL && error == 0) 965 error = copyout(&ru, args->rusage, sizeof(ru)); 966 967 return (error); 968 } 969 970 int 971 linux_mknod(struct thread *td, struct linux_mknod_args *args) 972 { 973 char *path; 974 int error; 975 976 LCONVPATHCREAT(td, args->path, &path); 977 978 #ifdef DEBUG 979 if (ldebug(mknod)) 980 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); 981 #endif 982 983 switch (args->mode & S_IFMT) { 984 case S_IFIFO: 985 case S_IFSOCK: 986 error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode); 987 break; 988 989 case S_IFCHR: 990 case S_IFBLK: 991 error = kern_mknod(td, path, UIO_SYSSPACE, args->mode, 992 args->dev); 993 break; 994 995 case S_IFDIR: 996 error = EPERM; 997 break; 998 999 case 0: 1000 args->mode |= S_IFREG; 1001 /* FALLTHROUGH */ 1002 case S_IFREG: 1003 error = kern_open(td, path, UIO_SYSSPACE, 1004 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 1005 if (error == 0) 1006 kern_close(td, td->td_retval[0]); 1007 break; 1008 1009 default: 1010 error = EINVAL; 1011 break; 1012 } 1013 LFREEPATH(path); 1014 return (error); 1015 } 1016 1017 int 1018 linux_mknodat(struct thread *td, struct linux_mknodat_args *args) 1019 { 1020 char *path; 1021 int error, dfd; 1022 1023 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 1024 LCONVPATHCREAT_AT(td, args->filename, &path, dfd); 1025 1026 #ifdef DEBUG 1027 if (ldebug(mknodat)) 1028 printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev); 1029 #endif 1030 1031 switch (args->mode & S_IFMT) { 1032 case S_IFIFO: 1033 case S_IFSOCK: 1034 error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode); 1035 break; 1036 1037 case S_IFCHR: 1038 case S_IFBLK: 1039 error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode, 1040 args->dev); 1041 break; 1042 1043 case S_IFDIR: 1044 error = EPERM; 1045 break; 1046 1047 case 0: 1048 args->mode |= S_IFREG; 1049 /* FALLTHROUGH */ 1050 case S_IFREG: 1051 error = kern_openat(td, dfd, path, UIO_SYSSPACE, 1052 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 1053 if (error == 0) 1054 kern_close(td, td->td_retval[0]); 1055 break; 1056 1057 default: 1058 error = EINVAL; 1059 break; 1060 } 1061 LFREEPATH(path); 1062 return (error); 1063 } 1064 1065 /* 1066 * UGH! This is just about the dumbest idea I've ever heard!! 1067 */ 1068 int 1069 linux_personality(struct thread *td, struct linux_personality_args *args) 1070 { 1071 #ifdef DEBUG 1072 if (ldebug(personality)) 1073 printf(ARGS(personality, "%lu"), (unsigned long)args->per); 1074 #endif 1075 if (args->per != 0) 1076 return EINVAL; 1077 1078 /* Yes Jim, it's still a Linux... */ 1079 td->td_retval[0] = 0; 1080 return 0; 1081 } 1082 1083 struct l_itimerval { 1084 l_timeval it_interval; 1085 l_timeval it_value; 1086 }; 1087 1088 #define B2L_ITIMERVAL(bip, lip) \ 1089 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ 1090 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ 1091 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ 1092 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; 1093 1094 int 1095 linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) 1096 { 1097 int error; 1098 struct l_itimerval ls; 1099 struct itimerval aitv, oitv; 1100 1101 #ifdef DEBUG 1102 if (ldebug(setitimer)) 1103 printf(ARGS(setitimer, "%p, %p"), 1104 (void *)uap->itv, (void *)uap->oitv); 1105 #endif 1106 1107 if (uap->itv == NULL) { 1108 uap->itv = uap->oitv; 1109 return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); 1110 } 1111 1112 error = copyin(uap->itv, &ls, sizeof(ls)); 1113 if (error != 0) 1114 return (error); 1115 B2L_ITIMERVAL(&aitv, &ls); 1116 #ifdef DEBUG 1117 if (ldebug(setitimer)) { 1118 printf("setitimer: value: sec: %jd, usec: %ld\n", 1119 (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); 1120 printf("setitimer: interval: sec: %jd, usec: %ld\n", 1121 (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); 1122 } 1123 #endif 1124 error = kern_setitimer(td, uap->which, &aitv, &oitv); 1125 if (error != 0 || uap->oitv == NULL) 1126 return (error); 1127 B2L_ITIMERVAL(&ls, &oitv); 1128 1129 return (copyout(&ls, uap->oitv, sizeof(ls))); 1130 } 1131 1132 int 1133 linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) 1134 { 1135 int error; 1136 struct l_itimerval ls; 1137 struct itimerval aitv; 1138 1139 #ifdef DEBUG 1140 if (ldebug(getitimer)) 1141 printf(ARGS(getitimer, "%p"), (void *)uap->itv); 1142 #endif 1143 error = kern_getitimer(td, uap->which, &aitv); 1144 if (error != 0) 1145 return (error); 1146 B2L_ITIMERVAL(&ls, &aitv); 1147 return (copyout(&ls, uap->itv, sizeof(ls))); 1148 } 1149 1150 int 1151 linux_nice(struct thread *td, struct linux_nice_args *args) 1152 { 1153 struct setpriority_args bsd_args; 1154 1155 bsd_args.which = PRIO_PROCESS; 1156 bsd_args.who = 0; /* current process */ 1157 bsd_args.prio = args->inc; 1158 return setpriority(td, &bsd_args); 1159 } 1160 1161 int 1162 linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 1163 { 1164 struct ucred *newcred, *oldcred; 1165 l_gid_t linux_gidset[NGROUPS]; 1166 gid_t *bsd_gidset; 1167 int ngrp, error; 1168 struct proc *p; 1169 1170 ngrp = args->gidsetsize; 1171 if (ngrp < 0 || ngrp >= NGROUPS) 1172 return (EINVAL); 1173 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); 1174 if (error) 1175 return (error); 1176 newcred = crget(); 1177 p = td->td_proc; 1178 PROC_LOCK(p); 1179 oldcred = p->p_ucred; 1180 1181 /* 1182 * cr_groups[0] holds egid. Setting the whole set from 1183 * the supplied set will cause egid to be changed too. 1184 * Keep cr_groups[0] unchanged to prevent that. 1185 */ 1186 1187 if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { 1188 PROC_UNLOCK(p); 1189 crfree(newcred); 1190 return (error); 1191 } 1192 1193 crcopy(newcred, oldcred); 1194 if (ngrp > 0) { 1195 newcred->cr_ngroups = ngrp + 1; 1196 1197 bsd_gidset = newcred->cr_groups; 1198 ngrp--; 1199 while (ngrp >= 0) { 1200 bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 1201 ngrp--; 1202 } 1203 } else 1204 newcred->cr_ngroups = 1; 1205 1206 setsugid(p); 1207 p->p_ucred = newcred; 1208 PROC_UNLOCK(p); 1209 crfree(oldcred); 1210 return (0); 1211 } 1212 1213 int 1214 linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 1215 { 1216 struct ucred *cred; 1217 l_gid_t linux_gidset[NGROUPS]; 1218 gid_t *bsd_gidset; 1219 int bsd_gidsetsz, ngrp, error; 1220 1221 cred = td->td_ucred; 1222 bsd_gidset = cred->cr_groups; 1223 bsd_gidsetsz = cred->cr_ngroups - 1; 1224 1225 /* 1226 * cr_groups[0] holds egid. Returning the whole set 1227 * here will cause a duplicate. Exclude cr_groups[0] 1228 * to prevent that. 1229 */ 1230 1231 if ((ngrp = args->gidsetsize) == 0) { 1232 td->td_retval[0] = bsd_gidsetsz; 1233 return (0); 1234 } 1235 1236 if (ngrp < bsd_gidsetsz) 1237 return (EINVAL); 1238 1239 ngrp = 0; 1240 while (ngrp < bsd_gidsetsz) { 1241 linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 1242 ngrp++; 1243 } 1244 1245 if ((error = copyout(linux_gidset, args->grouplist, 1246 ngrp * sizeof(l_gid_t)))) 1247 return (error); 1248 1249 td->td_retval[0] = ngrp; 1250 return (0); 1251 } 1252 1253 int 1254 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) 1255 { 1256 struct rlimit bsd_rlim; 1257 struct l_rlimit rlim; 1258 u_int which; 1259 int error; 1260 1261 #ifdef DEBUG 1262 if (ldebug(setrlimit)) 1263 printf(ARGS(setrlimit, "%d, %p"), 1264 args->resource, (void *)args->rlim); 1265 #endif 1266 1267 if (args->resource >= LINUX_RLIM_NLIMITS) 1268 return (EINVAL); 1269 1270 which = linux_to_bsd_resource[args->resource]; 1271 if (which == -1) 1272 return (EINVAL); 1273 1274 error = copyin(args->rlim, &rlim, sizeof(rlim)); 1275 if (error) 1276 return (error); 1277 1278 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; 1279 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; 1280 return (kern_setrlimit(td, which, &bsd_rlim)); 1281 } 1282 1283 int 1284 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) 1285 { 1286 struct l_rlimit rlim; 1287 struct proc *p = td->td_proc; 1288 struct rlimit bsd_rlim; 1289 u_int which; 1290 1291 #ifdef DEBUG 1292 if (ldebug(old_getrlimit)) 1293 printf(ARGS(old_getrlimit, "%d, %p"), 1294 args->resource, (void *)args->rlim); 1295 #endif 1296 1297 if (args->resource >= LINUX_RLIM_NLIMITS) 1298 return (EINVAL); 1299 1300 which = linux_to_bsd_resource[args->resource]; 1301 if (which == -1) 1302 return (EINVAL); 1303 1304 PROC_LOCK(p); 1305 lim_rlimit(p, which, &bsd_rlim); 1306 PROC_UNLOCK(p); 1307 1308 #ifdef COMPAT_LINUX32 1309 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; 1310 if (rlim.rlim_cur == UINT_MAX) 1311 rlim.rlim_cur = INT_MAX; 1312 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; 1313 if (rlim.rlim_max == UINT_MAX) 1314 rlim.rlim_max = INT_MAX; 1315 #else 1316 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; 1317 if (rlim.rlim_cur == ULONG_MAX) 1318 rlim.rlim_cur = LONG_MAX; 1319 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; 1320 if (rlim.rlim_max == ULONG_MAX) 1321 rlim.rlim_max = LONG_MAX; 1322 #endif 1323 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1324 } 1325 1326 int 1327 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) 1328 { 1329 struct l_rlimit rlim; 1330 struct proc *p = td->td_proc; 1331 struct rlimit bsd_rlim; 1332 u_int which; 1333 1334 #ifdef DEBUG 1335 if (ldebug(getrlimit)) 1336 printf(ARGS(getrlimit, "%d, %p"), 1337 args->resource, (void *)args->rlim); 1338 #endif 1339 1340 if (args->resource >= LINUX_RLIM_NLIMITS) 1341 return (EINVAL); 1342 1343 which = linux_to_bsd_resource[args->resource]; 1344 if (which == -1) 1345 return (EINVAL); 1346 1347 PROC_LOCK(p); 1348 lim_rlimit(p, which, &bsd_rlim); 1349 PROC_UNLOCK(p); 1350 1351 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; 1352 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; 1353 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1354 } 1355 1356 int 1357 linux_sched_setscheduler(struct thread *td, 1358 struct linux_sched_setscheduler_args *args) 1359 { 1360 struct sched_setscheduler_args bsd; 1361 1362 #ifdef DEBUG 1363 if (ldebug(sched_setscheduler)) 1364 printf(ARGS(sched_setscheduler, "%d, %d, %p"), 1365 args->pid, args->policy, (const void *)args->param); 1366 #endif 1367 1368 switch (args->policy) { 1369 case LINUX_SCHED_OTHER: 1370 bsd.policy = SCHED_OTHER; 1371 break; 1372 case LINUX_SCHED_FIFO: 1373 bsd.policy = SCHED_FIFO; 1374 break; 1375 case LINUX_SCHED_RR: 1376 bsd.policy = SCHED_RR; 1377 break; 1378 default: 1379 return EINVAL; 1380 } 1381 1382 bsd.pid = args->pid; 1383 bsd.param = (struct sched_param *)args->param; 1384 return sched_setscheduler(td, &bsd); 1385 } 1386 1387 int 1388 linux_sched_getscheduler(struct thread *td, 1389 struct linux_sched_getscheduler_args *args) 1390 { 1391 struct sched_getscheduler_args bsd; 1392 int error; 1393 1394 #ifdef DEBUG 1395 if (ldebug(sched_getscheduler)) 1396 printf(ARGS(sched_getscheduler, "%d"), args->pid); 1397 #endif 1398 1399 bsd.pid = args->pid; 1400 error = sched_getscheduler(td, &bsd); 1401 1402 switch (td->td_retval[0]) { 1403 case SCHED_OTHER: 1404 td->td_retval[0] = LINUX_SCHED_OTHER; 1405 break; 1406 case SCHED_FIFO: 1407 td->td_retval[0] = LINUX_SCHED_FIFO; 1408 break; 1409 case SCHED_RR: 1410 td->td_retval[0] = LINUX_SCHED_RR; 1411 break; 1412 } 1413 1414 return error; 1415 } 1416 1417 int 1418 linux_sched_get_priority_max(struct thread *td, 1419 struct linux_sched_get_priority_max_args *args) 1420 { 1421 struct sched_get_priority_max_args bsd; 1422 1423 #ifdef DEBUG 1424 if (ldebug(sched_get_priority_max)) 1425 printf(ARGS(sched_get_priority_max, "%d"), args->policy); 1426 #endif 1427 1428 switch (args->policy) { 1429 case LINUX_SCHED_OTHER: 1430 bsd.policy = SCHED_OTHER; 1431 break; 1432 case LINUX_SCHED_FIFO: 1433 bsd.policy = SCHED_FIFO; 1434 break; 1435 case LINUX_SCHED_RR: 1436 bsd.policy = SCHED_RR; 1437 break; 1438 default: 1439 return EINVAL; 1440 } 1441 return sched_get_priority_max(td, &bsd); 1442 } 1443 1444 int 1445 linux_sched_get_priority_min(struct thread *td, 1446 struct linux_sched_get_priority_min_args *args) 1447 { 1448 struct sched_get_priority_min_args bsd; 1449 1450 #ifdef DEBUG 1451 if (ldebug(sched_get_priority_min)) 1452 printf(ARGS(sched_get_priority_min, "%d"), args->policy); 1453 #endif 1454 1455 switch (args->policy) { 1456 case LINUX_SCHED_OTHER: 1457 bsd.policy = SCHED_OTHER; 1458 break; 1459 case LINUX_SCHED_FIFO: 1460 bsd.policy = SCHED_FIFO; 1461 break; 1462 case LINUX_SCHED_RR: 1463 bsd.policy = SCHED_RR; 1464 break; 1465 default: 1466 return EINVAL; 1467 } 1468 return sched_get_priority_min(td, &bsd); 1469 } 1470 1471 #define REBOOT_CAD_ON 0x89abcdef 1472 #define REBOOT_CAD_OFF 0 1473 #define REBOOT_HALT 0xcdef0123 1474 #define REBOOT_RESTART 0x01234567 1475 #define REBOOT_RESTART2 0xA1B2C3D4 1476 #define REBOOT_POWEROFF 0x4321FEDC 1477 #define REBOOT_MAGIC1 0xfee1dead 1478 #define REBOOT_MAGIC2 0x28121969 1479 #define REBOOT_MAGIC2A 0x05121996 1480 #define REBOOT_MAGIC2B 0x16041998 1481 1482 int 1483 linux_reboot(struct thread *td, struct linux_reboot_args *args) 1484 { 1485 struct reboot_args bsd_args; 1486 1487 #ifdef DEBUG 1488 if (ldebug(reboot)) 1489 printf(ARGS(reboot, "0x%x"), args->cmd); 1490 #endif 1491 1492 if (args->magic1 != REBOOT_MAGIC1) 1493 return EINVAL; 1494 1495 switch (args->magic2) { 1496 case REBOOT_MAGIC2: 1497 case REBOOT_MAGIC2A: 1498 case REBOOT_MAGIC2B: 1499 break; 1500 default: 1501 return EINVAL; 1502 } 1503 1504 switch (args->cmd) { 1505 case REBOOT_CAD_ON: 1506 case REBOOT_CAD_OFF: 1507 return (priv_check(td, PRIV_REBOOT)); 1508 case REBOOT_HALT: 1509 bsd_args.opt = RB_HALT; 1510 break; 1511 case REBOOT_RESTART: 1512 case REBOOT_RESTART2: 1513 bsd_args.opt = 0; 1514 break; 1515 case REBOOT_POWEROFF: 1516 bsd_args.opt = RB_POWEROFF; 1517 break; 1518 default: 1519 return EINVAL; 1520 } 1521 return reboot(td, &bsd_args); 1522 } 1523 1524 1525 /* 1526 * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify 1527 * td->td_retval[1] when COMPAT_43 is defined. This clobbers registers that 1528 * are assumed to be preserved. The following lightweight syscalls fixes 1529 * this. See also linux_getgid16() and linux_getuid16() in linux_uid16.c 1530 * 1531 * linux_getpid() - MP SAFE 1532 * linux_getgid() - MP SAFE 1533 * linux_getuid() - MP SAFE 1534 */ 1535 1536 int 1537 linux_getpid(struct thread *td, struct linux_getpid_args *args) 1538 { 1539 struct linux_emuldata *em; 1540 1541 #ifdef DEBUG 1542 if (ldebug(getpid)) 1543 printf(ARGS(getpid, "")); 1544 #endif 1545 1546 if (linux_use26(td)) { 1547 em = em_find(td->td_proc, EMUL_DONTLOCK); 1548 KASSERT(em != NULL, ("getpid: emuldata not found.\n")); 1549 td->td_retval[0] = em->shared->group_pid; 1550 } else { 1551 td->td_retval[0] = td->td_proc->p_pid; 1552 } 1553 1554 return (0); 1555 } 1556 1557 int 1558 linux_gettid(struct thread *td, struct linux_gettid_args *args) 1559 { 1560 1561 #ifdef DEBUG 1562 if (ldebug(gettid)) 1563 printf(ARGS(gettid, "")); 1564 #endif 1565 1566 td->td_retval[0] = td->td_proc->p_pid; 1567 return (0); 1568 } 1569 1570 1571 int 1572 linux_getppid(struct thread *td, struct linux_getppid_args *args) 1573 { 1574 struct linux_emuldata *em; 1575 struct proc *p, *pp; 1576 1577 #ifdef DEBUG 1578 if (ldebug(getppid)) 1579 printf(ARGS(getppid, "")); 1580 #endif 1581 1582 if (!linux_use26(td)) { 1583 PROC_LOCK(td->td_proc); 1584 td->td_retval[0] = td->td_proc->p_pptr->p_pid; 1585 PROC_UNLOCK(td->td_proc); 1586 return (0); 1587 } 1588 1589 em = em_find(td->td_proc, EMUL_DONTLOCK); 1590 1591 KASSERT(em != NULL, ("getppid: process emuldata not found.\n")); 1592 1593 /* find the group leader */ 1594 p = pfind(em->shared->group_pid); 1595 1596 if (p == NULL) { 1597 #ifdef DEBUG 1598 printf(LMSG("parent process not found.\n")); 1599 #endif 1600 return (0); 1601 } 1602 1603 pp = p->p_pptr; /* switch to parent */ 1604 PROC_LOCK(pp); 1605 PROC_UNLOCK(p); 1606 1607 /* if its also linux process */ 1608 if (pp->p_sysent == &elf_linux_sysvec) { 1609 em = em_find(pp, EMUL_DONTLOCK); 1610 KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); 1611 1612 td->td_retval[0] = em->shared->group_pid; 1613 } else 1614 td->td_retval[0] = pp->p_pid; 1615 1616 PROC_UNLOCK(pp); 1617 1618 return (0); 1619 } 1620 1621 int 1622 linux_getgid(struct thread *td, struct linux_getgid_args *args) 1623 { 1624 1625 #ifdef DEBUG 1626 if (ldebug(getgid)) 1627 printf(ARGS(getgid, "")); 1628 #endif 1629 1630 td->td_retval[0] = td->td_ucred->cr_rgid; 1631 return (0); 1632 } 1633 1634 int 1635 linux_getuid(struct thread *td, struct linux_getuid_args *args) 1636 { 1637 1638 #ifdef DEBUG 1639 if (ldebug(getuid)) 1640 printf(ARGS(getuid, "")); 1641 #endif 1642 1643 td->td_retval[0] = td->td_ucred->cr_ruid; 1644 return (0); 1645 } 1646 1647 1648 int 1649 linux_getsid(struct thread *td, struct linux_getsid_args *args) 1650 { 1651 struct getsid_args bsd; 1652 1653 #ifdef DEBUG 1654 if (ldebug(getsid)) 1655 printf(ARGS(getsid, "%i"), args->pid); 1656 #endif 1657 1658 bsd.pid = args->pid; 1659 return getsid(td, &bsd); 1660 } 1661 1662 int 1663 linux_nosys(struct thread *td, struct nosys_args *ignore) 1664 { 1665 1666 return (ENOSYS); 1667 } 1668 1669 int 1670 linux_getpriority(struct thread *td, struct linux_getpriority_args *args) 1671 { 1672 struct getpriority_args bsd_args; 1673 int error; 1674 1675 #ifdef DEBUG 1676 if (ldebug(getpriority)) 1677 printf(ARGS(getpriority, "%i, %i"), args->which, args->who); 1678 #endif 1679 1680 bsd_args.which = args->which; 1681 bsd_args.who = args->who; 1682 error = getpriority(td, &bsd_args); 1683 td->td_retval[0] = 20 - td->td_retval[0]; 1684 return error; 1685 } 1686 1687 int 1688 linux_sethostname(struct thread *td, struct linux_sethostname_args *args) 1689 { 1690 int name[2]; 1691 1692 #ifdef DEBUG 1693 if (ldebug(sethostname)) 1694 printf(ARGS(sethostname, "*, %i"), args->len); 1695 #endif 1696 1697 name[0] = CTL_KERN; 1698 name[1] = KERN_HOSTNAME; 1699 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, 1700 args->len, 0, 0)); 1701 } 1702 1703 int 1704 linux_exit_group(struct thread *td, struct linux_exit_group_args *args) 1705 { 1706 struct linux_emuldata *em, *td_em, *tmp_em; 1707 struct proc *sp; 1708 1709 #ifdef DEBUG 1710 if (ldebug(exit_group)) 1711 printf(ARGS(exit_group, "%i"), args->error_code); 1712 #endif 1713 1714 if (linux_use26(td)) { 1715 td_em = em_find(td->td_proc, EMUL_DONTLOCK); 1716 1717 KASSERT(td_em != NULL, ("exit_group: emuldata not found.\n")); 1718 1719 EMUL_SHARED_RLOCK(&emul_shared_lock); 1720 LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { 1721 if (em->pid == td_em->pid) 1722 continue; 1723 1724 sp = pfind(em->pid); 1725 psignal(sp, SIGKILL); 1726 PROC_UNLOCK(sp); 1727 #ifdef DEBUG 1728 printf(LMSG("linux_sys_exit_group: kill PID %d\n"), em->pid); 1729 #endif 1730 } 1731 1732 EMUL_SHARED_RUNLOCK(&emul_shared_lock); 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 1741 return (0); 1742 } 1743 1744 int 1745 linux_prctl(struct thread *td, struct linux_prctl_args *args) 1746 { 1747 int error = 0, max_size; 1748 struct proc *p = td->td_proc; 1749 char comm[LINUX_MAX_COMM_LEN]; 1750 struct linux_emuldata *em; 1751 int pdeath_signal; 1752 1753 #ifdef DEBUG 1754 if (ldebug(prctl)) 1755 printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option, 1756 args->arg2, args->arg3, args->arg4, args->arg5); 1757 #endif 1758 1759 switch (args->option) { 1760 case LINUX_PR_SET_PDEATHSIG: 1761 if (!LINUX_SIG_VALID(args->arg2)) 1762 return (EINVAL); 1763 em = em_find(p, EMUL_DOLOCK); 1764 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1765 em->pdeath_signal = args->arg2; 1766 EMUL_UNLOCK(&emul_lock); 1767 break; 1768 case LINUX_PR_GET_PDEATHSIG: 1769 em = em_find(p, EMUL_DOLOCK); 1770 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1771 pdeath_signal = em->pdeath_signal; 1772 EMUL_UNLOCK(&emul_lock); 1773 error = copyout(&pdeath_signal, 1774 (void *)(register_t)args->arg2, 1775 sizeof(pdeath_signal)); 1776 break; 1777 case LINUX_PR_SET_NAME: 1778 /* 1779 * To be on the safe side we need to make sure to not 1780 * overflow the size a linux program expects. We already 1781 * do this here in the copyin, so that we don't need to 1782 * check on copyout. 1783 */ 1784 max_size = MIN(sizeof(comm), sizeof(p->p_comm)); 1785 error = copyinstr((void *)(register_t)args->arg2, comm, 1786 max_size, NULL); 1787 1788 /* Linux silently truncates the name if it is too long. */ 1789 if (error == ENAMETOOLONG) { 1790 /* 1791 * XXX: copyinstr() isn't documented to populate the 1792 * array completely, so do a copyin() to be on the 1793 * safe side. This should be changed in case 1794 * copyinstr() is changed to guarantee this. 1795 */ 1796 error = copyin((void *)(register_t)args->arg2, comm, 1797 max_size - 1); 1798 comm[max_size - 1] = '\0'; 1799 } 1800 if (error) 1801 return (error); 1802 1803 PROC_LOCK(p); 1804 strlcpy(p->p_comm, comm, sizeof(p->p_comm)); 1805 PROC_UNLOCK(p); 1806 break; 1807 case LINUX_PR_GET_NAME: 1808 PROC_LOCK(p); 1809 strlcpy(comm, p->p_comm, sizeof(comm)); 1810 PROC_UNLOCK(p); 1811 error = copyout(comm, (void *)(register_t)args->arg2, 1812 strlen(comm) + 1); 1813 break; 1814 default: 1815 error = EINVAL; 1816 break; 1817 } 1818 1819 return (error); 1820 } 1821 1822 /* 1823 * Get affinity of a process. 1824 */ 1825 int 1826 linux_sched_getaffinity(struct thread *td, 1827 struct linux_sched_getaffinity_args *args) 1828 { 1829 int error; 1830 struct cpuset_getaffinity_args cga; 1831 1832 #ifdef DEBUG 1833 if (ldebug(sched_getaffinity)) 1834 printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid, 1835 args->len); 1836 #endif 1837 1838 cga.level = CPU_LEVEL_WHICH; 1839 cga.which = CPU_WHICH_PID; 1840 cga.id = args->pid; 1841 cga.cpusetsize = sizeof(cpumask_t); 1842 cga.mask = (cpuset_t *) args->user_mask_ptr; 1843 1844 if ((error = cpuset_getaffinity(td, &cga)) == 0) 1845 td->td_retval[0] = sizeof(cpumask_t); 1846 1847 return (error); 1848 } 1849 1850 /* 1851 * Set affinity of a process. 1852 */ 1853 int 1854 linux_sched_setaffinity(struct thread *td, 1855 struct linux_sched_setaffinity_args *args) 1856 { 1857 struct cpuset_setaffinity_args csa; 1858 1859 #ifdef DEBUG 1860 if (ldebug(sched_setaffinity)) 1861 printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid, 1862 args->len); 1863 #endif 1864 csa.level = CPU_LEVEL_WHICH; 1865 csa.which = CPU_WHICH_PID; 1866 csa.id = args->pid; 1867 csa.cpusetsize = args->len; 1868 csa.mask = (cpuset_t *) args->user_mask_ptr; 1869 1870 return (cpuset_setaffinity(td, &csa)); 1871 } 1872