1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 34 * $Id: kern_ktrace.c,v 1.24 1998/11/10 09:16:29 peter Exp $ 35 */ 36 37 #include "opt_ktrace.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/sysproto.h> 42 #include <sys/kernel.h> 43 #include <sys/proc.h> 44 #include <sys/fcntl.h> 45 #include <sys/lock.h> 46 #include <sys/namei.h> 47 #include <sys/vnode.h> 48 #include <sys/ktrace.h> 49 #include <sys/malloc.h> 50 #include <sys/syslog.h> 51 52 static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 53 54 #ifdef KTRACE 55 static struct ktr_header *ktrgetheader __P((int type)); 56 static void ktrwrite __P((struct vnode *, struct ktr_header *)); 57 static int ktrcanset __P((struct proc *,struct proc *)); 58 static int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 59 static int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 60 61 62 static struct ktr_header * 63 ktrgetheader(type) 64 int type; 65 { 66 register struct ktr_header *kth; 67 struct proc *p = curproc; /* XXX */ 68 69 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 70 M_KTRACE, M_WAITOK); 71 kth->ktr_type = type; 72 microtime(&kth->ktr_time); 73 kth->ktr_pid = p->p_pid; 74 bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); 75 return (kth); 76 } 77 78 void 79 ktrsyscall(vp, code, narg, args) 80 struct vnode *vp; 81 int code, narg, args[]; 82 { 83 struct ktr_header *kth; 84 struct ktr_syscall *ktp; 85 register int len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); 86 struct proc *p = curproc; /* XXX */ 87 int *argp, i; 88 89 p->p_traceflag |= KTRFAC_ACTIVE; 90 kth = ktrgetheader(KTR_SYSCALL); 91 MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 92 ktp->ktr_code = code; 93 ktp->ktr_narg = narg; 94 argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); 95 for (i = 0; i < narg; i++) 96 *argp++ = args[i]; 97 kth->ktr_buf = (caddr_t)ktp; 98 kth->ktr_len = len; 99 ktrwrite(vp, kth); 100 FREE(ktp, M_KTRACE); 101 FREE(kth, M_KTRACE); 102 p->p_traceflag &= ~KTRFAC_ACTIVE; 103 } 104 105 void 106 ktrsysret(vp, code, error, retval) 107 struct vnode *vp; 108 int code, error, retval; 109 { 110 struct ktr_header *kth; 111 struct ktr_sysret ktp; 112 struct proc *p = curproc; /* XXX */ 113 114 p->p_traceflag |= KTRFAC_ACTIVE; 115 kth = ktrgetheader(KTR_SYSRET); 116 ktp.ktr_code = code; 117 ktp.ktr_error = error; 118 ktp.ktr_retval = retval; /* what about val2 ? */ 119 120 kth->ktr_buf = (caddr_t)&ktp; 121 kth->ktr_len = sizeof(struct ktr_sysret); 122 123 ktrwrite(vp, kth); 124 FREE(kth, M_KTRACE); 125 p->p_traceflag &= ~KTRFAC_ACTIVE; 126 } 127 128 void 129 ktrnamei(vp, path) 130 struct vnode *vp; 131 char *path; 132 { 133 struct ktr_header *kth; 134 struct proc *p = curproc; /* XXX */ 135 136 p->p_traceflag |= KTRFAC_ACTIVE; 137 kth = ktrgetheader(KTR_NAMEI); 138 kth->ktr_len = strlen(path); 139 kth->ktr_buf = path; 140 141 ktrwrite(vp, kth); 142 FREE(kth, M_KTRACE); 143 p->p_traceflag &= ~KTRFAC_ACTIVE; 144 } 145 146 void 147 ktrgenio(vp, fd, rw, iov, len, error) 148 struct vnode *vp; 149 int fd; 150 enum uio_rw rw; 151 register struct iovec *iov; 152 int len, error; 153 { 154 struct ktr_header *kth; 155 register struct ktr_genio *ktp; 156 register caddr_t cp; 157 register int resid = len, cnt; 158 struct proc *p = curproc; /* XXX */ 159 160 if (error) 161 return; 162 p->p_traceflag |= KTRFAC_ACTIVE; 163 kth = ktrgetheader(KTR_GENIO); 164 MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, 165 M_KTRACE, M_WAITOK); 166 ktp->ktr_fd = fd; 167 ktp->ktr_rw = rw; 168 cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); 169 while (resid > 0) { 170 if ((cnt = iov->iov_len) > resid) 171 cnt = resid; 172 if (copyin(iov->iov_base, cp, (unsigned)cnt)) 173 goto done; 174 cp += cnt; 175 resid -= cnt; 176 iov++; 177 } 178 kth->ktr_buf = (caddr_t)ktp; 179 kth->ktr_len = sizeof (struct ktr_genio) + len; 180 181 ktrwrite(vp, kth); 182 done: 183 FREE(kth, M_KTRACE); 184 FREE(ktp, M_KTRACE); 185 p->p_traceflag &= ~KTRFAC_ACTIVE; 186 } 187 188 void 189 ktrpsig(vp, sig, action, mask, code) 190 struct vnode *vp; 191 int sig; 192 sig_t action; 193 int mask, code; 194 { 195 struct ktr_header *kth; 196 struct ktr_psig kp; 197 struct proc *p = curproc; /* XXX */ 198 199 p->p_traceflag |= KTRFAC_ACTIVE; 200 kth = ktrgetheader(KTR_PSIG); 201 kp.signo = (char)sig; 202 kp.action = action; 203 kp.mask = mask; 204 kp.code = code; 205 kth->ktr_buf = (caddr_t)&kp; 206 kth->ktr_len = sizeof (struct ktr_psig); 207 208 ktrwrite(vp, kth); 209 FREE(kth, M_KTRACE); 210 p->p_traceflag &= ~KTRFAC_ACTIVE; 211 } 212 213 void 214 ktrcsw(vp, out, user) 215 struct vnode *vp; 216 int out, user; 217 { 218 struct ktr_header *kth; 219 struct ktr_csw kc; 220 struct proc *p = curproc; /* XXX */ 221 222 p->p_traceflag |= KTRFAC_ACTIVE; 223 kth = ktrgetheader(KTR_CSW); 224 kc.out = out; 225 kc.user = user; 226 kth->ktr_buf = (caddr_t)&kc; 227 kth->ktr_len = sizeof (struct ktr_csw); 228 229 ktrwrite(vp, kth); 230 FREE(kth, M_KTRACE); 231 p->p_traceflag &= ~KTRFAC_ACTIVE; 232 } 233 #endif 234 235 /* Interface and common routines */ 236 237 /* 238 * ktrace system call 239 */ 240 #ifndef _SYS_SYSPROTO_H_ 241 struct ktrace_args { 242 char *fname; 243 int ops; 244 int facs; 245 int pid; 246 }; 247 #endif 248 /* ARGSUSED */ 249 int 250 ktrace(curp, uap) 251 struct proc *curp; 252 register struct ktrace_args *uap; 253 { 254 #ifdef KTRACE 255 register struct vnode *vp = NULL; 256 register struct proc *p; 257 struct pgrp *pg; 258 int facs = uap->facs & ~KTRFAC_ROOT; 259 int ops = KTROP(uap->ops); 260 int descend = uap->ops & KTRFLAG_DESCEND; 261 int ret = 0; 262 int error = 0; 263 struct nameidata nd; 264 265 curp->p_traceflag |= KTRFAC_ACTIVE; 266 if (ops != KTROP_CLEAR) { 267 /* 268 * an operation which requires a file argument. 269 */ 270 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, curp); 271 error = vn_open(&nd, FREAD|FWRITE, 0); 272 if (error) { 273 curp->p_traceflag &= ~KTRFAC_ACTIVE; 274 return (error); 275 } 276 vp = nd.ni_vp; 277 VOP_UNLOCK(vp, 0, curp); 278 if (vp->v_type != VREG) { 279 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 280 curp->p_traceflag &= ~KTRFAC_ACTIVE; 281 return (EACCES); 282 } 283 } 284 /* 285 * Clear all uses of the tracefile 286 */ 287 if (ops == KTROP_CLEARFILE) { 288 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 289 if (p->p_tracep == vp) { 290 if (ktrcanset(curp, p)) { 291 p->p_tracep = NULL; 292 p->p_traceflag = 0; 293 (void) vn_close(vp, FREAD|FWRITE, 294 p->p_ucred, p); 295 } else 296 error = EPERM; 297 } 298 } 299 goto done; 300 } 301 /* 302 * need something to (un)trace (XXX - why is this here?) 303 */ 304 if (!facs) { 305 error = EINVAL; 306 goto done; 307 } 308 /* 309 * do it 310 */ 311 if (uap->pid < 0) { 312 /* 313 * by process group 314 */ 315 pg = pgfind(-uap->pid); 316 if (pg == NULL) { 317 error = ESRCH; 318 goto done; 319 } 320 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) 321 if (descend) 322 ret |= ktrsetchildren(curp, p, ops, facs, vp); 323 else 324 ret |= ktrops(curp, p, ops, facs, vp); 325 326 } else { 327 /* 328 * by pid 329 */ 330 p = pfind(uap->pid); 331 if (p == NULL) { 332 error = ESRCH; 333 goto done; 334 } 335 if (descend) 336 ret |= ktrsetchildren(curp, p, ops, facs, vp); 337 else 338 ret |= ktrops(curp, p, ops, facs, vp); 339 } 340 if (!ret) 341 error = EPERM; 342 done: 343 if (vp != NULL) 344 (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 345 curp->p_traceflag &= ~KTRFAC_ACTIVE; 346 return (error); 347 #else 348 return ENOSYS; 349 #endif 350 } 351 352 /* 353 * utrace system call 354 */ 355 /* ARGSUSED */ 356 int 357 utrace(curp, uap) 358 struct proc *curp; 359 register struct utrace_args *uap; 360 { 361 #ifdef KTRACE 362 struct ktr_header *kth; 363 struct proc *p = curproc; /* XXX */ 364 register caddr_t cp; 365 366 if (!KTRPOINT(p, KTR_USER)) 367 return (0); 368 p->p_traceflag |= KTRFAC_ACTIVE; 369 kth = ktrgetheader(KTR_USER); 370 MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 371 if (!copyin(uap->addr, cp, uap->len)) { 372 kth->ktr_buf = cp; 373 kth->ktr_len = uap->len; 374 ktrwrite(p->p_tracep, kth); 375 } 376 FREE(kth, M_KTRACE); 377 FREE(cp, M_KTRACE); 378 p->p_traceflag &= ~KTRFAC_ACTIVE; 379 380 return (0); 381 #else 382 return (ENOSYS); 383 #endif 384 } 385 386 #ifdef KTRACE 387 static int 388 ktrops(curp, p, ops, facs, vp) 389 struct proc *p, *curp; 390 int ops, facs; 391 struct vnode *vp; 392 { 393 394 if (!ktrcanset(curp, p)) 395 return (0); 396 if (ops == KTROP_SET) { 397 if (p->p_tracep != vp) { 398 /* 399 * if trace file already in use, relinquish 400 */ 401 if (p->p_tracep != NULL) 402 vrele(p->p_tracep); 403 VREF(vp); 404 p->p_tracep = vp; 405 } 406 p->p_traceflag |= facs; 407 if (curp->p_ucred->cr_uid == 0) 408 p->p_traceflag |= KTRFAC_ROOT; 409 } else { 410 /* KTROP_CLEAR */ 411 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 412 /* no more tracing */ 413 p->p_traceflag = 0; 414 if (p->p_tracep != NULL) { 415 vrele(p->p_tracep); 416 p->p_tracep = NULL; 417 } 418 } 419 } 420 421 return (1); 422 } 423 424 static int 425 ktrsetchildren(curp, top, ops, facs, vp) 426 struct proc *curp, *top; 427 int ops, facs; 428 struct vnode *vp; 429 { 430 register struct proc *p; 431 register int ret = 0; 432 433 p = top; 434 for (;;) { 435 ret |= ktrops(curp, p, ops, facs, vp); 436 /* 437 * If this process has children, descend to them next, 438 * otherwise do any siblings, and if done with this level, 439 * follow back up the tree (but not past top). 440 */ 441 if (p->p_children.lh_first) 442 p = p->p_children.lh_first; 443 else for (;;) { 444 if (p == top) 445 return (ret); 446 if (p->p_sibling.le_next) { 447 p = p->p_sibling.le_next; 448 break; 449 } 450 p = p->p_pptr; 451 } 452 } 453 /*NOTREACHED*/ 454 } 455 456 static void 457 ktrwrite(vp, kth) 458 struct vnode *vp; 459 register struct ktr_header *kth; 460 { 461 struct uio auio; 462 struct iovec aiov[2]; 463 register struct proc *p = curproc; /* XXX */ 464 int error; 465 466 if (vp == NULL) 467 return; 468 auio.uio_iov = &aiov[0]; 469 auio.uio_offset = 0; 470 auio.uio_segflg = UIO_SYSSPACE; 471 auio.uio_rw = UIO_WRITE; 472 aiov[0].iov_base = (caddr_t)kth; 473 aiov[0].iov_len = sizeof(struct ktr_header); 474 auio.uio_resid = sizeof(struct ktr_header); 475 auio.uio_iovcnt = 1; 476 auio.uio_procp = curproc; 477 if (kth->ktr_len > 0) { 478 auio.uio_iovcnt++; 479 aiov[1].iov_base = kth->ktr_buf; 480 aiov[1].iov_len = kth->ktr_len; 481 auio.uio_resid += kth->ktr_len; 482 } 483 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 484 error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); 485 VOP_UNLOCK(vp, 0, p); 486 if (!error) 487 return; 488 /* 489 * If error encountered, give up tracing on this vnode. 490 */ 491 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 492 error); 493 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 494 if (p->p_tracep == vp) { 495 p->p_tracep = NULL; 496 p->p_traceflag = 0; 497 vrele(vp); 498 } 499 } 500 } 501 502 /* 503 * Return true if caller has permission to set the ktracing state 504 * of target. Essentially, the target can't possess any 505 * more permissions than the caller. KTRFAC_ROOT signifies that 506 * root previously set the tracing status on the target process, and 507 * so, only root may further change it. 508 * 509 * TODO: check groups. use caller effective gid. 510 */ 511 static int 512 ktrcanset(callp, targetp) 513 struct proc *callp, *targetp; 514 { 515 register struct pcred *caller = callp->p_cred; 516 register struct pcred *target = targetp->p_cred; 517 518 if ((caller->pc_ucred->cr_uid == target->p_ruid && 519 target->p_ruid == target->p_svuid && 520 caller->p_rgid == target->p_rgid && /* XXX */ 521 target->p_rgid == target->p_svgid && 522 (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 523 caller->pc_ucred->cr_uid == 0) 524 return (1); 525 526 return (0); 527 } 528 529 #endif /* KTRACE */ 530