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__) || defined(__alpha__) 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/mac.h> 47 #include <sys/malloc.h> 48 #include <sys/mman.h> 49 #include <sys/mount.h> 50 #include <sys/mutex.h> 51 #include <sys/namei.h> 52 #include <sys/proc.h> 53 #include <sys/reboot.h> 54 #include <sys/resourcevar.h> 55 #include <sys/signalvar.h> 56 #include <sys/stat.h> 57 #include <sys/syscallsubr.h> 58 #include <sys/sysctl.h> 59 #include <sys/sysproto.h> 60 #include <sys/systm.h> 61 #include <sys/time.h> 62 #include <sys/vmmeter.h> 63 #include <sys/vnode.h> 64 #include <sys/wait.h> 65 66 #include <vm/vm.h> 67 #include <vm/pmap.h> 68 #include <vm/vm_kern.h> 69 #include <vm/vm_map.h> 70 #include <vm/vm_extern.h> 71 #include <vm/vm_object.h> 72 #include <vm/swap_pager.h> 73 74 #include <posix4/sched.h> 75 76 #include <compat/linux/linux_sysproto.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_mib.h> 87 #include <compat/linux/linux_util.h> 88 89 #ifdef __i386__ 90 #include <machine/cputypes.h> 91 #endif 92 93 #ifdef __alpha__ 94 #define BSD_TO_LINUX_SIGNAL(sig) (sig) 95 #else 96 #define BSD_TO_LINUX_SIGNAL(sig) \ 97 (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) 98 #endif 99 100 #ifndef __alpha__ 101 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { 102 RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 103 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 104 RLIMIT_MEMLOCK, -1 105 }; 106 #endif /*!__alpha__*/ 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_ulong totalbig; 120 l_ulong freebig; 121 l_uint mem_unit; 122 char _f[6]; /* Pads structure to 64 bytes */ 123 }; 124 #ifndef __alpha__ 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 #endif /*!__alpha__*/ 170 171 #ifndef __alpha__ 172 int 173 linux_alarm(struct thread *td, struct linux_alarm_args *args) 174 { 175 struct itimerval it, old_it; 176 int error; 177 178 #ifdef DEBUG 179 if (ldebug(alarm)) 180 printf(ARGS(alarm, "%u"), args->secs); 181 #endif 182 183 if (args->secs > 100000000) 184 return (EINVAL); 185 186 it.it_value.tv_sec = (long)args->secs; 187 it.it_value.tv_usec = 0; 188 it.it_interval.tv_sec = 0; 189 it.it_interval.tv_usec = 0; 190 error = kern_setitimer(td, ITIMER_REAL, &it, &old_it); 191 if (error) 192 return (error); 193 if (timevalisset(&old_it.it_value)) { 194 if (old_it.it_value.tv_usec != 0) 195 old_it.it_value.tv_sec++; 196 td->td_retval[0] = old_it.it_value.tv_sec; 197 } 198 return (0); 199 } 200 #endif /*!__alpha__*/ 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__) || defined(__alpha__) 227 228 int 229 linux_uselib(struct thread *td, struct linux_uselib_args *args) 230 { 231 struct nameidata ni; 232 struct vnode *vp; 233 struct exec *a_out; 234 struct vattr attr; 235 vm_offset_t vmaddr; 236 unsigned long file_offset; 237 vm_offset_t buffer; 238 unsigned long bss_size; 239 char *library; 240 int error; 241 int locked; 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 /* 255 * XXX: This code should make use of vn_open(), rather than doing 256 * all this stuff itself. 257 */ 258 NDINIT(&ni, LOOKUP, ISOPEN|FOLLOW|LOCKLEAF, UIO_SYSSPACE, library, td); 259 error = namei(&ni); 260 LFREEPATH(library); 261 if (error) 262 goto cleanup; 263 264 vp = ni.ni_vp; 265 /* 266 * XXX - This looks like a bogus check. A LOCKLEAF namei should not 267 * succeed without returning a vnode. 268 */ 269 if (vp == NULL) { 270 error = ENOEXEC; /* ?? */ 271 goto cleanup; 272 } 273 NDFREE(&ni, NDF_ONLY_PNBUF); 274 275 /* 276 * From here on down, we have a locked vnode that must be unlocked. 277 */ 278 locked++; 279 280 /* Writable? */ 281 if (vp->v_writecount) { 282 error = ETXTBSY; 283 goto cleanup; 284 } 285 286 /* Executable? */ 287 error = VOP_GETATTR(vp, &attr, td->td_ucred, td); 288 if (error) 289 goto cleanup; 290 291 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 292 ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { 293 error = ENOEXEC; 294 goto cleanup; 295 } 296 297 /* Sensible size? */ 298 if (attr.va_size == 0) { 299 error = ENOEXEC; 300 goto cleanup; 301 } 302 303 /* Can we access it? */ 304 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 305 if (error) 306 goto cleanup; 307 308 /* 309 * XXX: This should use vn_open() so that it is properly authorized, 310 * and to reduce code redundancy all over the place here. 311 */ 312 #ifdef MAC 313 error = mac_check_vnode_open(td->td_ucred, vp, FREAD); 314 if (error) 315 goto cleanup; 316 #endif 317 error = VOP_OPEN(vp, FREAD, td->td_ucred, td, -1); 318 if (error) 319 goto cleanup; 320 321 /* Pull in executable header into kernel_map */ 322 error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, 323 VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); 324 /* 325 * Lock no longer needed 326 */ 327 locked = 0; 328 VOP_UNLOCK(vp, 0, td); 329 330 if (error) 331 goto cleanup; 332 333 /* Is it a Linux binary ? */ 334 if (((a_out->a_magic >> 16) & 0xff) != 0x64) { 335 error = ENOEXEC; 336 goto cleanup; 337 } 338 339 /* 340 * While we are here, we should REALLY do some more checks 341 */ 342 343 /* Set file/virtual offset based on a.out variant. */ 344 switch ((int)(a_out->a_magic & 0xffff)) { 345 case 0413: /* ZMAGIC */ 346 file_offset = 1024; 347 break; 348 case 0314: /* QMAGIC */ 349 file_offset = 0; 350 break; 351 default: 352 error = ENOEXEC; 353 goto cleanup; 354 } 355 356 bss_size = round_page(a_out->a_bss); 357 358 /* Check various fields in header for validity/bounds. */ 359 if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { 360 error = ENOEXEC; 361 goto cleanup; 362 } 363 364 /* text + data can't exceed file size */ 365 if (a_out->a_data + a_out->a_text > attr.va_size) { 366 error = EFAULT; 367 goto cleanup; 368 } 369 370 /* 371 * text/data/bss must not exceed limits 372 * XXX - this is not complete. it should check current usage PLUS 373 * the resources needed by this library. 374 */ 375 PROC_LOCK(td->td_proc); 376 if (a_out->a_text > maxtsiz || 377 a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA)) { 378 PROC_UNLOCK(td->td_proc); 379 error = ENOMEM; 380 goto cleanup; 381 } 382 PROC_UNLOCK(td->td_proc); 383 384 mp_fixme("Unlocked vflags access."); 385 /* prevent more writers */ 386 vp->v_vflag |= VV_TEXT; 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, td); 467 468 /* Release the kernel mapping. */ 469 if (a_out) 470 vm_map_remove(kernel_map, (vm_offset_t)a_out, 471 (vm_offset_t)a_out + PAGE_SIZE); 472 473 return error; 474 } 475 476 #endif /* __i386__ || __alpha__ */ 477 478 int 479 linux_select(struct thread *td, struct linux_select_args *args) 480 { 481 l_timeval ltv; 482 struct timeval tv0, tv1, utv, *tvp; 483 int error; 484 485 #ifdef DEBUG 486 if (ldebug(select)) 487 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, 488 (void *)args->readfds, (void *)args->writefds, 489 (void *)args->exceptfds, (void *)args->timeout); 490 #endif 491 492 /* 493 * Store current time for computation of the amount of 494 * time left. 495 */ 496 if (args->timeout) { 497 if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 498 goto select_out; 499 utv.tv_sec = ltv.tv_sec; 500 utv.tv_usec = ltv.tv_usec; 501 #ifdef DEBUG 502 if (ldebug(select)) 503 printf(LMSG("incoming timeout (%jd/%ld)"), 504 (intmax_t)utv.tv_sec, utv.tv_usec); 505 #endif 506 507 if (itimerfix(&utv)) { 508 /* 509 * The timeval was invalid. Convert it to something 510 * valid that will act as it does under Linux. 511 */ 512 utv.tv_sec += utv.tv_usec / 1000000; 513 utv.tv_usec %= 1000000; 514 if (utv.tv_usec < 0) { 515 utv.tv_sec -= 1; 516 utv.tv_usec += 1000000; 517 } 518 if (utv.tv_sec < 0) 519 timevalclear(&utv); 520 } 521 microtime(&tv0); 522 tvp = &utv; 523 } else 524 tvp = NULL; 525 526 error = kern_select(td, args->nfds, args->readfds, args->writefds, 527 args->exceptfds, tvp); 528 529 #ifdef DEBUG 530 if (ldebug(select)) 531 printf(LMSG("real select returns %d"), error); 532 #endif 533 if (error) { 534 /* 535 * See fs/select.c in the Linux kernel. Without this, 536 * Maelstrom doesn't work. 537 */ 538 if (error == ERESTART) 539 error = EINTR; 540 goto select_out; 541 } 542 543 if (args->timeout) { 544 if (td->td_retval[0]) { 545 /* 546 * Compute how much time was left of the timeout, 547 * by subtracting the current time and the time 548 * before we started the call, and subtracting 549 * that result from the user-supplied value. 550 */ 551 microtime(&tv1); 552 timevalsub(&tv1, &tv0); 553 timevalsub(&utv, &tv1); 554 if (utv.tv_sec < 0) 555 timevalclear(&utv); 556 } else 557 timevalclear(&utv); 558 #ifdef DEBUG 559 if (ldebug(select)) 560 printf(LMSG("outgoing timeout (%jd/%ld)"), 561 (intmax_t)utv.tv_sec, utv.tv_usec); 562 #endif 563 ltv.tv_sec = utv.tv_sec; 564 ltv.tv_usec = utv.tv_usec; 565 if ((error = copyout(<v, args->timeout, sizeof(ltv)))) 566 goto select_out; 567 } 568 569 select_out: 570 #ifdef DEBUG 571 if (ldebug(select)) 572 printf(LMSG("select_out -> %d"), error); 573 #endif 574 return error; 575 } 576 577 int 578 linux_mremap(struct thread *td, struct linux_mremap_args *args) 579 { 580 struct munmap_args /* { 581 void *addr; 582 size_t len; 583 } */ bsd_args; 584 int error = 0; 585 586 #ifdef DEBUG 587 if (ldebug(mremap)) 588 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), 589 (void *)(uintptr_t)args->addr, 590 (unsigned long)args->old_len, 591 (unsigned long)args->new_len, 592 (unsigned long)args->flags); 593 #endif 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 = 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 msync(td, &bsd_args); 627 } 628 629 #ifndef __alpha__ 630 int 631 linux_time(struct thread *td, struct linux_time_args *args) 632 { 633 struct timeval tv; 634 l_time_t tm; 635 int error; 636 637 #ifdef DEBUG 638 if (ldebug(time)) 639 printf(ARGS(time, "*")); 640 #endif 641 642 microtime(&tv); 643 tm = tv.tv_sec; 644 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) 645 return error; 646 td->td_retval[0] = tm; 647 return 0; 648 } 649 #endif /*!__alpha__*/ 650 651 struct l_times_argv { 652 l_long tms_utime; 653 l_long tms_stime; 654 l_long tms_cutime; 655 l_long tms_cstime; 656 }; 657 658 #ifdef __alpha__ 659 #define CLK_TCK 1024 /* Linux uses 1024 on alpha */ 660 #else 661 #define CLK_TCK 100 /* Linux uses 100 */ 662 #endif 663 664 #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 665 666 int 667 linux_times(struct thread *td, struct linux_times_args *args) 668 { 669 struct timeval tv, utime, stime, cutime, cstime; 670 struct l_times_argv tms; 671 struct proc *p; 672 int error; 673 674 #ifdef DEBUG 675 if (ldebug(times)) 676 printf(ARGS(times, "*")); 677 #endif 678 679 p = td->td_proc; 680 PROC_LOCK(p); 681 calcru(p, &utime, &stime); 682 calccru(p, &cutime, &cstime); 683 PROC_UNLOCK(p); 684 685 tms.tms_utime = CONVTCK(utime); 686 tms.tms_stime = CONVTCK(stime); 687 688 tms.tms_cutime = CONVTCK(cutime); 689 tms.tms_cstime = CONVTCK(cstime); 690 691 if ((error = copyout(&tms, args->buf, sizeof(tms)))) 692 return error; 693 694 microuptime(&tv); 695 td->td_retval[0] = (int)CONVTCK(tv); 696 return 0; 697 } 698 699 int 700 linux_newuname(struct thread *td, struct linux_newuname_args *args) 701 { 702 struct l_new_utsname utsname; 703 char osname[LINUX_MAX_UTSNAME]; 704 char osrelease[LINUX_MAX_UTSNAME]; 705 char *p; 706 707 #ifdef DEBUG 708 if (ldebug(newuname)) 709 printf(ARGS(newuname, "*")); 710 #endif 711 712 linux_get_osname(td, osname); 713 linux_get_osrelease(td, osrelease); 714 715 bzero(&utsname, sizeof(utsname)); 716 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); 717 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); 718 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); 719 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); 720 for (p = utsname.version; *p != '\0'; ++p) 721 if (*p == '\n') { 722 *p = '\0'; 723 break; 724 } 725 #ifdef __i386__ 726 { 727 const char *class; 728 switch (cpu_class) { 729 case CPUCLASS_686: 730 class = "i686"; 731 break; 732 case CPUCLASS_586: 733 class = "i586"; 734 break; 735 case CPUCLASS_486: 736 class = "i486"; 737 break; 738 default: 739 class = "i386"; 740 } 741 strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME); 742 } 743 #elif defined(__amd64__) /* XXX: Linux can change 'personality'. */ 744 #ifdef COMPAT_LINUX32 745 strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME); 746 #else 747 strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME); 748 #endif /* COMPAT_LINUX32 */ 749 #else /* something other than i386 or amd64 - assume we and Linux agree */ 750 strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME); 751 #endif /* __i386__ */ 752 strlcpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME); 753 754 return (copyout(&utsname, args->buf, sizeof(utsname))); 755 } 756 757 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 758 struct l_utimbuf { 759 l_time_t l_actime; 760 l_time_t l_modtime; 761 }; 762 763 int 764 linux_utime(struct thread *td, struct linux_utime_args *args) 765 { 766 struct timeval tv[2], *tvp; 767 struct l_utimbuf lut; 768 char *fname; 769 int error; 770 771 LCONVPATHEXIST(td, args->fname, &fname); 772 773 #ifdef DEBUG 774 if (ldebug(utime)) 775 printf(ARGS(utime, "%s, *"), fname); 776 #endif 777 778 if (args->times) { 779 if ((error = copyin(args->times, &lut, sizeof lut))) { 780 LFREEPATH(fname); 781 return error; 782 } 783 tv[0].tv_sec = lut.l_actime; 784 tv[0].tv_usec = 0; 785 tv[1].tv_sec = lut.l_modtime; 786 tv[1].tv_usec = 0; 787 tvp = tv; 788 } else 789 tvp = NULL; 790 791 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 792 LFREEPATH(fname); 793 return (error); 794 } 795 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 796 797 #define __WCLONE 0x80000000 798 799 #ifndef __alpha__ 800 int 801 linux_waitpid(struct thread *td, struct linux_waitpid_args *args) 802 { 803 int error, options, tmpstat; 804 805 #ifdef DEBUG 806 if (ldebug(waitpid)) 807 printf(ARGS(waitpid, "%d, %p, %d"), 808 args->pid, (void *)args->status, args->options); 809 #endif 810 811 options = (args->options & (WNOHANG | WUNTRACED)); 812 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 813 if (args->options & __WCLONE) 814 options |= WLINUXCLONE; 815 816 error = kern_wait(td, args->pid, &tmpstat, options, NULL); 817 if (error) 818 return error; 819 820 if (args->status) { 821 tmpstat &= 0xffff; 822 if (WIFSIGNALED(tmpstat)) 823 tmpstat = (tmpstat & 0xffffff80) | 824 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 825 else if (WIFSTOPPED(tmpstat)) 826 tmpstat = (tmpstat & 0xffff00ff) | 827 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 828 return copyout(&tmpstat, args->status, sizeof(int)); 829 } 830 831 return 0; 832 } 833 #endif /*!__alpha__*/ 834 835 int 836 linux_wait4(struct thread *td, struct linux_wait4_args *args) 837 { 838 int error, options, tmpstat; 839 struct rusage ru, *rup; 840 struct proc *p; 841 842 #ifdef DEBUG 843 if (ldebug(wait4)) 844 printf(ARGS(wait4, "%d, %p, %d, %p"), 845 args->pid, (void *)args->status, args->options, 846 (void *)args->rusage); 847 #endif 848 849 options = (args->options & (WNOHANG | WUNTRACED)); 850 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 851 if (args->options & __WCLONE) 852 options |= WLINUXCLONE; 853 854 if (args->rusage != NULL) 855 rup = &ru; 856 else 857 rup = NULL; 858 error = kern_wait(td, args->pid, &tmpstat, options, rup); 859 if (error) 860 return error; 861 862 p = td->td_proc; 863 PROC_LOCK(p); 864 sigqueue_delete(&p->p_sigqueue, SIGCHLD); 865 PROC_UNLOCK(p); 866 867 if (args->status) { 868 tmpstat &= 0xffff; 869 if (WIFSIGNALED(tmpstat)) 870 tmpstat = (tmpstat & 0xffffff80) | 871 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 872 else if (WIFSTOPPED(tmpstat)) 873 tmpstat = (tmpstat & 0xffff00ff) | 874 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 875 error = copyout(&tmpstat, args->status, sizeof(int)); 876 } 877 if (args->rusage != NULL && error == 0) 878 error = copyout(&ru, args->rusage, sizeof(ru)); 879 880 return (error); 881 } 882 883 int 884 linux_mknod(struct thread *td, struct linux_mknod_args *args) 885 { 886 char *path; 887 int error; 888 889 LCONVPATHCREAT(td, args->path, &path); 890 891 #ifdef DEBUG 892 if (ldebug(mknod)) 893 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); 894 #endif 895 896 if (args->mode & S_IFIFO) 897 error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode); 898 else 899 error = kern_mknod(td, path, UIO_SYSSPACE, args->mode, 900 args->dev); 901 LFREEPATH(path); 902 return (error); 903 } 904 905 /* 906 * UGH! This is just about the dumbest idea I've ever heard!! 907 */ 908 int 909 linux_personality(struct thread *td, struct linux_personality_args *args) 910 { 911 #ifdef DEBUG 912 if (ldebug(personality)) 913 printf(ARGS(personality, "%lu"), (unsigned long)args->per); 914 #endif 915 #ifndef __alpha__ 916 if (args->per != 0) 917 return EINVAL; 918 #endif 919 920 /* Yes Jim, it's still a Linux... */ 921 td->td_retval[0] = 0; 922 return 0; 923 } 924 925 struct l_itimerval { 926 l_timeval it_interval; 927 l_timeval it_value; 928 }; 929 930 #define B2L_ITIMERVAL(bip, lip) \ 931 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ 932 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ 933 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ 934 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; 935 936 int 937 linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) 938 { 939 int error; 940 struct l_itimerval ls; 941 struct itimerval aitv, oitv; 942 943 #ifdef DEBUG 944 if (ldebug(setitimer)) 945 printf(ARGS(setitimer, "%p, %p"), 946 (void *)uap->itv, (void *)uap->oitv); 947 #endif 948 949 if (uap->itv == NULL) { 950 uap->itv = uap->oitv; 951 return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); 952 } 953 954 error = copyin(uap->itv, &ls, sizeof(ls)); 955 if (error != 0) 956 return (error); 957 B2L_ITIMERVAL(&aitv, &ls); 958 #ifdef DEBUG 959 if (ldebug(setitimer)) { 960 printf("setitimer: value: sec: %jd, usec: %ld\n", 961 (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); 962 printf("setitimer: interval: sec: %jd, usec: %ld\n", 963 (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); 964 } 965 #endif 966 error = kern_setitimer(td, uap->which, &aitv, &oitv); 967 if (error != 0 || uap->oitv == NULL) 968 return (error); 969 B2L_ITIMERVAL(&ls, &oitv); 970 971 return (copyout(&ls, uap->oitv, sizeof(ls))); 972 } 973 974 int 975 linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) 976 { 977 int error; 978 struct l_itimerval ls; 979 struct itimerval aitv; 980 981 #ifdef DEBUG 982 if (ldebug(getitimer)) 983 printf(ARGS(getitimer, "%p"), (void *)uap->itv); 984 #endif 985 error = kern_getitimer(td, uap->which, &aitv); 986 if (error != 0) 987 return (error); 988 B2L_ITIMERVAL(&ls, &aitv); 989 return (copyout(&ls, uap->itv, sizeof(ls))); 990 } 991 992 #ifndef __alpha__ 993 int 994 linux_nice(struct thread *td, struct linux_nice_args *args) 995 { 996 struct setpriority_args bsd_args; 997 998 bsd_args.which = PRIO_PROCESS; 999 bsd_args.who = 0; /* current process */ 1000 bsd_args.prio = args->inc; 1001 return setpriority(td, &bsd_args); 1002 } 1003 #endif /*!__alpha__*/ 1004 1005 int 1006 linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 1007 { 1008 struct ucred *newcred, *oldcred; 1009 l_gid_t linux_gidset[NGROUPS]; 1010 gid_t *bsd_gidset; 1011 int ngrp, error; 1012 struct proc *p; 1013 1014 ngrp = args->gidsetsize; 1015 if (ngrp < 0 || ngrp >= NGROUPS) 1016 return (EINVAL); 1017 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); 1018 if (error) 1019 return (error); 1020 newcred = crget(); 1021 p = td->td_proc; 1022 PROC_LOCK(p); 1023 oldcred = p->p_ucred; 1024 1025 /* 1026 * cr_groups[0] holds egid. Setting the whole set from 1027 * the supplied set will cause egid to be changed too. 1028 * Keep cr_groups[0] unchanged to prevent that. 1029 */ 1030 1031 if ((error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) { 1032 PROC_UNLOCK(p); 1033 crfree(newcred); 1034 return (error); 1035 } 1036 1037 crcopy(newcred, oldcred); 1038 if (ngrp > 0) { 1039 newcred->cr_ngroups = ngrp + 1; 1040 1041 bsd_gidset = newcred->cr_groups; 1042 ngrp--; 1043 while (ngrp >= 0) { 1044 bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 1045 ngrp--; 1046 } 1047 } 1048 else 1049 newcred->cr_ngroups = 1; 1050 1051 setsugid(p); 1052 p->p_ucred = newcred; 1053 PROC_UNLOCK(p); 1054 crfree(oldcred); 1055 return (0); 1056 } 1057 1058 int 1059 linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 1060 { 1061 struct ucred *cred; 1062 l_gid_t linux_gidset[NGROUPS]; 1063 gid_t *bsd_gidset; 1064 int bsd_gidsetsz, ngrp, error; 1065 1066 cred = td->td_ucred; 1067 bsd_gidset = cred->cr_groups; 1068 bsd_gidsetsz = cred->cr_ngroups - 1; 1069 1070 /* 1071 * cr_groups[0] holds egid. Returning the whole set 1072 * here will cause a duplicate. Exclude cr_groups[0] 1073 * to prevent that. 1074 */ 1075 1076 if ((ngrp = args->gidsetsize) == 0) { 1077 td->td_retval[0] = bsd_gidsetsz; 1078 return (0); 1079 } 1080 1081 if (ngrp < bsd_gidsetsz) 1082 return (EINVAL); 1083 1084 ngrp = 0; 1085 while (ngrp < bsd_gidsetsz) { 1086 linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 1087 ngrp++; 1088 } 1089 1090 if ((error = copyout(linux_gidset, args->grouplist, 1091 ngrp * sizeof(l_gid_t)))) 1092 return (error); 1093 1094 td->td_retval[0] = ngrp; 1095 return (0); 1096 } 1097 1098 #ifndef __alpha__ 1099 int 1100 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) 1101 { 1102 struct rlimit bsd_rlim; 1103 struct l_rlimit rlim; 1104 u_int which; 1105 int error; 1106 1107 #ifdef DEBUG 1108 if (ldebug(setrlimit)) 1109 printf(ARGS(setrlimit, "%d, %p"), 1110 args->resource, (void *)args->rlim); 1111 #endif 1112 1113 if (args->resource >= LINUX_RLIM_NLIMITS) 1114 return (EINVAL); 1115 1116 which = linux_to_bsd_resource[args->resource]; 1117 if (which == -1) 1118 return (EINVAL); 1119 1120 error = copyin(args->rlim, &rlim, sizeof(rlim)); 1121 if (error) 1122 return (error); 1123 1124 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; 1125 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; 1126 return (kern_setrlimit(td, which, &bsd_rlim)); 1127 } 1128 1129 int 1130 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) 1131 { 1132 struct l_rlimit rlim; 1133 struct proc *p = td->td_proc; 1134 struct rlimit bsd_rlim; 1135 u_int which; 1136 1137 #ifdef DEBUG 1138 if (ldebug(old_getrlimit)) 1139 printf(ARGS(old_getrlimit, "%d, %p"), 1140 args->resource, (void *)args->rlim); 1141 #endif 1142 1143 if (args->resource >= LINUX_RLIM_NLIMITS) 1144 return (EINVAL); 1145 1146 which = linux_to_bsd_resource[args->resource]; 1147 if (which == -1) 1148 return (EINVAL); 1149 1150 PROC_LOCK(p); 1151 lim_rlimit(p, which, &bsd_rlim); 1152 PROC_UNLOCK(p); 1153 1154 #ifdef COMPAT_LINUX32 1155 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; 1156 if (rlim.rlim_cur == UINT_MAX) 1157 rlim.rlim_cur = INT_MAX; 1158 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; 1159 if (rlim.rlim_max == UINT_MAX) 1160 rlim.rlim_max = INT_MAX; 1161 #else 1162 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; 1163 if (rlim.rlim_cur == ULONG_MAX) 1164 rlim.rlim_cur = LONG_MAX; 1165 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; 1166 if (rlim.rlim_max == ULONG_MAX) 1167 rlim.rlim_max = LONG_MAX; 1168 #endif 1169 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1170 } 1171 1172 int 1173 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) 1174 { 1175 struct l_rlimit rlim; 1176 struct proc *p = td->td_proc; 1177 struct rlimit bsd_rlim; 1178 u_int which; 1179 1180 #ifdef DEBUG 1181 if (ldebug(getrlimit)) 1182 printf(ARGS(getrlimit, "%d, %p"), 1183 args->resource, (void *)args->rlim); 1184 #endif 1185 1186 if (args->resource >= LINUX_RLIM_NLIMITS) 1187 return (EINVAL); 1188 1189 which = linux_to_bsd_resource[args->resource]; 1190 if (which == -1) 1191 return (EINVAL); 1192 1193 PROC_LOCK(p); 1194 lim_rlimit(p, which, &bsd_rlim); 1195 PROC_UNLOCK(p); 1196 1197 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; 1198 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; 1199 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1200 } 1201 #endif /*!__alpha__*/ 1202 1203 int 1204 linux_sched_setscheduler(struct thread *td, 1205 struct linux_sched_setscheduler_args *args) 1206 { 1207 struct sched_setscheduler_args bsd; 1208 1209 #ifdef DEBUG 1210 if (ldebug(sched_setscheduler)) 1211 printf(ARGS(sched_setscheduler, "%d, %d, %p"), 1212 args->pid, args->policy, (const void *)args->param); 1213 #endif 1214 1215 switch (args->policy) { 1216 case LINUX_SCHED_OTHER: 1217 bsd.policy = SCHED_OTHER; 1218 break; 1219 case LINUX_SCHED_FIFO: 1220 bsd.policy = SCHED_FIFO; 1221 break; 1222 case LINUX_SCHED_RR: 1223 bsd.policy = SCHED_RR; 1224 break; 1225 default: 1226 return EINVAL; 1227 } 1228 1229 bsd.pid = args->pid; 1230 bsd.param = (struct sched_param *)args->param; 1231 return sched_setscheduler(td, &bsd); 1232 } 1233 1234 int 1235 linux_sched_getscheduler(struct thread *td, 1236 struct linux_sched_getscheduler_args *args) 1237 { 1238 struct sched_getscheduler_args bsd; 1239 int error; 1240 1241 #ifdef DEBUG 1242 if (ldebug(sched_getscheduler)) 1243 printf(ARGS(sched_getscheduler, "%d"), args->pid); 1244 #endif 1245 1246 bsd.pid = args->pid; 1247 error = sched_getscheduler(td, &bsd); 1248 1249 switch (td->td_retval[0]) { 1250 case SCHED_OTHER: 1251 td->td_retval[0] = LINUX_SCHED_OTHER; 1252 break; 1253 case SCHED_FIFO: 1254 td->td_retval[0] = LINUX_SCHED_FIFO; 1255 break; 1256 case SCHED_RR: 1257 td->td_retval[0] = LINUX_SCHED_RR; 1258 break; 1259 } 1260 1261 return error; 1262 } 1263 1264 int 1265 linux_sched_get_priority_max(struct thread *td, 1266 struct linux_sched_get_priority_max_args *args) 1267 { 1268 struct sched_get_priority_max_args bsd; 1269 1270 #ifdef DEBUG 1271 if (ldebug(sched_get_priority_max)) 1272 printf(ARGS(sched_get_priority_max, "%d"), args->policy); 1273 #endif 1274 1275 switch (args->policy) { 1276 case LINUX_SCHED_OTHER: 1277 bsd.policy = SCHED_OTHER; 1278 break; 1279 case LINUX_SCHED_FIFO: 1280 bsd.policy = SCHED_FIFO; 1281 break; 1282 case LINUX_SCHED_RR: 1283 bsd.policy = SCHED_RR; 1284 break; 1285 default: 1286 return EINVAL; 1287 } 1288 return sched_get_priority_max(td, &bsd); 1289 } 1290 1291 int 1292 linux_sched_get_priority_min(struct thread *td, 1293 struct linux_sched_get_priority_min_args *args) 1294 { 1295 struct sched_get_priority_min_args bsd; 1296 1297 #ifdef DEBUG 1298 if (ldebug(sched_get_priority_min)) 1299 printf(ARGS(sched_get_priority_min, "%d"), args->policy); 1300 #endif 1301 1302 switch (args->policy) { 1303 case LINUX_SCHED_OTHER: 1304 bsd.policy = SCHED_OTHER; 1305 break; 1306 case LINUX_SCHED_FIFO: 1307 bsd.policy = SCHED_FIFO; 1308 break; 1309 case LINUX_SCHED_RR: 1310 bsd.policy = SCHED_RR; 1311 break; 1312 default: 1313 return EINVAL; 1314 } 1315 return sched_get_priority_min(td, &bsd); 1316 } 1317 1318 #define REBOOT_CAD_ON 0x89abcdef 1319 #define REBOOT_CAD_OFF 0 1320 #define REBOOT_HALT 0xcdef0123 1321 1322 int 1323 linux_reboot(struct thread *td, struct linux_reboot_args *args) 1324 { 1325 struct reboot_args bsd_args; 1326 1327 #ifdef DEBUG 1328 if (ldebug(reboot)) 1329 printf(ARGS(reboot, "0x%x"), args->cmd); 1330 #endif 1331 if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF) 1332 return (0); 1333 bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0; 1334 return (reboot(td, &bsd_args)); 1335 } 1336 1337 #ifndef __alpha__ 1338 1339 /* 1340 * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify 1341 * td->td_retval[1] when COMPAT_43 is defined. This 1342 * globbers registers that are assumed to be preserved. The following 1343 * lightweight syscalls fixes this. See also linux_getgid16() and 1344 * linux_getuid16() in linux_uid16.c. 1345 * 1346 * linux_getpid() - MP SAFE 1347 * linux_getgid() - MP SAFE 1348 * linux_getuid() - MP SAFE 1349 */ 1350 1351 int 1352 linux_getpid(struct thread *td, struct linux_getpid_args *args) 1353 { 1354 1355 td->td_retval[0] = td->td_proc->p_pid; 1356 return (0); 1357 } 1358 1359 int 1360 linux_getgid(struct thread *td, struct linux_getgid_args *args) 1361 { 1362 1363 td->td_retval[0] = td->td_ucred->cr_rgid; 1364 return (0); 1365 } 1366 1367 int 1368 linux_getuid(struct thread *td, struct linux_getuid_args *args) 1369 { 1370 1371 td->td_retval[0] = td->td_ucred->cr_ruid; 1372 return (0); 1373 } 1374 1375 #endif /*!__alpha__*/ 1376 1377 int 1378 linux_getsid(struct thread *td, struct linux_getsid_args *args) 1379 { 1380 struct getsid_args bsd; 1381 bsd.pid = args->pid; 1382 return getsid(td, &bsd); 1383 } 1384 1385 int 1386 linux_nosys(struct thread *td, struct nosys_args *ignore) 1387 { 1388 1389 return (ENOSYS); 1390 } 1391 1392 int 1393 linux_getpriority(struct thread *td, struct linux_getpriority_args *args) 1394 { 1395 struct getpriority_args bsd_args; 1396 int error; 1397 1398 bsd_args.which = args->which; 1399 bsd_args.who = args->who; 1400 error = getpriority(td, &bsd_args); 1401 td->td_retval[0] = 20 - td->td_retval[0]; 1402 return error; 1403 } 1404 1405 int 1406 linux_sethostname(struct thread *td, struct linux_sethostname_args *args) 1407 { 1408 struct proc *p = td->td_proc; 1409 int name[2]; 1410 int error; 1411 1412 name[0] = CTL_KERN; 1413 name[1] = KERN_HOSTNAME; 1414 if ((error = suser_cred(p->p_ucred, SUSER_ALLOWJAIL))) 1415 return (error); 1416 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, 1417 args->len, 0, 0)); 1418 } 1419 1420