Annotation of Net2/kern/sys_process.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      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:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
                     33:  *     from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
1.1.1.5 ! root       34:  *     sys_process.c,v 1.8 1993/07/13 22:13:33 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #define IPCREG
                     38: #include "param.h"
1.1.1.5 ! root       39: #include "systm.h"
1.1       root       40: #include "proc.h"
                     41: #include "vnode.h"
                     42: #include "buf.h"
                     43: #include "ptrace.h"
                     44: 
                     45: #include "machine/reg.h"
                     46: #include "machine/psl.h"
                     47: #include "vm/vm.h"
                     48: #include "vm/vm_page.h"
                     49: 
                     50: #include "user.h"
                     51: 
                     52: /*
1.1.1.3   root       53:  * NOTES.
                     54:  *
                     55:  * The following ptrace calls have been defined in addition to
                     56:  * the standard ones found in original <sys/ptrace.h>:
                     57:  *
                     58:  * PT_ATTACH           -       attach to running process
                     59:  * PT_DETACH           -       detach from running process
                     60:  * PT_SYSCALL          -       trace system calls
                     61:  * PT_GETREG           -       get register file
                     62:  * PT_SETREG           -       set register file
                     63:  * PT_BREAD_[IDU]      -       block read from process (not yet implemented)
                     64:  * PT_BWRITE_[IDU]     -       block write     "               "
                     65:  * PT_INHERIT          -       make forked processes inherit trace flags
                     66:  *
                     67:  */
                     68: 
                     69: /* Define to prevent extraneous clutter in source */
                     70: #ifndef SSTRC
                     71: #define        SSTRC   0
                     72: #endif
                     73: #ifndef SFTRC
                     74: #define        SFTRC   0
                     75: #endif
                     76: 
                     77: struct {
                     78:        int     flag;
                     79: #define IPC_BUSY       1
                     80: #define IPC_WANT       2
                     81: #define IPC_DONE       4
                     82:        int     req;                    /* copy of ptrace request */
                     83:        int     *addr;                  /* copy of ptrace address */
                     84:        int     data;                   /* copy of ptrace data */
                     85:        int     error;                  /* errno from `procxmt' */
                     86:        int     regs[NIPCREG];          /* PT_[GS]ETREG */
                     87:        caddr_t buf;                    /* PT_BREAD/WRITE */
                     88:        int     buflen;                 /*      "       */
                     89: } ipc;
                     90: 
                     91: /*
1.1       root       92:  * Process debugging system call.
                     93:  */
1.1.1.5 ! root       94: 
        !            95: struct ptrace_args {
        !            96:        int     req;
        !            97:        int     pid;
        !            98:        int     *addr;
        !            99:        int     data;
        !           100: };
        !           101: 
        !           102: int
1.1       root      103: ptrace(curp, uap, retval)
                    104:        struct proc *curp;
