[BACK]Return to sys_process.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/sys_process.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb