1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_ktrace.c 7.10 (Berkeley) 02/15/91 8 */ 9 10 #ifdef KTRACE 11 12 #include "param.h" 13 #include "user.h" 14 #include "proc.h" 15 #include "file.h" 16 #include "vnode.h" 17 #include "ktrace.h" 18 #include "malloc.h" 19 #include "syslog.h" 20 21 #include "syscalls.c" 22 23 extern int nsysent; 24 extern char *syscallnames[]; 25 26 struct ktr_header * 27 ktrgetheader(type) 28 { 29 register struct ktr_header *kth; 30 31 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 32 M_TEMP, M_WAITOK); 33 kth->ktr_type = type; 34 microtime(&kth->ktr_time); 35 kth->ktr_pid = u.u_procp->p_pid; 36 bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN); 37 return (kth); 38 } 39 40 ktrsyscall(vp, code, narg, args) 41 struct vnode *vp; 42 int code, narg, args[]; 43 { 44 struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); 45 struct ktr_syscall *ktp; 46 register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 47 int *argp, i; 48 49 MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); 50 ktp->ktr_code = code; 51 ktp->ktr_narg = narg; 52 argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 53 for (i = 0; i < narg; i++) 54 *argp++ = args[i]; 55 kth->ktr_buf = (caddr_t)ktp; 56 kth->ktr_len = len; 57 ktrwrite(vp, kth); 58 FREE(ktp, M_TEMP); 59 FREE(kth, M_TEMP); 60 } 61 62 ktrsysret(vp, code, error, retval) 63 struct vnode *vp; 64 int code, error, retval; 65 { 66 struct ktr_header *kth = ktrgetheader(KTR_SYSRET); 67 struct ktr_sysret ktp; 68 69 ktp.ktr_code = code; 70 ktp.ktr_error = error; 71 ktp.ktr_retval = retval; /* what about val2 ? */ 72 73 kth->ktr_buf = (caddr_t)&ktp; 74 kth->ktr_len = sizeof(struct ktr_sysret); 75 76 ktrwrite(vp, kth); 77 FREE(kth, M_TEMP); 78 } 79 80 ktrnamei(vp, path) 81 struct vnode *vp; 82 char *path; 83 { 84 struct ktr_header *kth = ktrgetheader(KTR_NAMEI); 85 86 kth->ktr_len = strlen(path); 87 kth->ktr_buf = path; 88 89 ktrwrite(vp, kth); 90 FREE(kth, M_TEMP); 91 } 92 93 ktrgenio(vp, fd, rw, iov, len, error) 94 struct vnode *vp; 95 int fd; 96 enum uio_rw rw; 97 register struct iovec *iov; 98 { 99 struct ktr_header *kth = ktrgetheader(KTR_GENIO); 100 register struct ktr_genio *ktp; 101 register caddr_t cp; 102 register int resid = len, cnt; 103 104 if (error) 105 return; 106 MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 107 M_TEMP, M_WAITOK); 108 ktp->ktr_fd = fd; 109 ktp->ktr_rw = rw; 110 cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 111 while (resid > 0) { 112 if ((cnt = iov->iov_len) > resid) 113 cnt = resid; 114 if (copyin(iov->iov_base, cp, (unsigned)cnt)) 115 goto done; 116 cp += cnt; 117 resid -= cnt; 118 iov++; 119 } 120 kth->ktr_buf = (caddr_t)ktp; 121 kth->ktr_len = sizeof (struct ktr_genio) + len; 122 123 ktrwrite(vp, kth); 124 done: 125 FREE(kth, M_TEMP); 126 FREE(ktp, M_TEMP); 127 } 128 129 ktrpsig(vp, sig, action, mask, code) 130 struct vnode *vp; 131 sig_t action; 132 { 133 struct ktr_header *kth = ktrgetheader(KTR_PSIG); 134 struct ktr_psig kp; 135 136 kp.signo = (char)sig; 137 kp.action = action; 138 kp.mask = mask; 139 kp.code = code; 140 kth->ktr_buf = (caddr_t)&kp; 141 kth->ktr_len = sizeof (struct ktr_psig); 142 143 ktrwrite(vp, kth); 144 FREE(kth, M_TEMP); 145 } 146 147 /* Interface and common routines */ 148 149 /* 150 * ktrace system call 151 */ 152 /* ARGSUSED */ 153 ktrace(curp, uap, retval) 154 struct proc *curp; 155 register struct args { 156 char *fname; 157 int ops; 158 int facs; 159 int pid; 160 } *uap; 161 int *retval; 162 { 163 register struct vnode *vp = NULL; 164 register struct nameidata *ndp = &u.u_nd; 165 register struct proc *p; 166 struct pgrp *pg; 167 int facs = uap->facs & ~KTRFAC_ROOT; 168 int ops = KTROP(uap->ops); 169 int descend = uap->ops & KTRFLAG_DESCEND; 170 int ret = 0; 171 int error = 0; 172 173 if (ops != KTROP_CLEAR) { 174 /* 175 * an operation which requires a file argument. 176 */ 177 ndp->ni_segflg = UIO_USERSPACE; 178 ndp->ni_dirp = uap->fname; 179 if (error = vn_open(ndp, FREAD|FWRITE, 0)) 180 return (error); 181 vp = ndp->ni_vp; 182 if (vp->v_type != VREG) { 183 vrele(vp); 184 return (EACCES); 185 } 186 } 187 /* 188 * Clear all uses of the tracefile 189 */ 190 if (ops == KTROP_CLEARFILE) { 191 for (p = allproc; p != NULL; p = p->p_nxt) { 192 if (p->p_tracep == vp) { 193 if (ktrcanset(curp, p)) { 194 p->p_tracep = NULL; 195 p->p_traceflag = 0; 196 vrele(vp); 197 } else 198 error = EPERM; 199 } 200 } 201 goto done; 202 } 203 /* 204 * need something to (un)trace (XXX - why is this here?) 205 */ 206 if (!facs) { 207 error = EINVAL; 208 goto done; 209 } 210 /* 211 * do it 212 */ 213 if (uap->pid < 0) { 214 /* 215 * by process group 216 */ 217 pg = pgfind(-uap->pid); 218 if (pg == NULL) { 219 error = ESRCH; 220 goto done; 221 } 222 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) 223 if (descend) 224 ret |= ktrsetchildren(curp, p, ops, facs, vp); 225 else 226 ret |= ktrops(curp, p, ops, facs, vp); 227 228 } else { 229 /* 230 * by pid 231 */ 232 p = pfind(uap->pid); 233 if (p == NULL) { 234 error = ESRCH; 235 goto done; 236 } 237 if (descend) 238 ret |= ktrsetchildren(curp, p, ops, facs, vp); 239 else 240 ret |= ktrops(curp, p, ops, facs, vp); 241 } 242 if (!ret) 243 error = EPERM; 244 done: 245 if (vp != NULL) 246 vrele(vp); 247 return (error); 248 } 249 250 ktrops(curp, p, ops, facs, vp) 251 struct proc *curp, *p; 252 struct vnode *vp; 253 { 254 255 if (!ktrcanset(curp, p)) 256 return (0); 257 if (ops == KTROP_SET) { 258 if (p->p_tracep != vp) { 259 /* 260 * if trace file already in use, relinquish 261 */ 262 if (p->p_tracep != NULL) 263 vrele(p->p_tracep); 264 VREF(vp); 265 p->p_tracep = vp; 266 } 267 p->p_traceflag |= facs; 268 if (curp->p_uid == 0) 269 p->p_traceflag |= KTRFAC_ROOT; 270 } else { 271 /* KTROP_CLEAR */ 272 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 273 /* no more tracing */ 274 p->p_traceflag = 0; 275 if (p->p_tracep != NULL) { 276 vrele(p->p_tracep); 277 p->p_tracep = NULL; 278 } 279 } 280 } 281 282 return (1); 283 } 284 285 ktrsetchildren(curp, top, ops, facs, vp) 286 struct proc *curp, *top; 287 struct vnode *vp; 288 { 289 register struct proc *p; 290 register int ret = 0; 291 292 p = top; 293 for (;;) { 294 ret |= ktrops(curp, p, ops, facs, vp); 295 /* 296 * If this process has children, descend to them next, 297 * otherwise do any siblings, and if done with this level, 298 * follow back up the tree (but not past top). 299 */ 300 if (p->p_cptr) 301 p = p->p_cptr; 302 else if (p == top) 303 return (ret); 304 else if (p->p_osptr) 305 p = p->p_osptr; 306 else for (;;) { 307 p = p->p_pptr; 308 if (p == top) 309 return (ret); 310 if (p->p_osptr) { 311 p = p->p_osptr; 312 break; 313 } 314 } 315 } 316 /*NOTREACHED*/ 317 } 318 319 ktrwrite(vp, kth) 320 struct vnode *vp; 321 register struct ktr_header *kth; 322 { 323 struct uio auio; 324 struct iovec aiov[2]; 325 struct proc *p; 326 int error; 327 328 if (vp == NULL) 329 return; 330 auio.uio_iov = &aiov[0]; 331 auio.uio_offset = 0; 332 auio.uio_segflg = UIO_SYSSPACE; 333 auio.uio_rw = UIO_WRITE; 334 aiov[0].iov_base = (caddr_t)kth; 335 aiov[0].iov_len = sizeof(struct ktr_header); 336 auio.uio_resid = sizeof(struct ktr_header); 337 auio.uio_iovcnt = 1; 338 if (kth->ktr_len > 0) { 339 auio.uio_iovcnt++; 340 aiov[1].iov_base = kth->ktr_buf; 341 aiov[1].iov_len = kth->ktr_len; 342 auio.uio_resid += kth->ktr_len; 343 } 344 VOP_LOCK(vp); 345 error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred); 346 VOP_UNLOCK(vp); 347 if (!error) 348 return; 349 /* 350 * If error encountered, give up tracing on this vnode. 351 */ 352 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); 353 for (p = allproc; p != NULL; p = p->p_nxt) { 354 if (p->p_tracep == vp) { 355 p->p_tracep = NULL; 356 p->p_traceflag = 0; 357 vrele(vp); 358 } 359 } 360 } 361 362 /* 363 * Return true if caller has permission to set the ktracing state 364 * of target. Essentially, the target can't possess any 365 * more permissions than the caller. KTRFAC_ROOT signifies that 366 * root previously set the tracing status on the target process, and 367 * so, only root may further change it. 368 * 369 * TODO: check groups (have to wait till group list is moved 370 * out of u. use caller effective gid. 371 */ 372 ktrcanset(caller, target) 373 register struct proc *caller, *target; 374 { 375 if ((caller->p_uid == target->p_ruid && 376 target->p_ruid == target->p_svuid && 377 caller->p_rgid == target->p_rgid && /* XXX */ 378 target->p_rgid == target->p_svgid && 379 (target->p_traceflag & KTRFAC_ROOT) == 0) || 380 caller->p_uid == 0) 381 return (1); 382 383 return (0); 384 } 385 386 #endif 387