1.1.1.5 ! root      105:        register struct ptrace_args *uap;
1.1       root      106:        int *retval;
                    107: {
1.1.1.3   root      108:        struct proc *p;
1.1.1.5 ! root      109:        int error = 0;
1.1       root      110: 
1.1.1.3   root      111:        *retval = 0;
                    112:        if (uap->req == PT_TRACE_ME) {
                    113:                curp->p_flag |= STRC;
                    114:                /*p->p_tptr = p->p_pptr; * What shall we do here ? */
                    115:                return 0;
                    116:        }
                    117:        if ((p = pfind(uap->pid)) == NULL) {
                    118:                return ESRCH;
                    119:        }
                    120: 
                    121: #ifdef notyet
                    122:        if (uap->req != PT_ATTACH && (
                    123:                        (p->p_flag & STRC) == 0 ||
                    124:                        (p->p_tptr && curp != p->p_tptr) ||
                    125:                        (!p->p_tptr && curp != p->p_pptr)))
                    126: 
                    127:                return ESRCH;
                    128: #endif
                    129: 
                    130: 
                    131: #ifdef PT_ATTACH
                    132:        switch (uap->req) {
                    133:        case PT_ATTACH:
                    134:                if (curp->p_ucred->cr_uid != 0 && (
                    135:                        curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
                    136:                        curp->p_ucred->cr_uid != p->p_cred->p_svuid))
                    137:                        return EACCES;
                    138: 
                    139:                p->p_tptr = curp;
                    140:                p->p_flag |= STRC;
                    141:                psignal(p, SIGTRAP);
                    142:                return 0;
                    143: 
                    144:        case PT_DETACH:
                    145:                if ((unsigned)uap->data >= NSIG)
                    146:                        return EINVAL;
                    147:                p->p_flag &= ~(STRC|SSTRC|SFTRC);
                    148:                p->p_tptr = NULL;
                    149:                psignal(p->p_pptr, SIGCHLD);
                    150:                wakeup((caddr_t)p->p_pptr);
                    151:                s = splhigh();
                    152:                if (p->p_stat == SSTOP) {
                    153:                        p->p_xstat = uap->data;
                    154:                        setrun(p);
                    155:                } else if (uap->data) {
                    156:                        psignal(p, uap->data);
                    157:                }
                    158:                splx(s);
                    159:                return 0;
                    160: 
                    161: #ifdef PT_INHERIT
                    162:        case PT_INHERIT:
                    163:                if ((p->p_flag & STRC) == 0)
                    164:                        return ESRCH;
                    165:                p->p_flag |= SFTRC;
                    166:                return 0;
                    167: #endif
                    168: 
                    169:        default:
                    170:                break;
                    171:        }
                    172: #endif
                    173: 
                    174:        /* Other ptrace calls require target process to be in stopped state */
                    175:        if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) {
                    176:                return ESRCH;
                    177:        }
                    178: 
                    179:        /* Acquire the ipc structure */
                    180:        while (ipc.flag & IPC_BUSY) {
                    181:                ipc.flag |= IPC_WANT;
                    182:                error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
                    183:                if (error)
                    184:                        goto out;
                    185:        }
                    186: 
                    187:        /* Got it, fill it */
                    188:        ipc.flag = IPC_BUSY;
                    189:        ipc.error = 0;
                    190:        ipc.req = uap->req;
                    191:        ipc.addr = uap->addr;
                    192:        ipc.data = uap->data;
                    193: 
                    194: #ifdef PT_GETREGS
                    195:        switch (uap->req) {
                    196:        case PT_SETREGS:
                    197:                error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs));
                    198:                if (error)
                    199:                        goto out;
                    200:                break;
                    201: 
                    202: #ifdef notyet  /* requires change in number of args to ptrace syscall */
                    203:        case PT_BWRITE_I:
                    204:        case PT_BWRITE_D:
                    205:                ipc.buflen = uap->data;
                    206:                ipc.buf = kmem_alloc_wait(kernelmap, uap->data);
                    207:                error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen);
                    208:                if (error) {
                    209:                        kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen);
                    210:                        goto out;
                    211:                }
                    212: #endif
                    213:        default:
                    214:                break;
                    215:        }
                    216: #endif
                    217: 
                    218:        setrun(p);
                    219:        while ((ipc.flag & IPC_DONE) == 0) {
                    220:                error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
                    221:                if (error)
                    222:                        goto out;
                    223:        }
                    224: 
                    225:        *retval = ipc.data;
                    226:        if (error = ipc.error)
                    227:                goto out;
                    228: 
                    229: #ifdef PT_GETREGS
                    230:        switch (uap->req) {
                    231:        case PT_GETREGS:
                    232:                error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs));
                    233:                break;
                    234: 
                    235:        case PT_BREAD_I:
                    236:        case PT_BREAD_D:
                    237:                /* Not yet */
                    238:        default:
                    239:                break;
                    240:        }
                    241: #endif
                    242: 
                    243: out:
                    244:        /* Release ipc structure */
                    245:        ipc.flag &= ~IPC_BUSY;
                    246:        if (ipc.flag & IPC_WANT) {
                    247:                ipc.flag &= ~IPC_WANT;
                    248:                wakeup((caddr_t)&ipc);
                    249:        }
                    250:        return error;
1.1       root      251: }
                    252: 
