The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_misc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1994-1995 Søren Schmidt
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer
   10  *    in this position and unchanged.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: releng/5.0/sys/compat/linux/linux_misc.c 105359 2002-10-17 22:00:30Z robert $
   29  */
   30 
   31 #include "opt_mac.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/blist.h>
   35 #include <sys/fcntl.h>
   36 #include <sys/imgact_aout.h>
   37 #include <sys/jail.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/mac.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mman.h>
   43 #include <sys/mount.h>
   44 #include <sys/mutex.h>
   45 #include <sys/namei.h>
   46 #include <sys/proc.h>
   47 #include <sys/reboot.h>
   48 #include <sys/resourcevar.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/stat.h>
   51 #include <sys/syscallsubr.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/sysproto.h>
   54 #include <sys/systm.h>
   55 #include <sys/time.h>
   56 #include <sys/vmmeter.h>
   57 #include <sys/vnode.h>
   58 #include <sys/wait.h>
   59 
   60 #include <vm/vm.h>
   61 #include <vm/pmap.h>
   62 #include <vm/vm_kern.h>
   63 #include <vm/vm_map.h>
   64 #include <vm/vm_extern.h>
   65 #include <vm/vm_object.h>
   66 #include <vm/swap_pager.h>
   67 
   68 #include <machine/limits.h>
   69 
   70 #include <posix4/sched.h>
   71 
   72 #include <machine/../linux/linux.h>
   73 #include <machine/../linux/linux_proto.h>
   74 
   75 #include <compat/linux/linux_mib.h>
   76 #include <compat/linux/linux_util.h>
   77 
   78 #ifdef __alpha__
   79 #define BSD_TO_LINUX_SIGNAL(sig)       (sig)
   80 #else
   81 #define BSD_TO_LINUX_SIGNAL(sig)        \
   82         (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
   83 #endif
   84 
   85 #ifndef __alpha__
   86 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
   87         RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
   88         RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
   89         RLIMIT_MEMLOCK, -1
   90 };
   91 #endif /*!__alpha__*/
   92 
   93 struct l_sysinfo {
   94         l_long          uptime;         /* Seconds since boot */
   95         l_ulong         loads[3];       /* 1, 5, and 15 minute load averages */
   96         l_ulong         totalram;       /* Total usable main memory size */
   97         l_ulong         freeram;        /* Available memory size */
   98         l_ulong         sharedram;      /* Amount of shared memory */
   99         l_ulong         bufferram;      /* Memory used by buffers */
  100         l_ulong         totalswap;      /* Total swap space size */
  101         l_ulong         freeswap;       /* swap space still available */
  102         l_ushort        procs;          /* Number of current processes */
  103         char            _f[22];         /* Pads structure to 64 bytes */
  104 };
  105 #ifndef __alpha__
  106 int
  107 linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
  108 {
  109         struct l_sysinfo sysinfo;
  110         vm_object_t object;
  111         int i;
  112         struct timespec ts;
  113 
  114         /* Uptime is copied out of print_uptime() in kern_shutdown.c */
  115         getnanouptime(&ts);
  116         i = 0;
  117         if (ts.tv_sec >= 86400) {
  118                 ts.tv_sec %= 86400;
  119                 i = 1;
  120         }
  121         if (i || ts.tv_sec >= 3600) {
  122                 ts.tv_sec %= 3600;
  123                 i = 1;
  124         }
  125         if (i || ts.tv_sec >= 60) {
  126                 ts.tv_sec %= 60;
  127                 i = 1;
  128         }
  129         sysinfo.uptime=ts.tv_sec;
  130 
  131         /* Use the information from the mib to get our load averages */
  132         for (i = 0; i < 3; i++)
  133                 sysinfo.loads[i] = averunnable.ldavg[i];
  134 
  135         sysinfo.totalram = physmem * PAGE_SIZE;
  136         sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE;
  137 
  138         sysinfo.sharedram = 0;
  139         for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
  140              object = TAILQ_NEXT(object, object_list))
  141                 if (object->shadow_count > 1)
  142                         sysinfo.sharedram += object->resident_page_count;
  143 
  144         sysinfo.sharedram *= PAGE_SIZE;
  145         sysinfo.bufferram = 0;
  146 
  147         if (swapblist == NULL) {
  148                 sysinfo.totalswap= 0;
  149                 sysinfo.freeswap = 0;
  150         } else {
  151                 sysinfo.totalswap = swapblist->bl_blocks * 1024;
  152                 sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
  153         }
  154 
  155         sysinfo.procs = 20; /* Hack */
  156 
  157         return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo));
  158 }
  159 #endif /*!__alpha__*/
  160 
  161 #ifndef __alpha__
  162 int
  163 linux_alarm(struct thread *td, struct linux_alarm_args *args)
  164 {
  165         struct itimerval it, old_it;
  166         struct timeval tv;
  167         int s;
  168 
  169 #ifdef DEBUG
  170         if (ldebug(alarm))
  171                 printf(ARGS(alarm, "%u"), args->secs);
  172 #endif
  173 
  174         if (args->secs > 100000000)
  175                 return EINVAL;
  176 
  177         it.it_value.tv_sec = (long)args->secs;
  178         it.it_value.tv_usec = 0;
  179         it.it_interval.tv_sec = 0;
  180         it.it_interval.tv_usec = 0;
  181         s = splsoftclock();
  182         old_it = td->td_proc->p_realtimer;
  183         getmicrouptime(&tv);
  184         if (timevalisset(&old_it.it_value))
  185                 callout_stop(&td->td_proc->p_itcallout);
  186         if (it.it_value.tv_sec != 0) {
  187                 callout_reset(&td->td_proc->p_itcallout, tvtohz(&it.it_value),
  188                     realitexpire, td->td_proc);
  189                 timevaladd(&it.it_value, &tv);
  190         }
  191         td->td_proc->p_realtimer = it;
  192         splx(s);
  193         if (timevalcmp(&old_it.it_value, &tv, >)) {
  194                 timevalsub(&old_it.it_value, &tv);
  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 #endif /*!__alpha__*/
  202 
  203 int
  204 linux_brk(struct thread *td, struct linux_brk_args *args)
  205 {
  206         struct vmspace *vm = td->td_proc->p_vmspace;
  207         vm_offset_t new, old;
  208         struct obreak_args /* {
  209                 char * nsize;
  210         } */ tmp;
  211 
  212 #ifdef DEBUG
  213         if (ldebug(brk))
  214                 printf(ARGS(brk, "%p"), (void *)args->dsend);
  215 #endif
  216         old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
  217         new = (vm_offset_t)args->dsend;
  218         tmp.nsize = (char *) new;
  219         if (((caddr_t)new > vm->vm_daddr) && !obreak(td, &tmp))
  220                 td->td_retval[0] = (long)new;
  221         else
  222                 td->td_retval[0] = (long)old;
  223 
  224         return 0;
  225 }
  226 
  227 int
  228 linux_uselib(struct thread *td, struct linux_uselib_args *args)
  229 {
  230         struct nameidata ni;
  231         struct vnode *vp;
  232         struct exec *a_out;
  233         struct vattr attr;
  234         vm_offset_t vmaddr;
  235         unsigned long file_offset;
  236         vm_offset_t buffer;
  237         unsigned long bss_size;
  238         char *library;
  239         int error;
  240         int locked;
  241 
  242         LCONVPATHEXIST(td, args->library, &library);
  243 
  244 #ifdef DEBUG
  245         if (ldebug(uselib))
  246                 printf(ARGS(uselib, "%s"), library);
  247 #endif
  248 
  249         a_out = NULL;
  250         locked = 0;
  251         vp = NULL;
  252 
  253         /*
  254          * XXX: This code should make use of vn_open(), rather than doing
  255          * all this stuff itself.
  256          */
  257         NDINIT(&ni, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, library, td);
  258         error = namei(&ni);
  259         LFREEPATH(library);
  260         if (error)
  261                 goto cleanup;
  262 
  263         vp = ni.ni_vp;
  264         /*
  265          * XXX - This looks like a bogus check. A LOCKLEAF namei should not
  266          * succeed without returning a vnode.
  267          */
  268         if (vp == NULL) {
  269                 error = ENOEXEC;        /* ?? */
  270                 goto cleanup;
  271         }
  272         NDFREE(&ni, NDF_ONLY_PNBUF);
  273 
  274         /*
  275          * From here on down, we have a locked vnode that must be unlocked.
  276          */
  277         locked++;
  278 
  279         /* Writable? */
  280         if (vp->v_writecount) {
  281                 error = ETXTBSY;
  282                 goto cleanup;
  283         }
  284 
  285         /* Executable? */
  286         error = VOP_GETATTR(vp, &attr, td->td_ucred, td);
  287         if (error)
  288                 goto cleanup;
  289 
  290         if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
  291             ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
  292                 error = ENOEXEC;
  293                 goto cleanup;
  294         }
  295 
  296         /* Sensible size? */
  297         if (attr.va_size == 0) {
  298                 error = ENOEXEC;
  299                 goto cleanup;
  300         }
  301 
  302         /* Can we access it? */
  303         error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
  304         if (error)
  305                 goto cleanup;
  306 
  307         /*
  308          * XXX: This should use vn_open() so that it is properly authorized,
  309          * and to reduce code redundancy all over the place here.
  310          */
  311 #ifdef MAC
  312         error = mac_check_vnode_open(td->td_ucred, vp, FREAD);
  313         if (error)
  314                 goto cleanup;
  315 #endif
  316         error = VOP_OPEN(vp, FREAD, td->td_ucred, td);
  317         if (error)
  318                 goto cleanup;
  319 
  320         /* Pull in executable header into kernel_map */
  321         error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE,
  322             VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
  323         /*
  324          * Lock no longer needed
  325          */
  326         locked = 0;
  327         VOP_UNLOCK(vp, 0, td);
  328 
  329         if (error)
  330                 goto cleanup;
  331 
  332         /* Is it a Linux binary ? */
  333         if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
  334                 error = ENOEXEC;
  335                 goto cleanup;
  336         }
  337 
  338         /*
  339          * While we are here, we should REALLY do some more checks
  340          */
  341 
  342         /* Set file/virtual offset based on a.out variant. */
  343         switch ((int)(a_out->a_magic & 0xffff)) {
  344         case 0413:      /* ZMAGIC */
  345                 file_offset = 1024;
  346                 break;
  347         case 0314:      /* QMAGIC */
  348                 file_offset = 0;
  349                 break;
  350         default:
  351                 error = ENOEXEC;
  352                 goto cleanup;
  353         }
  354 
  355         bss_size = round_page(a_out->a_bss);
  356 
  357         /* Check various fields in header for validity/bounds. */
  358         if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
  359                 error = ENOEXEC;
  360                 goto cleanup;
  361         }
  362 
  363         /* text + data can't exceed file size */
  364         if (a_out->a_data + a_out->a_text > attr.va_size) {
  365                 error = EFAULT;
  366                 goto cleanup;
  367         }
  368 
  369         /* To protect td->td_proc->p_rlimit in the if condition. */
  370         mtx_assert(&Giant, MA_OWNED);
  371 
  372         /*
  373          * text/data/bss must not exceed limits
  374          * XXX - this is not complete. it should check current usage PLUS
  375          * the resources needed by this library.
  376          */
  377         if (a_out->a_text > maxtsiz ||
  378             a_out->a_data + bss_size >
  379             td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur) {
  380                 error = ENOMEM;
  381                 goto cleanup;
  382         }
  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, (caddr_t)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((caddr_t)(uintptr_t)(buffer + file_offset),
  419                     (caddr_t)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, (caddr_t)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 int
  477 linux_select(struct thread *td, struct linux_select_args *args)
  478 {
  479         struct timeval tv0, tv1, utv, *tvp;
  480         int error;
  481 
  482 #ifdef DEBUG
  483         if (ldebug(select))
  484                 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
  485                     (void *)args->readfds, (void *)args->writefds,
  486                     (void *)args->exceptfds, (void *)args->timeout);
  487 #endif
  488 
  489         /*
  490          * Store current time for computation of the amount of
  491          * time left.
  492          */
  493         if (args->timeout) {
  494                 if ((error = copyin((caddr_t)args->timeout, &utv,
  495                     sizeof(utv))))
  496                         goto select_out;
  497 #ifdef DEBUG
  498                 if (ldebug(select))
  499                         printf(LMSG("incoming timeout (%ld/%ld)"),
  500                             utv.tv_sec, utv.tv_usec);
  501 #endif
  502 
  503                 if (itimerfix(&utv)) {
  504                         /*
  505                          * The timeval was invalid.  Convert it to something
  506                          * valid that will act as it does under Linux.
  507                          */
  508                         utv.tv_sec += utv.tv_usec / 1000000;
  509                         utv.tv_usec %= 1000000;
  510                         if (utv.tv_usec < 0) {
  511                                 utv.tv_sec -= 1;
  512                                 utv.tv_usec += 1000000;
  513                         }
  514                         if (utv.tv_sec < 0)
  515                                 timevalclear(&utv);
  516                 }
  517                 microtime(&tv0);
  518                 tvp = &utv;
  519         } else
  520                 tvp = NULL;
  521 
  522         error = kern_select(td, args->nfds, args->readfds, args->writefds,
  523             args->exceptfds, tvp);
  524 
  525 #ifdef DEBUG
  526         if (ldebug(select))
  527                 printf(LMSG("real select returns %d"), error);
  528 #endif
  529         if (error) {
  530                 /*
  531                  * See fs/select.c in the Linux kernel.  Without this,
  532                  * Maelstrom doesn't work.
  533                  */
  534                 if (error == ERESTART)
  535                         error = EINTR;
  536                 goto select_out;
  537         }
  538 
  539         if (args->timeout) {
  540                 if (td->td_retval[0]) {
  541                         /*
  542                          * Compute how much time was left of the timeout,
  543                          * by subtracting the current time and the time
  544                          * before we started the call, and subtracting
  545                          * that result from the user-supplied value.
  546                          */
  547                         microtime(&tv1);
  548                         timevalsub(&tv1, &tv0);
  549                         timevalsub(&utv, &tv1);
  550                         if (utv.tv_sec < 0)
  551                                 timevalclear(&utv);
  552                 } else
  553                         timevalclear(&utv);
  554 #ifdef DEBUG
  555                 if (ldebug(select))
  556                         printf(LMSG("outgoing timeout (%ld/%ld)"),
  557                             utv.tv_sec, utv.tv_usec);
  558 #endif
  559                 if ((error = copyout(&utv, (caddr_t)args->timeout,
  560                     sizeof(utv))))
  561                         goto select_out;
  562         }
  563 
  564 select_out:
  565 #ifdef DEBUG
  566         if (ldebug(select))
  567                 printf(LMSG("select_out -> %d"), error);
  568 #endif
  569         return error;
  570 }
  571 
  572 int     
  573 linux_mremap(struct thread *td, struct linux_mremap_args *args)
  574 {
  575         struct munmap_args /* {
  576                 void *addr;
  577                 size_t len;
  578         } */ bsd_args; 
  579         int error = 0;
  580  
  581 #ifdef DEBUG
  582         if (ldebug(mremap))
  583                 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
  584                     (void *)args->addr, 
  585                     (unsigned long)args->old_len, 
  586                     (unsigned long)args->new_len,
  587                     (unsigned long)args->flags);
  588 #endif
  589         args->new_len = round_page(args->new_len);
  590         args->old_len = round_page(args->old_len);
  591 
  592         if (args->new_len > args->old_len) {
  593                 td->td_retval[0] = 0;
  594                 return ENOMEM;
  595         }
  596 
  597         if (args->new_len < args->old_len) {
  598                 bsd_args.addr = (caddr_t)(args->addr + args->new_len);
  599                 bsd_args.len = args->old_len - args->new_len;
  600                 error = munmap(td, &bsd_args);
  601         }
  602 
  603         td->td_retval[0] = error ? 0 : (uintptr_t)args->addr;
  604         return error;
  605 }
  606 
  607 #define LINUX_MS_ASYNC       0x0001
  608 #define LINUX_MS_INVALIDATE  0x0002
  609 #define LINUX_MS_SYNC        0x0004
  610 
  611 int
  612 linux_msync(struct thread *td, struct linux_msync_args *args)
  613 {
  614         struct msync_args bsd_args;
  615 
  616         bsd_args.addr = (caddr_t)args->addr;
  617         bsd_args.len = args->len;
  618         bsd_args.flags = args->fl & ~LINUX_MS_SYNC;
  619 
  620         return msync(td, &bsd_args);
  621 }
  622 
  623 #ifndef __alpha__
  624 int
  625 linux_time(struct thread *td, struct linux_time_args *args)
  626 {
  627         struct timeval tv;
  628         l_time_t tm;
  629         int error;
  630 
  631 #ifdef DEBUG
  632         if (ldebug(time))
  633                 printf(ARGS(time, "*"));
  634 #endif
  635 
  636         microtime(&tv);
  637         tm = tv.tv_sec;
  638         if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm))))
  639                 return error;
  640         td->td_retval[0] = tm;
  641         return 0;
  642 }
  643 #endif  /*!__alpha__*/
  644 
  645 struct l_times_argv {
  646         l_long          tms_utime;
  647         l_long          tms_stime;
  648         l_long          tms_cutime;
  649         l_long          tms_cstime;
  650 };
  651 
  652 #ifdef __alpha__
  653 #define CLK_TCK 1024    /* Linux uses 1024 on alpha */
  654 #else
  655 #define CLK_TCK 100     /* Linux uses 100 */
  656 #endif
  657 
  658 #define CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
  659 
  660 int
  661 linux_times(struct thread *td, struct linux_times_args *args)
  662 {
  663         struct timeval tv;
  664         struct l_times_argv tms;
  665         struct rusage ru;
  666         int error;
  667 
  668 #ifdef DEBUG
  669         if (ldebug(times))
  670                 printf(ARGS(times, "*"));
  671 #endif
  672 
  673         mtx_lock_spin(&sched_lock);
  674         calcru(td->td_proc, &ru.ru_utime, &ru.ru_stime, NULL);
  675         mtx_unlock_spin(&sched_lock);
  676 
  677         tms.tms_utime = CONVTCK(ru.ru_utime);
  678         tms.tms_stime = CONVTCK(ru.ru_stime);
  679 
  680         tms.tms_cutime = CONVTCK(td->td_proc->p_stats->p_cru.ru_utime);
  681         tms.tms_cstime = CONVTCK(td->td_proc->p_stats->p_cru.ru_stime);
  682 
  683         if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms))))
  684                 return error;
  685 
  686         microuptime(&tv);
  687         td->td_retval[0] = (int)CONVTCK(tv);
  688         return 0;
  689 }
  690 
  691 int
  692 linux_newuname(struct thread *td, struct linux_newuname_args *args)
  693 {
  694         struct l_new_utsname utsname;
  695         char osname[LINUX_MAX_UTSNAME];
  696         char osrelease[LINUX_MAX_UTSNAME];
  697 
  698 #ifdef DEBUG
  699         if (ldebug(newuname))
  700                 printf(ARGS(newuname, "*"));
  701 #endif
  702 
  703         linux_get_osname(td->td_proc, osname);
  704         linux_get_osrelease(td->td_proc, osrelease);
  705 
  706         bzero(&utsname, sizeof(utsname));
  707         strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME);
  708         getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME);
  709         strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME);
  710         strlcpy(utsname.version, version, LINUX_MAX_UTSNAME);
  711         strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME);
  712         strlcpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME);
  713 
  714         return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname)));
  715 }
  716 
  717 #if defined(__i386__)
  718 struct l_utimbuf {
  719         l_time_t l_actime;
  720         l_time_t l_modtime;
  721 };
  722 
  723 int
  724 linux_utime(struct thread *td, struct linux_utime_args *args)
  725 {
  726         struct timeval tv[2], *tvp;
  727         struct l_utimbuf lut;
  728         char *fname;
  729         int error;
  730 
  731         LCONVPATHEXIST(td, args->fname, &fname);
  732 
  733 #ifdef DEBUG
  734         if (ldebug(utime))
  735                 printf(ARGS(utime, "%s, *"), fname);
  736 #endif
  737 
  738         if (args->times) {
  739                 if ((error = copyin((caddr_t)args->times, &lut, sizeof lut))) {
  740                         LFREEPATH(fname);
  741                         return error;
  742                 }
  743                 tv[0].tv_sec = lut.l_actime;
  744                 tv[0].tv_usec = 0;
  745                 tv[1].tv_sec = lut.l_modtime;
  746                 tv[1].tv_usec = 0;
  747                 tvp = tv;
  748         } else
  749                 tvp = NULL;
  750 
  751         error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
  752         LFREEPATH(fname);
  753         return (error);
  754 }
  755 #endif /* __i386__ */
  756 
  757 #define __WCLONE 0x80000000
  758 
  759 #ifndef __alpha__
  760 int
  761 linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
  762 {
  763         struct wait_args /* {
  764                 int pid;
  765                 int *status;
  766                 int options;
  767                 struct  rusage *rusage;
  768         } */ tmp;
  769         int error, tmpstat;
  770 
  771 #ifdef DEBUG
  772         if (ldebug(waitpid))
  773                 printf(ARGS(waitpid, "%d, %p, %d"),
  774                     args->pid, (void *)args->status, args->options);
  775 #endif
  776 
  777         tmp.pid = args->pid;
  778         tmp.status = args->status;
  779         tmp.options = (args->options & (WNOHANG | WUNTRACED));
  780         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
  781         if (args->options & __WCLONE)
  782                 tmp.options |= WLINUXCLONE;
  783         tmp.rusage = NULL;
  784 
  785         if ((error = wait4(td, &tmp)) != 0)
  786                 return error;
  787 
  788         if (args->status) {
  789                 if ((error = copyin((caddr_t)args->status, &tmpstat,
  790                     sizeof(int))) != 0)
  791                         return error;
  792                 tmpstat &= 0xffff;
  793                 if (WIFSIGNALED(tmpstat))
  794                         tmpstat = (tmpstat & 0xffffff80) |
  795                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
  796                 else if (WIFSTOPPED(tmpstat))
  797                         tmpstat = (tmpstat & 0xffff00ff) |
  798                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
  799                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
  800         }
  801 
  802         return 0;
  803 }
  804 #endif  /*!__alpha__*/
  805 
  806 int
  807 linux_wait4(struct thread *td, struct linux_wait4_args *args)
  808 {
  809         struct wait_args /* {
  810                 int pid;
  811                 int *status;
  812                 int options;
  813                 struct  rusage *rusage;
  814         } */ tmp;
  815         int error, tmpstat;
  816 
  817 #ifdef DEBUG
  818         if (ldebug(wait4))
  819                 printf(ARGS(wait4, "%d, %p, %d, %p"),
  820                     args->pid, (void *)args->status, args->options,
  821                     (void *)args->rusage);
  822 #endif
  823 
  824         tmp.pid = args->pid;
  825         tmp.status = args->status;
  826         tmp.options = (args->options & (WNOHANG | WUNTRACED));
  827         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
  828         if (args->options & __WCLONE)
  829                 tmp.options |= WLINUXCLONE;
  830         tmp.rusage = (struct rusage *)args->rusage;
  831 
  832         if ((error = wait4(td, &tmp)) != 0)
  833                 return error;
  834 
  835         SIGDELSET(td->td_proc->p_siglist, SIGCHLD);
  836 
  837         if (args->status) {
  838                 if ((error = copyin((caddr_t)args->status, &tmpstat,
  839                     sizeof(int))) != 0)
  840                         return error;
  841                 tmpstat &= 0xffff;
  842                 if (WIFSIGNALED(tmpstat))
  843                         tmpstat = (tmpstat & 0xffffff80) |
  844                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
  845                 else if (WIFSTOPPED(tmpstat))
  846                         tmpstat = (tmpstat & 0xffff00ff) |
  847                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
  848                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
  849         }
  850 
  851         return 0;
  852 }
  853 
  854 int
  855 linux_mknod(struct thread *td, struct linux_mknod_args *args)
  856 {
  857         char *path;
  858         int error;
  859 
  860         LCONVPATHCREAT(td, args->path, &path);
  861 
  862 #ifdef DEBUG
  863         if (ldebug(mknod))
  864                 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev);
  865 #endif
  866 
  867         if (args->mode & S_IFIFO)
  868                 error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode);
  869         else
  870                 error = kern_mknod(td, path, UIO_SYSSPACE, args->mode,
  871                     args->dev);
  872         LFREEPATH(path);
  873         return (error);
  874 }
  875 
  876 /*
  877  * UGH! This is just about the dumbest idea I've ever heard!!
  878  */
  879 int
  880 linux_personality(struct thread *td, struct linux_personality_args *args)
  881 {
  882 #ifdef DEBUG
  883         if (ldebug(personality))
  884                 printf(ARGS(personality, "%d"), args->per);
  885 #endif
  886 #ifndef __alpha__
  887         if (args->per != 0)
  888                 return EINVAL;
  889 #endif
  890 
  891         /* Yes Jim, it's still a Linux... */
  892         td->td_retval[0] = 0;
  893         return 0;
  894 }
  895 
  896 /*
  897  * Wrappers for get/setitimer for debugging..
  898  */
  899 int
  900 linux_setitimer(struct thread *td, struct linux_setitimer_args *args)
  901 {
  902         struct setitimer_args bsa;
  903         struct itimerval foo;
  904         int error;
  905 
  906 #ifdef DEBUG
  907         if (ldebug(setitimer))
  908                 printf(ARGS(setitimer, "%p, %p"),
  909                     (void *)args->itv, (void *)args->oitv);
  910 #endif
  911         bsa.which = args->which;
  912         bsa.itv = (struct itimerval *)args->itv;
  913         bsa.oitv = (struct itimerval *)args->oitv;
  914         if (args->itv) {
  915             if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo))))
  916                 return error;
  917 #ifdef DEBUG
  918             if (ldebug(setitimer)) {
  919                 printf("setitimer: value: sec: %ld, usec: %ld\n",
  920                     foo.it_value.tv_sec, foo.it_value.tv_usec);
  921                 printf("setitimer: interval: sec: %ld, usec: %ld\n",
  922                     foo.it_interval.tv_sec, foo.it_interval.tv_usec);
  923             }
  924 #endif
  925         }
  926         return setitimer(td, &bsa);
  927 }
  928 
  929 int
  930 linux_getitimer(struct thread *td, struct linux_getitimer_args *args)
  931 {
  932         struct getitimer_args bsa;
  933 #ifdef DEBUG
  934         if (ldebug(getitimer))
  935                 printf(ARGS(getitimer, "%p"), (void *)args->itv);
  936 #endif
  937         bsa.which = args->which;
  938         bsa.itv = (struct itimerval *)args->itv;
  939         return getitimer(td, &bsa);
  940 }
  941 
  942 #ifndef __alpha__
  943 int
  944 linux_nice(struct thread *td, struct linux_nice_args *args)
  945 {
  946         struct setpriority_args bsd_args;
  947 
  948         bsd_args.which = PRIO_PROCESS;
  949         bsd_args.who = 0;       /* current process */
  950         bsd_args.prio = args->inc;
  951         return setpriority(td, &bsd_args);
  952 }
  953 #endif  /*!__alpha__*/
  954 
  955 int
  956 linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
  957 {
  958         struct ucred *newcred, *oldcred;
  959         l_gid_t linux_gidset[NGROUPS];
  960         gid_t *bsd_gidset;
  961         int ngrp, error;
  962         struct proc *p;
  963 
  964         ngrp = args->gidsetsize;
  965         if (ngrp >= NGROUPS)
  966                 return (EINVAL);
  967         error = copyin((caddr_t)args->grouplist, linux_gidset,
  968             ngrp * sizeof(l_gid_t));
  969         if (error)
  970                 return (error);
  971         newcred = crget();
  972         p = td->td_proc;
  973         PROC_LOCK(p);
  974         oldcred = p->p_ucred;
  975 
  976         /*
  977          * cr_groups[0] holds egid. Setting the whole set from
  978          * the supplied set will cause egid to be changed too.
  979          * Keep cr_groups[0] unchanged to prevent that.
  980          */
  981 
  982         if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
  983                 PROC_UNLOCK(p);
  984                 crfree(newcred);
  985                 return (error);
  986         }
  987 
  988         crcopy(newcred, oldcred);
  989         if (ngrp > 0) {
  990                 newcred->cr_ngroups = ngrp + 1;
  991 
  992                 bsd_gidset = newcred->cr_groups;
  993                 ngrp--;
  994                 while (ngrp >= 0) {
  995                         bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
  996                         ngrp--;
  997                 }
  998         }
  999         else
 1000                 newcred->cr_ngroups = 1;
 1001 
 1002         setsugid(p);
 1003         p->p_ucred = newcred;
 1004         PROC_UNLOCK(p);
 1005         crfree(oldcred);
 1006         return (0);
 1007 }
 1008 
 1009 int
 1010 linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
 1011 {
 1012         struct ucred *cred;
 1013         l_gid_t linux_gidset[NGROUPS];
 1014         gid_t *bsd_gidset;
 1015         int bsd_gidsetsz, ngrp, error;
 1016 
 1017         cred = td->td_ucred;
 1018         bsd_gidset = cred->cr_groups;
 1019         bsd_gidsetsz = cred->cr_ngroups - 1;
 1020 
 1021         /*
 1022          * cr_groups[0] holds egid. Returning the whole set
 1023          * here will cause a duplicate. Exclude cr_groups[0]
 1024          * to prevent that.
 1025          */
 1026 
 1027         if ((ngrp = args->gidsetsize) == 0) {
 1028                 td->td_retval[0] = bsd_gidsetsz;
 1029                 return (0);
 1030         }
 1031 
 1032         if (ngrp < bsd_gidsetsz)
 1033                 return (EINVAL);
 1034 
 1035         ngrp = 0;
 1036         while (ngrp < bsd_gidsetsz) {
 1037                 linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
 1038                 ngrp++;
 1039         }
 1040 
 1041         if ((error = copyout(linux_gidset, (caddr_t)args->grouplist,
 1042             ngrp * sizeof(l_gid_t))))
 1043                 return (error);
 1044 
 1045         td->td_retval[0] = ngrp;
 1046         return (0);
 1047 }
 1048 
 1049 #ifndef __alpha__
 1050 int
 1051 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args)
 1052 {
 1053         struct rlimit bsd_rlim;
 1054         struct l_rlimit rlim;
 1055         u_int which;
 1056         int error;
 1057 
 1058 #ifdef DEBUG
 1059         if (ldebug(setrlimit))
 1060                 printf(ARGS(setrlimit, "%d, %p"),
 1061                     args->resource, (void *)args->rlim);
 1062 #endif
 1063 
 1064         if (args->resource >= LINUX_RLIM_NLIMITS)
 1065                 return (EINVAL);
 1066 
 1067         which = linux_to_bsd_resource[args->resource];
 1068         if (which == -1)
 1069                 return (EINVAL);
 1070 
 1071         error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim));
 1072         if (error)
 1073                 return (error);
 1074 
 1075         bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur;
 1076         bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max;
 1077         return (dosetrlimit(td, which, &bsd_rlim));
 1078 }
 1079 
 1080 int
 1081 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args)
 1082 {
 1083         struct l_rlimit rlim;
 1084         struct proc *p = td->td_proc;
 1085         struct rlimit *bsd_rlp;
 1086         u_int which;
 1087 
 1088 #ifdef DEBUG
 1089         if (ldebug(old_getrlimit))
 1090                 printf(ARGS(old_getrlimit, "%d, %p"),
 1091                     args->resource, (void *)args->rlim);
 1092 #endif
 1093 
 1094         if (args->resource >= LINUX_RLIM_NLIMITS)
 1095                 return (EINVAL);
 1096 
 1097         which = linux_to_bsd_resource[args->resource];
 1098         if (which == -1)
 1099                 return (EINVAL);
 1100         bsd_rlp = &p->p_rlimit[which];
 1101 
 1102         rlim.rlim_cur = (unsigned long)bsd_rlp->rlim_cur;
 1103         if (rlim.rlim_cur == ULONG_MAX)
 1104                 rlim.rlim_cur = LONG_MAX;
 1105         rlim.rlim_max = (unsigned long)bsd_rlp->rlim_max;
 1106         if (rlim.rlim_max == ULONG_MAX)
 1107                 rlim.rlim_max = LONG_MAX;
 1108         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
 1109 }
 1110 
 1111 int
 1112 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args)
 1113 {
 1114         struct l_rlimit rlim;
 1115         struct proc *p = td->td_proc;
 1116         struct rlimit *bsd_rlp;
 1117         u_int which;
 1118 
 1119 #ifdef DEBUG
 1120         if (ldebug(getrlimit))
 1121                 printf(ARGS(getrlimit, "%d, %p"),
 1122                     args->resource, (void *)args->rlim);
 1123 #endif
 1124 
 1125         if (args->resource >= LINUX_RLIM_NLIMITS)
 1126                 return (EINVAL);
 1127 
 1128         which = linux_to_bsd_resource[args->resource];
 1129         if (which == -1)
 1130                 return (EINVAL);
 1131         bsd_rlp = &p->p_rlimit[which];
 1132 
 1133         rlim.rlim_cur = (l_ulong)bsd_rlp->rlim_cur;
 1134         rlim.rlim_max = (l_ulong)bsd_rlp->rlim_max;
 1135         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
 1136 }
 1137 #endif /*!__alpha__*/
 1138 
 1139 int
 1140 linux_sched_setscheduler(struct thread *td,
 1141     struct linux_sched_setscheduler_args *args)
 1142 {
 1143         struct sched_setscheduler_args bsd;
 1144 
 1145 #ifdef DEBUG
 1146         if (ldebug(sched_setscheduler))
 1147                 printf(ARGS(sched_setscheduler, "%d, %d, %p"),
 1148                     args->pid, args->policy, (const void *)args->param);
 1149 #endif
 1150 
 1151         switch (args->policy) {
 1152         case LINUX_SCHED_OTHER:
 1153                 bsd.policy = SCHED_OTHER;
 1154                 break;
 1155         case LINUX_SCHED_FIFO:
 1156                 bsd.policy = SCHED_FIFO;
 1157                 break;
 1158         case LINUX_SCHED_RR:
 1159                 bsd.policy = SCHED_RR;
 1160                 break;
 1161         default:
 1162                 return EINVAL;
 1163         }
 1164 
 1165         bsd.pid = args->pid;
 1166         bsd.param = (struct sched_param *)args->param;
 1167         return sched_setscheduler(td, &bsd);
 1168 }
 1169 
 1170 int
 1171 linux_sched_getscheduler(struct thread *td,
 1172     struct linux_sched_getscheduler_args *args)
 1173 {
 1174         struct sched_getscheduler_args bsd;
 1175         int error;
 1176 
 1177 #ifdef DEBUG
 1178         if (ldebug(sched_getscheduler))
 1179                 printf(ARGS(sched_getscheduler, "%d"), args->pid);
 1180 #endif
 1181 
 1182         bsd.pid = args->pid;
 1183         error = sched_getscheduler(td, &bsd);
 1184 
 1185         switch (td->td_retval[0]) {
 1186         case SCHED_OTHER:
 1187                 td->td_retval[0] = LINUX_SCHED_OTHER;
 1188                 break;
 1189         case SCHED_FIFO:
 1190                 td->td_retval[0] = LINUX_SCHED_FIFO;
 1191                 break;
 1192         case SCHED_RR:
 1193                 td->td_retval[0] = LINUX_SCHED_RR;
 1194                 break;
 1195         }
 1196 
 1197         return error;
 1198 }
 1199 
 1200 int
 1201 linux_sched_get_priority_max(struct thread *td,
 1202     struct linux_sched_get_priority_max_args *args)
 1203 {
 1204         struct sched_get_priority_max_args bsd;
 1205 
 1206 #ifdef DEBUG
 1207         if (ldebug(sched_get_priority_max))
 1208                 printf(ARGS(sched_get_priority_max, "%d"), args->policy);
 1209 #endif
 1210 
 1211         switch (args->policy) {
 1212         case LINUX_SCHED_OTHER:
 1213                 bsd.policy = SCHED_OTHER;
 1214                 break;
 1215         case LINUX_SCHED_FIFO:
 1216                 bsd.policy = SCHED_FIFO;
 1217                 break;
 1218         case LINUX_SCHED_RR:
 1219                 bsd.policy = SCHED_RR;
 1220                 break;
 1221         default:
 1222                 return EINVAL;
 1223         }
 1224         return sched_get_priority_max(td, &bsd);
 1225 }
 1226 
 1227 int
 1228 linux_sched_get_priority_min(struct thread *td,
 1229     struct linux_sched_get_priority_min_args *args)
 1230 {
 1231         struct sched_get_priority_min_args bsd;
 1232 
 1233 #ifdef DEBUG
 1234         if (ldebug(sched_get_priority_min))
 1235                 printf(ARGS(sched_get_priority_min, "%d"), args->policy);
 1236 #endif
 1237 
 1238         switch (args->policy) {
 1239         case LINUX_SCHED_OTHER:
 1240                 bsd.policy = SCHED_OTHER;
 1241                 break;
 1242         case LINUX_SCHED_FIFO:
 1243                 bsd.policy = SCHED_FIFO;
 1244                 break;
 1245         case LINUX_SCHED_RR:
 1246                 bsd.policy = SCHED_RR;
 1247                 break;
 1248         default:
 1249                 return EINVAL;
 1250         }
 1251         return sched_get_priority_min(td, &bsd);
 1252 }
 1253 
 1254 #define REBOOT_CAD_ON   0x89abcdef
 1255 #define REBOOT_CAD_OFF  0
 1256 #define REBOOT_HALT     0xcdef0123
 1257 
 1258 int
 1259 linux_reboot(struct thread *td, struct linux_reboot_args *args)
 1260 {
 1261         struct reboot_args bsd_args;
 1262 
 1263 #ifdef DEBUG
 1264         if (ldebug(reboot))
 1265                 printf(ARGS(reboot, "0x%x"), args->cmd);
 1266 #endif
 1267         if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF)
 1268                 return (0);
 1269         bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0;
 1270         return (reboot(td, &bsd_args));
 1271 }
 1272 
 1273 #ifndef __alpha__
 1274 
 1275 /*
 1276  * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify
 1277  * td->td_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This
 1278  * globbers registers that are assumed to be preserved. The following
 1279  * lightweight syscalls fixes this. See also linux_getgid16() and
 1280  * linux_getuid16() in linux_uid16.c.
 1281  *
 1282  * linux_getpid() - MP SAFE
 1283  * linux_getgid() - MP SAFE
 1284  * linux_getuid() - MP SAFE
 1285  */
 1286 
 1287 int
 1288 linux_getpid(struct thread *td, struct linux_getpid_args *args)
 1289 {
 1290 
 1291         td->td_retval[0] = td->td_proc->p_pid;
 1292         return (0);
 1293 }
 1294 
 1295 int
 1296 linux_getgid(struct thread *td, struct linux_getgid_args *args)
 1297 {
 1298 
 1299         td->td_retval[0] = td->td_ucred->cr_rgid;
 1300         return (0);
 1301 }
 1302 
 1303 int
 1304 linux_getuid(struct thread *td, struct linux_getuid_args *args)
 1305 {
 1306 
 1307         td->td_retval[0] = td->td_ucred->cr_ruid;
 1308         return (0);
 1309 }
 1310 
 1311 #endif /*!__alpha__*/
 1312 
 1313 int
 1314 linux_getsid(struct thread *td, struct linux_getsid_args *args)
 1315 {
 1316         struct getsid_args bsd;
 1317         bsd.pid = args->pid;
 1318         return getsid(td, &bsd);
 1319 }

Cache object: 4fdc24e93ae250e70caf71f1fe494c3b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.