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

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

unix.superglobalmegacorp.com

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