1.1.1.5 ! root      253: int
1.1       root      254: procxmt(p)
                    255:        register struct proc *p;
                    256: {
1.1.1.5 ! root      257:        int rv = 0;
1.1       root      258: 
1.1.1.3   root      259:        /* Are we still being traced? */
                    260:        if ((p->p_flag & STRC) == 0)
                    261:                return 1;
                    262: 
                    263:        p->p_addr->u_kproc.kp_proc = *p;
                    264:        fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
                    265: 
                    266:        switch (ipc.req) {
                    267:        case PT_READ_I:
                    268:        case PT_READ_D:
1.1.1.5 ! root      269:                if (!useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_READ)) {
1.1.1.4   root      270:                        ipc.error = EFAULT;
                    271:                        break;
                    272:                }
1.1.1.3   root      273:                ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
                    274:                break;
                    275: 
                    276:        case PT_READ_U:
                    277:                if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
                    278:                        ipc.error = EFAULT;
                    279:                        break;
                    280:                }
                    281:                ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr);
                    282:                break;
                    283: 
                    284:        case PT_WRITE_I:
1.1.1.4   root      285:        case PT_WRITE_D: {                              /* 04 Sep 92*/
                    286:                vm_prot_t prot;         /* current protection of region */
                    287:                int cow;                /* ensure copy-on-write happens */
                    288: 
1.1.1.5 ! root      289:                if (cow = (useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_WRITE)
        !           290:                                == 0)) {
1.1.1.4   root      291:                        vm_offset_t     addr = (vm_offset_t)ipc.addr;
                    292:                        vm_size_t       size;
                    293:                        vm_prot_t       max_prot;
                    294:                        vm_inherit_t    inh;
                    295:                        boolean_t       shared;
                    296:                        vm_object_t     object;
                    297:                        vm_offset_t     objoff;
                    298: 
                    299:                        /*
                    300:                         * XXX - the useracc check is stronger than the vm
                    301:                         * checks because the user page tables are in the map.
                    302:                         */
1.1.1.5 ! root      303:                        if (!useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_READ) ||
1.1.1.4   root      304:                            vm_region(&p->p_vmspace->vm_map, &addr, &size,
                    305:                                        &prot, &max_prot, &inh, &shared,
                    306:                                        &object, &objoff) != KERN_SUCCESS ||
                    307:                            vm_protect(&p->p_vmspace->vm_map, ipc.addr,
                    308:                                        sizeof(ipc.data), FALSE,
                    309:                                        prot|VM_PROT_WRITE) != KERN_SUCCESS ||
                    310:                            vm_fault(&p->p_vmspace->vm_map,trunc_page(ipc.addr),
                    311:                                        VM_PROT_WRITE, FALSE) != KERN_SUCCESS) {
                    312: 
                    313:                                ipc.error = EFAULT;
                    314:                                break;
                    315:                        }
                    316:                }
                    317:                ipc.error = copyout((char *)&ipc.data,
                    318:                                        (char *)ipc.addr, sizeof(ipc.data));
                    319:                if (cow)
                    320:                        if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
                    321:                                        sizeof(ipc.data), FALSE,
                    322:                                        prot) != KERN_SUCCESS)
                    323:                                printf("ptrace: oops\n");
