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