root/kern/sys_process.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_ptrace
  2. process_checkioperm
  3. process_domem

    1 /*      $OpenBSD: sys_process.c,v 1.39 2007/04/10 17:47:55 miod Exp $   */
    2 /*      $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $     */
    3 
    4 /*-
    5  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
    6  * Copyright (c) 1982, 1986, 1989, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  * (c) UNIX System Laboratories, Inc.
    9  * All or some portions of this file are derived from material licensed
   10  * to the University of California by American Telephone and Telegraph
   11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   12  * the permission of UNIX System Laboratories, Inc.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
   39  */
   40 
   41 /*
   42  * References:
   43  *      (1) Bach's "The Design of the UNIX Operating System",
   44  *      (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
   45  *      (3) the "4.4BSD Programmer's Reference Manual" published
   46  *              by USENIX and O'Reilly & Associates.
   47  * The 4.4BSD PRM does a reasonably good job of documenting what the various
   48  * ptrace() requests should actually do, and its text is quoted several times
   49  * in this file.
   50  */
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/proc.h>
   55 #include <sys/signalvar.h>
   56 #include <sys/errno.h>
   57 #include <sys/malloc.h>
   58 #include <sys/ptrace.h>
   59 #include <sys/uio.h>
   60 #include <sys/user.h>
   61 #include <sys/sched.h>
   62 
   63 #include <sys/mount.h>
   64 #include <sys/syscallargs.h>
   65 
   66 #include <uvm/uvm_extern.h>
   67 
   68 #include <machine/reg.h>
   69 
   70 #ifdef PTRACE
   71 /*
   72  * Process debugging system call.
   73  */
   74 int
   75 sys_ptrace(struct proc *p, void *v, register_t *retval)
   76 {
   77         struct sys_ptrace_args /* {
   78                 syscallarg(int) req;
   79                 syscallarg(pid_t) pid;
   80                 syscallarg(caddr_t) addr;
   81                 syscallarg(int) data;
   82         } */ *uap = v;
   83         struct proc *t;                         /* target process */
   84         struct uio uio;
   85         struct iovec iov;
   86         struct ptrace_io_desc piod;
   87         struct ptrace_event pe;
   88         struct reg *regs;
   89 #if defined (PT_SETFPREGS) || defined (PT_GETFPREGS)
   90         struct fpreg *fpregs;
   91 #endif
   92 #if defined (PT_SETXMMREGS) || defined (PT_GETXMMREGS)
   93         struct xmmregs *xmmregs;
   94 #endif
   95 #ifdef PT_WCOOKIE
   96         register_t wcookie;
   97 #endif
   98         int error, write;
   99         int temp;
  100         int req;
  101         int s;
  102 
  103         /* "A foolish consistency..." XXX */
  104         if (SCARG(uap, req) == PT_TRACE_ME)
  105                 t = p;
  106         else {
  107 
  108                 /* Find the process we're supposed to be operating on. */
  109                 if ((t = pfind(SCARG(uap, pid))) == NULL)
  110                         return (ESRCH);
  111         }
  112 
  113         if ((t->p_flag & P_INEXEC) != 0)
  114                 return (EAGAIN);
  115 
  116         /* Make sure we can operate on it. */
  117         switch (SCARG(uap, req)) {
  118         case  PT_TRACE_ME:
  119                 /* Saying that you're being traced is always legal. */
  120                 break;
  121 
  122         case  PT_ATTACH:
  123                 /*
  124                  * You can't attach to a process if:
  125                  *      (1) it's the process that's doing the attaching,
  126                  */
  127                 if (t->p_pid == p->p_pid)
  128                         return (EINVAL);
  129 
  130                 /*
  131                  *      (2) it's a system process
  132                  */
  133                 if (ISSET(t->p_flag, P_SYSTEM))
  134                         return (EPERM);
  135 
  136                 /*
  137                  *      (3) it's already being traced, or
  138                  */
  139                 if (ISSET(t->p_flag, P_TRACED))
  140                         return (EBUSY);
  141 
  142                 /*
  143                  *      (4) it's not owned by you, or the last exec
  144                  *          gave us setuid/setgid privs (unless
  145                  *          you're root), or...
  146                  * 
  147                  *      [Note: once P_SUGID or P_SUGIDEXEC gets set in
  148                  *      execve(), they stay set until the process does
  149                  *      another execve().  Hence this prevents a setuid
  150                  *      process which revokes its special privileges using
  151                  *      setuid() from being traced.  This is good security.]
  152                  */
  153                 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
  154                     ISSET(t->p_flag, P_SUGIDEXEC) ||
  155                     ISSET(t->p_flag, P_SUGID)) &&
  156                     (error = suser(p, 0)) != 0)
  157                         return (error);
  158 
  159                 /*
  160                  *      (5) ...it's init, which controls the security level
  161                  *          of the entire system, and the system was not
  162                  *          compiled with permanently insecure mode turned
  163                  *          on.
  164                  */
  165                 if ((t->p_pid == 1) && (securelevel > -1))
  166                         return (EPERM);
  167                 break;
  168 
  169         case  PT_READ_I:
  170         case  PT_READ_D:
  171         case  PT_WRITE_I:
  172         case  PT_WRITE_D:
  173         case  PT_IO:
  174         case  PT_CONTINUE:
  175         case  PT_KILL:
  176         case  PT_DETACH:
  177 #ifdef PT_STEP
  178         case  PT_STEP:
  179 #endif
  180         case  PT_SET_EVENT_MASK:
  181         case  PT_GET_EVENT_MASK:
  182         case  PT_GET_PROCESS_STATE:
  183         case  PT_GETREGS:
  184         case  PT_SETREGS:
  185 #ifdef PT_GETFPREGS
  186         case  PT_GETFPREGS:
  187 #endif
  188 #ifdef PT_SETFPREGS
  189         case  PT_SETFPREGS:
  190 #endif
  191 #ifdef PT_GETXMMREGS
  192         case  PT_GETXMMREGS:
  193 #endif
  194 #ifdef PT_SETXMMREGS
  195         case  PT_SETXMMREGS:
  196 #endif
  197 #ifdef PT_WCOOKIE
  198         case  PT_WCOOKIE:
  199 #endif
  200                 /*
  201                  * You can't do what you want to the process if:
  202                  *      (1) It's not being traced at all,
  203                  */
  204                 if (!ISSET(t->p_flag, P_TRACED))
  205                         return (EPERM);
  206 
  207                 /*
  208                  *      (2) it's not being traced by _you_, or
  209                  */
  210                 if (t->p_pptr != p)
  211                         return (EBUSY);
  212 
  213                 /*
  214                  *      (3) it's not currently stopped.
  215                  */
  216                 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
  217                         return (EBUSY);
  218                 break;
  219 
  220         default:                        /* It was not a legal request. */
  221                 return (EINVAL);
  222         }
  223 
  224         /* Do single-step fixup if needed. */
  225         FIX_SSTEP(t);
  226 
  227         /* Now do the operation. */
  228         write = 0;
  229         *retval = 0;
  230 
  231         switch (SCARG(uap, req)) {
  232         case  PT_TRACE_ME:
  233                 /* Just set the trace flag. */
  234                 atomic_setbits_int(&t->p_flag, P_TRACED);
  235                 t->p_oppid = t->p_pptr->p_pid;
  236                 if (t->p_ptstat == NULL)
  237                         t->p_ptstat = malloc(sizeof(*t->p_ptstat),
  238                             M_SUBPROC, M_WAITOK);
  239                 bzero(t->p_ptstat, sizeof(*t->p_ptstat));
  240                 return (0);
  241 
  242         case  PT_WRITE_I:               /* XXX no separate I and D spaces */
  243         case  PT_WRITE_D:
  244                 write = 1;
  245                 temp = SCARG(uap, data);
  246         case  PT_READ_I:                /* XXX no separate I and D spaces */
  247         case  PT_READ_D:
  248                 /* write = 0 done above. */
  249                 iov.iov_base = (caddr_t)&temp;
  250                 iov.iov_len = sizeof(int);
  251                 uio.uio_iov = &iov;
  252                 uio.uio_iovcnt = 1;
  253                 uio.uio_offset = (off_t)(long)SCARG(uap, addr);
  254                 uio.uio_resid = sizeof(int);
  255                 uio.uio_segflg = UIO_SYSSPACE;
  256                 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  257                 uio.uio_procp = p;
  258                 error = process_domem(p, t, &uio, write ? PT_WRITE_I :
  259                                 PT_READ_I);
  260                 if (write == 0)
  261                         *retval = temp;
  262                 return (error);
  263         case  PT_IO:
  264                 error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
  265                 if (error)
  266                         return (error);
  267                 iov.iov_base = piod.piod_addr;
  268                 iov.iov_len = piod.piod_len;
  269                 uio.uio_iov = &iov;
  270                 uio.uio_iovcnt = 1;
  271                 uio.uio_offset = (off_t)(long)piod.piod_offs;
  272                 uio.uio_resid = piod.piod_len;
  273                 uio.uio_segflg = UIO_USERSPACE;
  274                 uio.uio_procp = p;
  275                 switch (piod.piod_op) {
  276                 case PIOD_READ_I:
  277                         req = PT_READ_I;
  278                         uio.uio_rw = UIO_READ;
  279                         break;
  280                 case PIOD_READ_D:
  281                         req = PT_READ_D;
  282                         uio.uio_rw = UIO_READ;
  283                         break;
  284                 case PIOD_WRITE_I:
  285                         req = PT_WRITE_I;
  286                         uio.uio_rw = UIO_WRITE;
  287                         break;
  288                 case PIOD_WRITE_D:
  289                         req = PT_WRITE_D;
  290                         uio.uio_rw = UIO_WRITE;
  291                         break;
  292                 default:
  293                         return (EINVAL);
  294                 }
  295                 error = process_domem(p, t, &uio, req);
  296                 piod.piod_len -= uio.uio_resid;
  297                 (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
  298                 return (error);
  299 #ifdef PT_STEP
  300         case  PT_STEP:
  301                 /*
  302                  * From the 4.4BSD PRM:
  303                  * "Execution continues as in request PT_CONTINUE; however
  304                  * as soon as possible after execution of at least one
  305                  * instruction, execution stops again. [ ... ]"
  306                  */
  307 #endif
  308         case  PT_CONTINUE:
  309                 /*
  310                  * From the 4.4BSD PRM:
  311                  * "The data argument is taken as a signal number and the
  312                  * child's execution continues at location addr as if it
  313                  * incurred that signal.  Normally the signal number will
  314                  * be either 0 to indicate that the signal that caused the
  315                  * stop should be ignored, or that value fetched out of
  316                  * the process's image indicating which signal caused
  317                  * the stop.  If addr is (int *)1 then execution continues
  318                  * from where it stopped."
  319                  */
  320 
  321                 /* Check that the data is a valid signal number or zero. */
  322                 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
  323                         return (EINVAL);
  324 
  325                 /* If the address parameter is not (int *)1, set the pc. */
  326                 if ((int *)SCARG(uap, addr) != (int *)1)
  327                         if ((error = process_set_pc(t, SCARG(uap, addr))) != 0)
  328                                 goto relebad;
  329 
  330 #ifdef PT_STEP
  331                 /*
  332                  * Arrange for a single-step, if that's requested and possible.
  333                  */
  334                 error = process_sstep(t, SCARG(uap, req) == PT_STEP);
  335                 if (error)
  336                         goto relebad;
  337 #endif
  338                 goto sendsig;
  339 
  340         case  PT_DETACH:
  341                 /*
  342                  * From the 4.4BSD PRM:
  343                  * "The data argument is taken as a signal number and the
  344                  * child's execution continues at location addr as if it
  345                  * incurred that signal.  Normally the signal number will
  346                  * be either 0 to indicate that the signal that caused the
  347                  * stop should be ignored, or that value fetched out of
  348                  * the process's image indicating which signal caused
  349                  * the stop.  If addr is (int *)1 then execution continues
  350                  * from where it stopped."
  351                  */
  352 
  353                 /* Check that the data is a valid signal number or zero. */
  354                 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
  355                         return (EINVAL);
  356 
  357 #ifdef PT_STEP
  358                 /*
  359                  * Arrange for a single-step, if that's requested and possible.
  360                  */
  361                 error = process_sstep(t, SCARG(uap, req) == PT_STEP);
  362                 if (error)
  363                         goto relebad;
  364 #endif
  365 
  366                 /* give process back to original parent or init */
  367                 if (t->p_oppid != t->p_pptr->p_pid) {
  368                         struct proc *pp;
  369 
  370                         pp = pfind(t->p_oppid);
  371                         proc_reparent(t, pp ? pp : initproc);
  372                 }
  373 
  374                 /* not being traced any more */
  375                 t->p_oppid = 0;
  376                 atomic_clearbits_int(&t->p_flag, P_TRACED|P_WAITED);
  377 
  378         sendsig:
  379                 bzero(t->p_ptstat, sizeof(*t->p_ptstat));
  380 
  381                 /* Finally, deliver the requested signal (or none). */
  382                 if (t->p_stat == SSTOP) {
  383                         t->p_xstat = SCARG(uap, data);
  384                         SCHED_LOCK(s);
  385                         setrunnable(t);
  386                         SCHED_UNLOCK(s);
  387                 } else {
  388                         if (SCARG(uap, data) != 0)
  389                                 psignal(t, SCARG(uap, data));
  390                 }
  391                 return (0);
  392 
  393         relebad:
  394                 return (error);
  395 
  396         case  PT_KILL:
  397                 /* just send the process a KILL signal. */
  398                 SCARG(uap, data) = SIGKILL;
  399                 goto sendsig;   /* in PT_CONTINUE, above. */
  400 
  401         case  PT_ATTACH:
  402                 /*
  403                  * As done in procfs:
  404                  * Go ahead and set the trace flag.
  405                  * Save the old parent (it's reset in
  406                  *   _DETACH, and also in kern_exit.c:wait4()
  407                  * Reparent the process so that the tracing
  408                  *   proc gets to see all the action.
  409                  * Stop the target.
  410                  */
  411                 atomic_setbits_int(&t->p_flag, P_TRACED);
  412                 t->p_oppid = t->p_pptr->p_pid;
  413                 if (t->p_pptr != p)
  414                         proc_reparent(t, p);
  415                 if (t->p_ptstat == NULL)
  416                         t->p_ptstat = malloc(sizeof(*t->p_ptstat),
  417                             M_SUBPROC, M_WAITOK);
  418                 SCARG(uap, data) = SIGSTOP;
  419                 goto sendsig;
  420 
  421         case  PT_GET_EVENT_MASK:
  422                 if (SCARG(uap, data) != sizeof(pe))
  423                         return (EINVAL);
  424                 bzero(&pe, sizeof(pe));
  425                 pe.pe_set_event = t->p_ptmask;
  426                 return (copyout(&pe, SCARG(uap, addr), sizeof(pe)));
  427         case  PT_SET_EVENT_MASK:
  428                 if (SCARG(uap, data) != sizeof(pe))
  429                         return (EINVAL);
  430                 if ((error = copyin(SCARG(uap, addr), &pe, sizeof(pe))))
  431                         return (error);
  432                 t->p_ptmask = pe.pe_set_event;
  433                 return (0);
  434 
  435         case  PT_GET_PROCESS_STATE:
  436                 if (SCARG(uap, data) != sizeof(*t->p_ptstat))
  437                         return (EINVAL);
  438                 return (copyout(t->p_ptstat, SCARG(uap, addr),
  439                     sizeof(*t->p_ptstat)));
  440 
  441         case  PT_SETREGS:
  442                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  443                 if ((error = process_checkioperm(p, t)) != 0)
  444                         return (error);
  445 
  446                 regs = malloc(sizeof(*regs), M_TEMP, M_WAITOK);
  447                 error = copyin(SCARG(uap, addr), regs, sizeof(*regs));
  448                 if (error == 0) {
  449                         error = process_write_regs(t, regs);
  450                 }
  451                 free(regs, M_TEMP);
  452                 return (error);
  453         case  PT_GETREGS:
  454                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  455                 if ((error = process_checkioperm(p, t)) != 0)
  456                         return (error);
  457 
  458                 regs = malloc(sizeof(*regs), M_TEMP, M_WAITOK);
  459                 error = process_read_regs(t, regs);
  460                 if (error == 0)
  461                         error = copyout(regs,
  462                             SCARG(uap, addr), sizeof (*regs));
  463                 free(regs, M_TEMP);
  464                 return (error);
  465 #ifdef PT_SETFPREGS
  466         case  PT_SETFPREGS:
  467                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  468                 if ((error = process_checkioperm(p, t)) != 0)
  469                         return (error);
  470 
  471                 fpregs = malloc(sizeof(*fpregs), M_TEMP, M_WAITOK);
  472                 error = copyin(SCARG(uap, addr), fpregs, sizeof(*fpregs));
  473                 if (error == 0) {
  474                         error = process_write_fpregs(t, fpregs);
  475                 }
  476                 free(fpregs, M_TEMP);
  477                 return (error);
  478 #endif
  479 #ifdef PT_GETFPREGS
  480         case  PT_GETFPREGS:
  481                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  482                 if ((error = process_checkioperm(p, t)) != 0)
  483                         return (error);
  484 
  485                 fpregs = malloc(sizeof(*fpregs), M_TEMP, M_WAITOK);
  486                 error = process_read_fpregs(t, fpregs);
  487                 if (error == 0)
  488                         error = copyout(fpregs,
  489                             SCARG(uap, addr), sizeof(*fpregs));
  490                 free(fpregs, M_TEMP);
  491                 return (error);
  492 #endif
  493 #ifdef PT_SETXMMREGS
  494         case  PT_SETXMMREGS:
  495                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  496                 if ((error = process_checkioperm(p, t)) != 0)
  497                         return (error);
  498 
  499                 xmmregs = malloc(sizeof(*xmmregs), M_TEMP, M_WAITOK);
  500                 error = copyin(SCARG(uap, addr), xmmregs, sizeof(*xmmregs));
  501                 if (error == 0) {
  502                         error = process_write_xmmregs(t, xmmregs);
  503                 }
  504                 free(xmmregs, M_TEMP);
  505                 return (error);
  506 #endif
  507 #ifdef PT_GETXMMREGS
  508         case  PT_GETXMMREGS:
  509                 KASSERT((p->p_flag & P_SYSTEM) == 0);
  510                 if ((error = process_checkioperm(p, t)) != 0)
  511                         return (error);
  512 
  513                 xmmregs = malloc(sizeof(*xmmregs), M_TEMP, M_WAITOK);
  514                 error = process_read_xmmregs(t, xmmregs);
  515                 if (error == 0)
  516                         error = copyout(xmmregs,
  517                             SCARG(uap, addr), sizeof(*xmmregs));
  518                 free(xmmregs, M_TEMP);
  519                 return (error);
  520 #endif
  521 #ifdef PT_WCOOKIE
  522         case  PT_WCOOKIE:
  523                 wcookie = process_get_wcookie (t);
  524                 return (copyout(&wcookie, SCARG(uap, addr),
  525                     sizeof (register_t)));
  526 #endif
  527         }
  528 
  529 #ifdef DIAGNOSTIC
  530         panic("ptrace: impossible");
  531 #endif
  532         return 0;
  533 }
  534 #endif  /* PTRACE */
  535 
  536 /*
  537  * Check if a process is allowed to fiddle with the memory of another.
  538  *
  539  * p = tracer
  540  * t = tracee
  541  *
  542  * 1.  You can't attach to a process not owned by you or one that has raised
  543  *     its privileges.
  544  * 1a. ...unless you are root.
  545  *
  546  * 2.  init is always off-limits because it can control the securelevel.
  547  * 2a. ...unless securelevel is permanently set to insecure.
  548  *
  549  * 3.  Processes that are in the process of doing an exec() are always
  550  *     off-limits because of the can of worms they are. Just wait a
  551  *     second.
  552  */
  553 int
  554 process_checkioperm(struct proc *p, struct proc *t)
  555 {
  556         int error;
  557 
  558         if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
  559             ISSET(t->p_flag, P_SUGIDEXEC) ||
  560             ISSET(t->p_flag, P_SUGID)) &&
  561             (error = suser(p, 0)) != 0)
  562                 return (error);
  563 
  564         if ((t->p_pid == 1) && (securelevel > -1))
  565                 return (EPERM);
  566 
  567         if (t->p_flag & P_INEXEC)
  568                 return (EAGAIN);
  569 
  570         return (0);
  571 }
  572 
  573 int
  574 process_domem(struct proc *curp, struct proc *p, struct uio *uio, int req)
  575 {
  576         int error;
  577         vaddr_t addr;
  578         vsize_t len;
  579 
  580         len = uio->uio_resid;
  581         if (len == 0)
  582                 return (0);
  583 
  584         if ((error = process_checkioperm(curp, p)) != 0)
  585                 return (error);
  586 
  587         /* XXXCDC: how should locking work here? */
  588         if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 
  589                 return(EFAULT);
  590         addr = uio->uio_offset;
  591         p->p_vmspace->vm_refcnt++;  /* XXX */
  592         error = uvm_io(&p->p_vmspace->vm_map, uio,
  593             (req == PT_WRITE_I) ? UVM_IO_FIXPROT : 0);
  594         uvmspace_free(p->p_vmspace);
  595 
  596         if (error == 0 && req == PT_WRITE_I)
  597                 pmap_proc_iflush(p, addr, len);
  598 
  599         return (error);
  600 }

/* [<][>][^][v][top][bottom][index][help] */