1.1.1.3   root      324:                break;
1.1.1.4   root      325:        }
1.1.1.3   root      326: 
                    327:        case PT_WRITE_U:
                    328:                if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
                    329:                        ipc.error = EFAULT;
                    330:                        break;
                    331:                }
                    332:                *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data;
                    333:                break;
                    334: 
                    335:        case PT_CONTINUE:
                    336:                if (ipc.addr != (int *)1) {
                    337: #ifdef i386
                    338:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
                    339: #endif
                    340:                }
                    341:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
                    342:                if ((unsigned)ipc.data >= NSIG) {
                    343:                        ipc.error = EINVAL;
                    344:                } else {
                    345:                        p->p_xstat = ipc.data;
                    346:                        rv = 1;
                    347:                }
                    348:                break;
                    349: 
                    350:        case PT_KILL:
                    351:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
                    352:                rv = 2;
                    353:                break;
                    354: 
                    355:        case PT_STEP:
                    356: #ifdef i386
                    357:                if (ipc.addr != (int *)1) {
                    358:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
                    359:                }
                    360:                p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T;
                    361: #endif
                    362:                p->p_flag &= ~SSTRC;    /* Only set by PT_SYSCALL */
                    363:                p->p_xstat = 0;
                    364:                rv = 1;
                    365:                break;
                    366: 
                    367: #ifdef PT_SYSCALL
                    368:        case PT_SYSCALL:
                    369:                if (ipc.addr != (int *)1) {
                    370: #ifdef i386
                    371:                        p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
                    372: #endif
                    373:                }
                    374:                p->p_flag |= SSTRC;
                    375:                p->p_xstat = 0;
                    376:                rv = 1;
                    377:                break;
                    378: #endif
                    379: #ifdef PT_GETREGS
                    380:        case PT_GETREGS:
                    381: #ifdef i386
                    382:                xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
                    383: #endif
                    384: 
                    385:                for (i = 0; i < NIPCREG; i++)
                    386:                        ipc.regs[i] = p->p_regs[xreg[i]];
                    387:                break;
                    388: 
                    389:        case PT_SETREGS:
                    390: #ifdef i386
                    391:                xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
                    392: #endif
                    393: 
                    394:                for (i = 0; i < NIPCREG; i++)
                    395:                        p->p_regs[xreg[i]] = ipc.regs[i];
                    396:                break;
                    397: #endif
                    398: 
                    399: #ifdef PT_DUMP
                    400:        case PT_DUMP:
                    401:                /* Should be able to specify core file name */
                    402:                ipc.error = coredump(p);
                    403:                break;
                    404: #endif
                    405: 
                    406:        default:
                    407:                ipc.error = EINVAL;
                    408:        }
                    409:        ipc.flag |= IPC_DONE;
                    410:        wakeup((caddr_t)&ipc);
                    411: 
                    412:        if (rv == 2)
1.1.1.5 ! root      413:                kexit(p, 0);    /*???*/
1.1.1.3   root      414: 
                    415:        return rv;
1.1       root      416: }
                    417: 
                    418: /*
                    419:  * Enable process profiling system call.
                    420:  */
1.1.1.5 ! root      421: 
        !           422: struct profil_args {
        !           423:        short   *bufbase;       /* base of data buffer */
        !           424:        unsigned bufsize;       /* size of data buffer */
        !           425:        unsigned pcoffset;      /* pc offset (for subtraction) */
        !           426:        unsigned pcscale;       /* scaling factor for offset pc */
        !           427: };
        !           428: 
1.1       root      429: /* ARGSUSED */
1.1.1.5 ! root      430: int
1.1       root      431: profil(p, uap, retval)
                    432:        struct proc *p;
1.1.1.5 ! root      433:        register struct profil_args *uap;
1.1       root      434:        int *retval;
                    435: {
1.1.1.3   root      436:        /* from looking at man pages, and include files, looks like
                    437:         * this just sets up the fields of p->p_stats->p_prof...
                    438:         * and those fields come straight from the args.
                    439:         * only thing *we* have to do is check the args for validity...
                    440:         *
                    441:         * cgd
                    442:         */
1.1       root      443: 
1.1.1.3   root      444:        /* check to make sure that the buffer is OK.  addupc (in locore)
                    445:         * checks for faults, but would one be generated, say, writing to
                    446:         * kernel space?  probably not -- it just uses "movl"...
                    447:         *
                    448:         * so we've gotta check to make sure that the info set up for
                    449:         * addupc is set right... it's gotta be writable by the user...
1.1       root      450:         */
1.1.1.3   root      451: 
1.1.1.5 ! root      452:        if (useracc((caddr_t)uap->bufbase, uap->bufsize*sizeof(short), B_WRITE)
        !           453:                        == 0)
1.1.1.3   root      454:                return EFAULT;
                    455: 
                    456:        p->p_stats->p_prof.pr_base = uap->bufbase;
                    457:        p->p_stats->p_prof.pr_size = uap->bufsize;
                    458:        p->p_stats->p_prof.pr_off = uap->pcoffset;
                    459:        p->p_stats->p_prof.pr_scale = uap->pcscale;
                    460: 
                    461:        return 0;
1.1       root      462: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.