kern_ktrace.c revision 1.50 1 /* $NetBSD: kern_ktrace.c,v 1.50 2000/12/19 22:08:36 scw Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)kern_ktrace.c 8.5 (Berkeley) 5/14/95
36 */
37
38 #include "opt_ktrace.h"
39
40 #ifdef KTRACE
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/proc.h>
45 #include <sys/file.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 #include <sys/filedesc.h>
52 #include <sys/ioctl.h>
53
54 #include <sys/mount.h>
55 #include <sys/syscallargs.h>
56
57 int ktrace_common(struct proc *, int, int, int, struct file *);
58 void ktrinitheader(struct ktr_header *, struct proc *, int);
59 int ktrops(struct proc *, struct proc *, int, int, struct file *);
60 int ktrsetchildren(struct proc *, struct proc *, int, int,
61 struct file *);
62 int ktrwrite(struct proc *, struct ktr_header *);
63 int ktrcanset(struct proc *, struct proc *);
64 int ktrsamefile(struct file *, struct file *);
65
66 /*
67 * "deep" compare of two files for the purposes of clearing a trace.
68 * Returns true if they're the same open file, or if they point at the
69 * same underlying vnode/socket.
70 */
71
72 int
73 ktrsamefile(struct file *f1, struct file *f2)
74 {
75 return ((f1 == f2) ||
76 ((f1 != NULL) && (f2 != NULL) &&
77 (f1->f_type == f2->f_type) &&
78 (f1->f_data == f2->f_data)));
79 }
80
81 void
82 ktrderef(struct proc *p)
83 {
84 struct file *fp = p->p_tracep;
85 p->p_traceflag = 0;
86 if (fp == NULL)
87 return;
88 FILE_USE(fp);
89 closef(fp, NULL);
90
91 p->p_tracep = NULL;
92 }
93
94 void
95 ktradref(struct proc *p)
96 {
97 struct file *fp = p->p_tracep;
98
99 fp->f_count++;
100 }
101
102 void
103 ktrinitheader(struct ktr_header *kth, struct proc *p, int type)
104 {
105
106 memset(kth, 0, sizeof(*kth));
107 kth->ktr_type = type;
108 microtime(&kth->ktr_time);
109 kth->ktr_pid = p->p_pid;
110 memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
111 }
112
113 void
114 ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[])
115 {
116 struct ktr_header kth;
117 struct ktr_syscall *ktp;
118 register_t *argp;
119 size_t len = sizeof(struct ktr_syscall) + argsize;
120 int i;
121
122 p->p_traceflag |= KTRFAC_ACTIVE;
123 ktrinitheader(&kth, p, KTR_SYSCALL);
124 ktp = malloc(len, M_TEMP, M_WAITOK);
125 ktp->ktr_code = code;
126 ktp->ktr_argsize = argsize;
127 argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
128 for (i = 0; i < (argsize / sizeof(*argp)); i++)
129 *argp++ = args[i];
130 kth.ktr_buf = (caddr_t)ktp;
131 kth.ktr_len = len;
132 (void) ktrwrite(p, &kth);
133 free(ktp, M_TEMP);
134 p->p_traceflag &= ~KTRFAC_ACTIVE;
135 }
136
137 void
138 ktrsysret(struct proc *p, register_t code, int error, register_t retval)
139 {
140 struct ktr_header kth;
141 struct ktr_sysret ktp;
142
143 p->p_traceflag |= KTRFAC_ACTIVE;
144 ktrinitheader(&kth, p, KTR_SYSRET);
145 ktp.ktr_code = code;
146 ktp.ktr_eosys = 0; /* XXX unused */
147 ktp.ktr_error = error;
148 ktp.ktr_retval = retval; /* what about val2 ? */
149
150 kth.ktr_buf = (caddr_t)&ktp;
151 kth.ktr_len = sizeof(struct ktr_sysret);
152
153 (void) ktrwrite(p, &kth);
154 p->p_traceflag &= ~KTRFAC_ACTIVE;
155 }
156
157 void
158 ktrnamei(struct proc *p, char *path)
159 {
160 struct ktr_header kth;
161
162 p->p_traceflag |= KTRFAC_ACTIVE;
163 ktrinitheader(&kth, p, KTR_NAMEI);
164 kth.ktr_len = strlen(path);
165 kth.ktr_buf = path;
166
167 (void) ktrwrite(p, &kth);
168 p->p_traceflag &= ~KTRFAC_ACTIVE;
169 }
170
171 void
172 ktremul(struct proc *p)
173 {
174 struct ktr_header kth;
175 const char *emul = p->p_emul->e_name;
176
177 p->p_traceflag |= KTRFAC_ACTIVE;
178 ktrinitheader(&kth, p, KTR_EMUL);
179 kth.ktr_len = strlen(emul);
180 kth.ktr_buf = (caddr_t)emul;
181
182 (void) ktrwrite(p, &kth);
183 p->p_traceflag &= ~KTRFAC_ACTIVE;
184 }
185
186 void
187 ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov,
188 int len, int error)
189 {
190 struct ktr_header kth;
191 struct ktr_genio *ktp;
192 caddr_t cp;
193 int resid = len, cnt;
194 int buflen;
195
196 if (error)
197 return;
198
199 p->p_traceflag |= KTRFAC_ACTIVE;
200
201 buflen = min(PAGE_SIZE, len + sizeof(struct ktr_genio));
202
203 ktrinitheader(&kth, p, KTR_GENIO);
204 ktp = malloc(buflen, M_TEMP, M_WAITOK);
205 ktp->ktr_fd = fd;
206 ktp->ktr_rw = rw;
207
208 kth.ktr_buf = (caddr_t)ktp;
209
210 cp = (caddr_t)((char *)ktp + sizeof(struct ktr_genio));
211 buflen -= sizeof(struct ktr_genio);
212
213 while (resid > 0) {
214 KDASSERT(p->p_cpu != NULL);
215 KDASSERT(p->p_cpu == curcpu());
216 if (p->p_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
217 preempt(NULL);
218
219 cnt = min(iov->iov_len, buflen);
220 if (cnt > resid)
221 cnt = resid;
222 if (copyin(iov->iov_base, cp, cnt))
223 break;
224
225 kth.ktr_len = cnt + sizeof(struct ktr_genio);
226
227 if (__predict_false(ktrwrite(p, &kth) != 0))
228 break;
229
230 iov->iov_base = (caddr_t)iov->iov_base + cnt;
231 iov->iov_len -= cnt;
232
233 if (iov->iov_len == 0)
234 iov++;
235
236 resid -= cnt;
237 }
238
239 free(ktp, M_TEMP);
240 p->p_traceflag &= ~KTRFAC_ACTIVE;
241 }
242
243 void
244 ktrpsig(struct proc *p, int sig, sig_t action, sigset_t *mask, int code)
245 {
246 struct ktr_header kth;
247 struct ktr_psig kp;
248
249 p->p_traceflag |= KTRFAC_ACTIVE;
250 ktrinitheader(&kth, p, KTR_PSIG);
251 kp.signo = (char)sig;
252 kp.action = action;
253 kp.mask = *mask;
254 kp.code = code;
255 kth.ktr_buf = (caddr_t)&kp;
256 kth.ktr_len = sizeof(struct ktr_psig);
257
258 (void) ktrwrite(p, &kth);
259 p->p_traceflag &= ~KTRFAC_ACTIVE;
260 }
261
262 void
263 ktrcsw(struct proc *p, int out, int user)
264 {
265 struct ktr_header kth;
266 struct ktr_csw kc;
267
268 p->p_traceflag |= KTRFAC_ACTIVE;
269 ktrinitheader(&kth, p, KTR_CSW);
270 kc.out = out;
271 kc.user = user;
272 kth.ktr_buf = (caddr_t)&kc;
273 kth.ktr_len = sizeof(struct ktr_csw);
274
275 (void) ktrwrite(p, &kth);
276 p->p_traceflag &= ~KTRFAC_ACTIVE;
277 }
278
279 /* Interface and common routines */
280
281 int
282 ktrace_common(struct proc *curp, int ops, int facs, int pid, struct file *fp)
283 {
284 int ret = 0;
285 int error = 0;
286 int one = 1;
287 int descend;
288 struct proc *p;
289 struct pgrp *pg;
290
291 curp->p_traceflag |= KTRFAC_ACTIVE;
292 descend = ops & KTRFLAG_DESCEND;
293 facs = facs & ~((unsigned) KTRFAC_ROOT);
294
295 /*
296 * Clear all uses of the tracefile
297 */
298 if (KTROP(ops) == KTROP_CLEARFILE) {
299 proclist_lock_read();
300 for (p = LIST_FIRST(&allproc); p != NULL;
301 p = LIST_NEXT(p, p_list)) {
302 if (ktrsamefile(p->p_tracep, fp)) {
303 if (ktrcanset(curp, p))
304 ktrderef(p);
305 else
306 error = EPERM;
307 }
308 }
309 proclist_unlock_read();
310 goto done;
311 }
312
313 /*
314 * Mark fp non-blocking, to avoid problems from possible deadlocks.
315 */
316
317 if (fp != NULL) {
318 fp->f_flag |= FNONBLOCK;
319 (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&one, curp);
320 }
321
322 /*
323 * need something to (un)trace (XXX - why is this here?)
324 */
325 if (!facs) {
326 error = EINVAL;
327 goto done;
328 }
329 /*
330 * do it
331 */
332 if (pid < 0) {
333 /*
334 * by process group
335 */
336 pg = pgfind(-pid);
337 if (pg == NULL) {
338 error = ESRCH;
339 goto done;
340 }
341 for (p = LIST_FIRST(&pg->pg_members); p != NULL;
342 p = LIST_NEXT(p, p_pglist)) {
343 if (descend)
344 ret |= ktrsetchildren(curp, p, ops, facs, fp);
345 else
346 ret |= ktrops(curp, p, ops, facs, fp);
347 }
348
349 } else {
350 /*
351 * by pid
352 */
353 p = pfind(pid);
354 if (p == NULL) {
355 error = ESRCH;
356 goto done;
357 }
358 if (descend)
359 ret |= ktrsetchildren(curp, p, ops, facs, fp);
360 else
361 ret |= ktrops(curp, p, ops, facs, fp);
362 }
363 if (!ret)
364 error = EPERM;
365 done:
366 curp->p_traceflag &= ~KTRFAC_ACTIVE;
367 return (error);
368 }
369
370 /*
371 * ktrace system call
372 */
373 /* ARGSUSED */
374 int
375 sys_fktrace(struct proc *curp, void *v, register_t *retval)
376 {
377 struct sys_fktrace_args /* {
378 syscallarg(int) fd;
379 syscallarg(int) ops;
380 syscallarg(int) facs;
381 syscallarg(int) pid;
382 } */ *uap = v;
383 struct file *fp = NULL;
384 struct filedesc *fdp = curp->p_fd;
385
386 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
387 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
388 (fp->f_flag & FWRITE) == 0)
389 return (EBADF);
390
391 return ktrace_common(curp, SCARG(uap, ops),
392 SCARG(uap, facs), SCARG(uap, pid), fp);
393 }
394
395 /*
396 * ktrace system call
397 */
398 /* ARGSUSED */
399 int
400 sys_ktrace(struct proc *curp, void *v, register_t *retval)
401 {
402 struct sys_ktrace_args /* {
403 syscallarg(const char *) fname;
404 syscallarg(int) ops;
405 syscallarg(int) facs;
406 syscallarg(int) pid;
407 } */ *uap = v;
408 struct vnode *vp = NULL;
409 struct file *fp = NULL;
410 int fd;
411 int ops = SCARG(uap, ops);
412 int error = 0;
413 struct nameidata nd;
414
415 ops = KTROP(ops) | (ops & KTRFLAG_DESCEND);
416
417 curp->p_traceflag |= KTRFAC_ACTIVE;
418 if (ops != KTROP_CLEAR) {
419 /*
420 * an operation which requires a file argument.
421 */
422 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
423 curp);
424 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
425 curp->p_traceflag &= ~KTRFAC_ACTIVE;
426 return (error);
427 }
428 vp = nd.ni_vp;
429 VOP_UNLOCK(vp, 0);
430 if (vp->v_type != VREG) {
431 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
432 curp->p_traceflag &= ~KTRFAC_ACTIVE;
433 return (EACCES);
434 }
435 /*
436 * XXX This uses up a file descriptor slot in the
437 * tracing process for the duration of this syscall.
438 * This is not expected to be a problem. If
439 * falloc(NULL, ...) DTRT we could skip that part, but
440 * that would require changing its interface to allow
441 * the caller to pass in a ucred..
442 *
443 * This will FILE_USE the fp it returns, if any.
444 * Keep it in use until we return.
445 */
446 if ((error = falloc(curp, &fp, &fd)) != 0)
447 goto done;
448
449 fp->f_flag = FWRITE|FAPPEND;
450 fp->f_type = DTYPE_VNODE;
451 fp->f_ops = &vnops;
452 fp->f_data = (caddr_t)vp;
453 vp = NULL;
454 }
455 error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs),
456 SCARG(uap, pid), fp);
457 done:
458 if (vp != NULL)
459 (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
460 if (fp != NULL) {
461 FILE_UNUSE(fp, curp); /* release file */
462 fdrelease(curp, fd); /* release fd table slot */
463 }
464 return (error);
465 }
466
467 int
468 ktrops(struct proc *curp, struct proc *p, int ops, int facs, struct file *fp)
469 {
470
471 if (!ktrcanset(curp, p))
472 return (0);
473 if (KTROP(ops) == KTROP_SET) {
474 if (p->p_tracep != fp) {
475 /*
476 * if trace file already in use, relinquish
477 */
478 ktrderef(p);
479 p->p_tracep = fp;
480 ktradref(p);
481 }
482 p->p_traceflag |= facs;
483 if (curp->p_ucred->cr_uid == 0)
484 p->p_traceflag |= KTRFAC_ROOT;
485 } else {
486 /* KTROP_CLEAR */
487 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
488 /* no more tracing */
489 ktrderef(p);
490 }
491 }
492
493 /*
494 * Emit an emulation record, every time there is a ktrace
495 * change/attach request.
496 */
497 if (KTRPOINT(p, KTR_EMUL))
498 ktremul(p);
499 #ifdef __HAVE_SYSCALL_INTERN
500 (*p->p_emul->e_syscall_intern)(p);
501 #endif
502
503 return (1);
504 }
505
506 int
507 ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs,
508 struct file *fp)
509 {
510 struct proc *p;
511 int ret = 0;
512
513 p = top;
514 for (;;) {
515 ret |= ktrops(curp, p, ops, facs, fp);
516 /*
517 * If this process has children, descend to them next,
518 * otherwise do any siblings, and if done with this level,
519 * follow back up the tree (but not past top).
520 */
521 if (LIST_FIRST(&p->p_children) != NULL)
522 p = LIST_FIRST(&p->p_children);
523 else for (;;) {
524 if (p == top)
525 return (ret);
526 if (LIST_NEXT(p, p_sibling) != NULL) {
527 p = LIST_NEXT(p, p_sibling);
528 break;
529 }
530 p = p->p_pptr;
531 }
532 }
533 /*NOTREACHED*/
534 }
535
536 int
537 ktrwrite(struct proc *p, struct ktr_header *kth)
538 {
539 struct uio auio;
540 struct iovec aiov[2];
541 int error, tries;
542 struct file *fp = p->p_tracep;
543
544 if (fp == NULL)
545 return 0;
546
547 auio.uio_iov = &aiov[0];
548 auio.uio_offset = 0;
549 auio.uio_segflg = UIO_SYSSPACE;
550 auio.uio_rw = UIO_WRITE;
551 aiov[0].iov_base = (caddr_t)kth;
552 aiov[0].iov_len = sizeof(struct ktr_header);
553 auio.uio_resid = sizeof(struct ktr_header);
554 auio.uio_iovcnt = 1;
555 auio.uio_procp = (struct proc *)0;
556 if (kth->ktr_len > 0) {
557 auio.uio_iovcnt++;
558 aiov[1].iov_base = kth->ktr_buf;
559 aiov[1].iov_len = kth->ktr_len;
560 auio.uio_resid += kth->ktr_len;
561 }
562
563 FILE_USE(fp);
564
565 tries = 0;
566 do {
567 error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
568 fp->f_cred, FOF_UPDATE_OFFSET);
569 tries++;
570 if (error == EWOULDBLOCK)
571 yield();
572 } while ((error == EWOULDBLOCK) && (tries < 3));
573 FILE_UNUSE(fp, NULL);
574
575 if (__predict_true(error == 0))
576 return (0);
577 /*
578 * If error encountered, give up tracing on this vnode. Don't report
579 * EPIPE as this can easily happen with fktrace()/ktruss.
580 */
581 if (error != EPIPE)
582 log(LOG_NOTICE,
583 "ktrace write failed, errno %d, tracing stopped\n",
584 error);
585 proclist_lock_read();
586 for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
587 if (ktrsamefile(p->p_tracep, fp))
588 ktrderef(p);
589 }
590 proclist_unlock_read();
591
592 return (error);
593 }
594
595 /*
596 * Return true if caller has permission to set the ktracing state
597 * of target. Essentially, the target can't possess any
598 * more permissions than the caller. KTRFAC_ROOT signifies that
599 * root previously set the tracing status on the target process, and
600 * so, only root may further change it.
601 *
602 * TODO: check groups. use caller effective gid.
603 */
604 int
605 ktrcanset(struct proc *callp, struct proc *targetp)
606 {
607 struct pcred *caller = callp->p_cred;
608 struct pcred *target = targetp->p_cred;
609
610 if ((caller->pc_ucred->cr_uid == target->p_ruid &&
611 target->p_ruid == target->p_svuid &&
612 caller->p_rgid == target->p_rgid && /* XXX */
613 target->p_rgid == target->p_svgid &&
614 (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
615 caller->pc_ucred->cr_uid == 0)
616 return (1);
617
618 return (0);
619 }
620 #endif /* KTRACE */
621