1*36359Smarc /* 2*36359Smarc * Copyright (c) 1989 The Regents of the University of California. 3*36359Smarc * All rights reserved. 4*36359Smarc * 5*36359Smarc * Redistribution and use in source and binary forms are permitted 6*36359Smarc * provided that the above copyright notice and this paragraph are 7*36359Smarc * duplicated in all such forms and that any documentation, 8*36359Smarc * advertising materials, and other materials related to such 9*36359Smarc * distribution and use acknowledge that the software was developed 10*36359Smarc * by the University of California, Berkeley. The name of the 11*36359Smarc * University may not be used to endorse or promote products derived 12*36359Smarc * from this software without specific prior written permission. 13*36359Smarc * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*36359Smarc * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36359Smarc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*36359Smarc * 17*36359Smarc * @(#)kern_ktrace.c 1.1 (Berkeley) 12/14/88 18*36359Smarc */ 19*36359Smarc 20*36359Smarc #ifdef KTRACE 21*36359Smarc 22*36359Smarc #include "param.h" 23*36359Smarc #include "systm.h" 24*36359Smarc #include "dir.h" 25*36359Smarc #include "user.h" 26*36359Smarc #include "assym.s" 27*36359Smarc #include "proc.h" 28*36359Smarc #include "seg.h" 29*36359Smarc #include "acct.h" 30*36359Smarc #include "fs.h" 31*36359Smarc #include "inode.h" 32*36359Smarc #include "syslog.h" 33*36359Smarc #include "kernel.h" 34*36359Smarc #include "ktrace.h" 35*36359Smarc #include "malloc.h" 36*36359Smarc 37*36359Smarc #include "../sys/syscalls.c" 38*36359Smarc 39*36359Smarc extern int nsysent; 40*36359Smarc extern char *syscallnames[]; 41*36359Smarc 42*36359Smarc struct ktr_header * 43*36359Smarc ktrgetheader(type) 44*36359Smarc { 45*36359Smarc register struct ktr_header *kth; 46*36359Smarc 47*36359Smarc MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 48*36359Smarc M_TEMP, M_WAITOK); 49*36359Smarc if (kth == NULL) 50*36359Smarc return (NULL); 51*36359Smarc kth->ktr_type = type; 52*36359Smarc kth->ktr_time = time; 53*36359Smarc kth->ktr_pid = u.u_procp->p_pid; 54*36359Smarc bcopy(u.u_comm, kth->ktr_comm, MAXCOMLEN); 55*36359Smarc 56*36359Smarc return (kth); 57*36359Smarc } 58*36359Smarc 59*36359Smarc ktrsyscall(ip, code, narg) 60*36359Smarc struct inode *ip; 61*36359Smarc { 62*36359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 63*36359Smarc struct ktr_syscall *ktp; 64*36359Smarc register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 65*36359Smarc int *argp, i; 66*36359Smarc 67*36359Smarc if (kth == NULL) { 68*36359Smarc printf("lost syscall trace - no header\n"); /* DEBUG */ 69*36359Smarc return; 70*36359Smarc } 71*36359Smarc MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 72*36359Smarc if (ktp == NULL) { 73*36359Smarc printf("lost syscall trace - no buffer\n"); /* DEBUG */ 74*36359Smarc FREE(kth, M_TEMP); 75*36359Smarc return; 76*36359Smarc } 77*36359Smarc ktp->ktr_code = code; 78*36359Smarc ktp->ktr_narg = narg; 79*36359Smarc argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 80*36359Smarc for (i = 0; i < narg; i++) 81*36359Smarc *argp++ = u.u_arg[i]; 82*36359Smarc kth->ktr_buf = (caddr_t)ktp; 83*36359Smarc kth->ktr_len = len; 84*36359Smarc ktrwrite(ip, kth); 85*36359Smarc FREE(ktp, M_TEMP); 86*36359Smarc FREE(kth, M_TEMP); 87*36359Smarc } 88*36359Smarc 89*36359Smarc ktrsysret(ip, code) 90*36359Smarc struct inode *ip; 91*36359Smarc { 92*36359Smarc struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 93*36359Smarc struct ktr_sysret *ktp; 94*36359Smarc 95*36359Smarc if (kth == NULL) { 96*36359Smarc printf("lost syscall ret - no header\n"); /* DEBUG */ 97*36359Smarc return; 98*36359Smarc } 99*36359Smarc MALLOC(ktp, struct ktr_sysret *, sizeof(struct ktr_sysret), 100*36359Smarc M_TEMP , M_WAITOK); 101*36359Smarc if (ktp == NULL) { 102*36359Smarc printf("lost syscall ret - no buffer\n"); /* DEBUG */ 103*36359Smarc FREE(kth, M_TEMP); 104*36359Smarc return; 105*36359Smarc } 106*36359Smarc ktp->ktr_code = code; 107*36359Smarc ktp->ktr_eosys = u.u_eosys; 108*36359Smarc ktp->ktr_error = u.u_error; 109*36359Smarc ktp->ktr_retval = u.u_r.r_val1; /* what about val2 ? */ 110*36359Smarc 111*36359Smarc kth->ktr_buf = (caddr_t)ktp; 112*36359Smarc kth->ktr_len = sizeof(struct ktr_sysret); 113*36359Smarc 114*36359Smarc ktrwrite(ip, kth); 115*36359Smarc FREE(ktp, M_TEMP); 116*36359Smarc FREE(kth, M_TEMP); 117*36359Smarc } 118*36359Smarc 119*36359Smarc ktrnamei(ip, path) 120*36359Smarc struct inode *ip; 121*36359Smarc char *path; 122*36359Smarc { 123*36359Smarc struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 124*36359Smarc 125*36359Smarc if (kth == NULL) { 126*36359Smarc printf("lost namei - no header\n"); /* DEBUG */ 127*36359Smarc return; 128*36359Smarc } 129*36359Smarc kth->ktr_len = strlen(path); 130*36359Smarc kth->ktr_buf = path; 131*36359Smarc 132*36359Smarc ktrwrite(ip, kth); 133*36359Smarc FREE(kth, M_TEMP); 134*36359Smarc } 135*36359Smarc 136*36359Smarc /* 137*36359Smarc * ktrace system call 138*36359Smarc */ 139*36359Smarc ktrace() 140*36359Smarc { 141*36359Smarc register struct inode *ip = NULL; 142*36359Smarc register struct a { 143*36359Smarc char *fname; 144*36359Smarc int ops; 145*36359Smarc int facs; 146*36359Smarc pid_t pid; 147*36359Smarc } *uap = (struct a *)u.u_ap; 148*36359Smarc register struct nameidata *ndp = &u.u_nd; 149*36359Smarc register struct proc *p; 150*36359Smarc struct pgrp *pg; 151*36359Smarc register int ops = uap->ops&0x3; 152*36359Smarc register int facs = uap->facs; 153*36359Smarc 154*36359Smarc /* 155*36359Smarc * Until security implications are thought through, 156*36359Smarc * limit tracing to root. 157*36359Smarc */ 158*36359Smarc if (!suser()) { 159*36359Smarc u.u_error = EACCES; 160*36359Smarc return; 161*36359Smarc } 162*36359Smarc if (ops != KTROP_CLEAR) { 163*36359Smarc /* 164*36359Smarc * an operation which requires a file argument. 165*36359Smarc */ 166*36359Smarc ndp->ni_nameiop = LOOKUP | FOLLOW; 167*36359Smarc ndp->ni_segflg = UIO_USERSPACE; 168*36359Smarc ndp->ni_dirp = uap->fname; 169*36359Smarc ip = namei(ndp); 170*36359Smarc if (ip == NULL) 171*36359Smarc return; 172*36359Smarc if ((ip->i_mode&IFMT) != IFREG) { 173*36359Smarc u.u_error = EACCES; 174*36359Smarc iput(ip); 175*36359Smarc return; 176*36359Smarc } 177*36359Smarc if (ip->i_fs->fs_ronly) { 178*36359Smarc u.u_error = EROFS; 179*36359Smarc iput(ip); 180*36359Smarc return; 181*36359Smarc } 182*36359Smarc iunlock(ip); 183*36359Smarc } 184*36359Smarc /* 185*36359Smarc * Clear all uses of the tracefile 186*36359Smarc */ 187*36359Smarc if (ops == KTROP_CLEARFILE) { 188*36359Smarc for (p = allproc; p != NULL; p = p->p_nxt) { 189*36359Smarc if (p->p_tracep == ip) { 190*36359Smarc p->p_flag &= ~SKTR; 191*36359Smarc p->p_tracep = NULL; 192*36359Smarc p->p_traceflag = 0; 193*36359Smarc irele(ip); 194*36359Smarc } 195*36359Smarc } 196*36359Smarc goto done; 197*36359Smarc } 198*36359Smarc 199*36359Smarc /* 200*36359Smarc * need something to (un)trace 201*36359Smarc */ 202*36359Smarc if (!facs) { 203*36359Smarc u.u_error = EINVAL; 204*36359Smarc goto done; 205*36359Smarc } 206*36359Smarc 207*36359Smarc if (uap->pid < 0) { 208*36359Smarc pg = pgfind(-uap->pid); 209*36359Smarc if (pg == NULL) { 210*36359Smarc u.u_error = ESRCH; 211*36359Smarc goto done; 212*36359Smarc } 213*36359Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 214*36359Smarc if (uap->ops&KTROP_INHERITFLAG) 215*36359Smarc ktrsetchildren(p, ops, facs, ip); 216*36359Smarc else 217*36359Smarc ktrops(p, ops, facs, ip); 218*36359Smarc 219*36359Smarc } else { 220*36359Smarc p = pfind(uap->pid); 221*36359Smarc if (p == NULL) { 222*36359Smarc u.u_error = ESRCH; 223*36359Smarc goto done; 224*36359Smarc } 225*36359Smarc if (uap->ops&KTROP_INHERITFLAG) 226*36359Smarc ktrsetchildren(p, ops, facs, ip); 227*36359Smarc else 228*36359Smarc ktrops(p, ops, facs, ip); 229*36359Smarc } 230*36359Smarc done: 231*36359Smarc if (ip != NULL) 232*36359Smarc irele(ip); 233*36359Smarc } 234*36359Smarc 235*36359Smarc ktrops(p, ops, facs, ip) 236*36359Smarc struct proc *p; 237*36359Smarc struct inode *ip; 238*36359Smarc { 239*36359Smarc if (ops == KTROP_SET) { 240*36359Smarc if (p->p_tracep != ip) { 241*36359Smarc /* 242*36359Smarc * if trace file already in use, relinquish 243*36359Smarc */ 244*36359Smarc if (p->p_tracep != NULL) 245*36359Smarc irele(p->p_tracep); 246*36359Smarc igrab(ip); 247*36359Smarc p->p_tracep = ip; 248*36359Smarc iunlock(ip); 249*36359Smarc } 250*36359Smarc p->p_traceflag |= facs; 251*36359Smarc } else { 252*36359Smarc /* KTROP_CLEAR */ 253*36359Smarc if ((p->p_traceflag &= ~facs) == 0) { 254*36359Smarc if (p->p_tracep != NULL) { 255*36359Smarc irele(p->p_tracep); 256*36359Smarc p->p_tracep = NULL; 257*36359Smarc } 258*36359Smarc p->p_flag &= SKTR; 259*36359Smarc } 260*36359Smarc } 261*36359Smarc } 262*36359Smarc 263*36359Smarc ktrsetchildren(top, ops, facs, ip) 264*36359Smarc struct proc *top; 265*36359Smarc struct inode *ip; 266*36359Smarc { 267*36359Smarc register struct proc *p; 268*36359Smarc register int ndx; 269*36359Smarc 270*36359Smarc p = top; 271*36359Smarc for (;;) { 272*36359Smarc if (ops == KTROP_SET) 273*36359Smarc p->p_flag |= SKTR; 274*36359Smarc ktrops(p, ops, facs, ip); 275*36359Smarc /* 276*36359Smarc * If this process has children, descend to them next, 277*36359Smarc * otherwise do any siblings, and if done with this level, 278*36359Smarc * follow back up the tree (but not past top). 279*36359Smarc */ 280*36359Smarc if (p->p_cptr) 281*36359Smarc p = p->p_cptr; 282*36359Smarc else if (p == top) 283*36359Smarc return; 284*36359Smarc else if (p->p_osptr) 285*36359Smarc p = p->p_osptr; 286*36359Smarc else for (;;) { 287*36359Smarc p = p->p_pptr; 288*36359Smarc if (p == top) 289*36359Smarc return; 290*36359Smarc if (p->p_osptr) { 291*36359Smarc p = p->p_osptr; 292*36359Smarc break; 293*36359Smarc } 294*36359Smarc } 295*36359Smarc } 296*36359Smarc } 297*36359Smarc 298*36359Smarc ktrwrite(ip, kth) 299*36359Smarc register struct inode *ip; 300*36359Smarc struct ktr_header *kth; 301*36359Smarc { 302*36359Smarc int save = u.u_error; 303*36359Smarc int osize; 304*36359Smarc 305*36359Smarc ilock(ip); 306*36359Smarc osize = ip->i_size; 307*36359Smarc u.u_error = 0; 308*36359Smarc u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)kth, 309*36359Smarc sizeof(struct ktr_header), ip->i_size, 1, (int *)0); 310*36359Smarc if (u.u_error) { 311*36359Smarc itrunc(ip, (u_long)osize); 312*36359Smarc goto end; 313*36359Smarc } 314*36359Smarc if (kth->ktr_len > 0) { 315*36359Smarc u.u_error = rdwri(UIO_WRITE, ip, kth->ktr_buf, 316*36359Smarc kth->ktr_len, ip->i_size, 1, (int *)0); 317*36359Smarc if (u.u_error) 318*36359Smarc itrunc(ip, (u_long)osize); 319*36359Smarc } 320*36359Smarc end: 321*36359Smarc u.u_error = save; 322*36359Smarc iunlock(ip); 323*36359Smarc } 324*36359Smarc 325*36359Smarc #endif 326