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: releng/5.1/sys/kern/kern_ktrace.c 114026 2003-04-25 19:59:35Z jhb $
35 */
36
37 #include "opt_ktrace.h"
38 #include "opt_mac.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/fcntl.h>
43 #include <sys/jail.h>
44 #include <sys/kernel.h>
45 #include <sys/kthread.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <sys/mac.h>
49 #include <sys/malloc.h>
50 #include <sys/namei.h>
51 #include <sys/proc.h>
52 #include <sys/unistd.h>
53 #include <sys/vnode.h>
54 #include <sys/ktrace.h>
55 #include <sys/sema.h>
56 #include <sys/sx.h>
57 #include <sys/sysctl.h>
58 #include <sys/syslog.h>
59 #include <sys/sysproto.h>
60
61 static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE");
62
63 #ifdef KTRACE
64
65 #ifndef KTRACE_REQUEST_POOL
66 #define KTRACE_REQUEST_POOL 100
67 #endif
68
69 struct ktr_request {
70 struct ktr_header ktr_header;
71 struct ucred *ktr_cred;
72 struct vnode *ktr_vp;
73 union {
74 struct ktr_syscall ktr_syscall;
75 struct ktr_sysret ktr_sysret;
76 struct ktr_genio ktr_genio;
77 struct ktr_psig ktr_psig;
78 struct ktr_csw ktr_csw;
79 } ktr_data;
80 STAILQ_ENTRY(ktr_request) ktr_list;
81 };
82
83 static int data_lengths[] = {
84 0, /* none */
85 offsetof(struct ktr_syscall, ktr_args), /* KTR_SYSCALL */
86 sizeof(struct ktr_sysret), /* KTR_SYSRET */
87 0, /* KTR_NAMEI */
88 sizeof(struct ktr_genio), /* KTR_GENIO */
89 sizeof(struct ktr_psig), /* KTR_PSIG */
90 sizeof(struct ktr_csw), /* KTR_CSW */
91 0 /* KTR_USER */
92 };
93
94 static STAILQ_HEAD(, ktr_request) ktr_todo;
95 static STAILQ_HEAD(, ktr_request) ktr_free;
96
97 SYSCTL_NODE(_kern, OID_AUTO, ktrace, CTLFLAG_RD, 0, "KTRACE options");
98
99 static uint ktr_requestpool = KTRACE_REQUEST_POOL;
100 TUNABLE_INT("kern.ktrace.request_pool", &ktr_requestpool);
101
102 static uint ktr_geniosize = PAGE_SIZE;
103 TUNABLE_INT("kern.ktrace.genio_size", &ktr_geniosize);
104 SYSCTL_UINT(_kern_ktrace, OID_AUTO, genio_size, CTLFLAG_RW, &ktr_geniosize,
105 0, "Maximum size of genio event payload");
106
107 static int print_message = 1;
108 struct mtx ktrace_mtx;
109 static struct sema ktrace_sema;
110
111 static void ktrace_init(void *dummy);
112 static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
113 static uint ktrace_resize_pool(uint newsize);
114 static struct ktr_request *ktr_getrequest(int type);
115 static void ktr_submitrequest(struct ktr_request *req);
116 static void ktr_freerequest(struct ktr_request *req);
117 static void ktr_loop(void *dummy);
118 static void ktr_writerequest(struct ktr_request *req);
119 static int ktrcanset(struct thread *,struct proc *);
120 static int ktrsetchildren(struct thread *,struct proc *,int,int,struct vnode *);
121 static int ktrops(struct thread *,struct proc *,int,int,struct vnode *);
122
123 static void
124 ktrace_init(void *dummy)
125 {
126 struct ktr_request *req;
127 int i;
128
129 mtx_init(&ktrace_mtx, "ktrace", NULL, MTX_DEF | MTX_QUIET);
130 sema_init(&ktrace_sema, 0, "ktrace");
131 STAILQ_INIT(&ktr_todo);
132 STAILQ_INIT(&ktr_free);
133 for (i = 0; i < ktr_requestpool; i++) {
134 req = malloc(sizeof(struct ktr_request), M_KTRACE, M_WAITOK);
135 STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
136 }
137 kthread_create(ktr_loop, NULL, NULL, RFHIGHPID, 0, "ktrace");
138 }
139 SYSINIT(ktrace_init, SI_SUB_KTRACE, SI_ORDER_ANY, ktrace_init, NULL);
140
141 static int
142 sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS)
143 {
144 struct thread *td;
145 uint newsize, oldsize, wantsize;
146 int error;
147
148 /* Handle easy read-only case first to avoid warnings from GCC. */
149 if (!req->newptr) {
150 mtx_lock(&ktrace_mtx);
151 oldsize = ktr_requestpool;
152 mtx_unlock(&ktrace_mtx);
153 return (SYSCTL_OUT(req, &oldsize, sizeof(uint)));
154 }
155
156 error = SYSCTL_IN(req, &wantsize, sizeof(uint));
157 if (error)
158 return (error);
159 td = curthread;
160 td->td_inktrace = 1;
161 mtx_lock(&ktrace_mtx);
162 oldsize = ktr_requestpool;
163 newsize = ktrace_resize_pool(wantsize);
164 mtx_unlock(&ktrace_mtx);
165 td->td_inktrace = 0;
166 error = SYSCTL_OUT(req, &oldsize, sizeof(uint));
167 if (error)
168 return (error);
169 if (newsize != wantsize)
170 return (ENOSPC);
171 return (0);
172 }
173 SYSCTL_PROC(_kern_ktrace, OID_AUTO, request_pool, CTLTYPE_UINT|CTLFLAG_RW,
174 &ktr_requestpool, 0, sysctl_kern_ktrace_request_pool, "IU", "");
175
176 static uint
177 ktrace_resize_pool(uint newsize)
178 {
179 struct ktr_request *req;
180
181 mtx_assert(&ktrace_mtx, MA_OWNED);
182 print_message = 1;
183 if (newsize == ktr_requestpool)
184 return (newsize);
185 if (newsize < ktr_requestpool)
186 /* Shrink pool down to newsize if possible. */
187 while (ktr_requestpool > newsize) {
188 req = STAILQ_FIRST(&ktr_free);
189 if (req == NULL)
190 return (ktr_requestpool);
191 STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
192 ktr_requestpool--;
193 mtx_unlock(&ktrace_mtx);
194 free(req, M_KTRACE);
195 mtx_lock(&ktrace_mtx);
196 }
197 else
198 /* Grow pool up to newsize. */
199 while (ktr_requestpool < newsize) {
200 mtx_unlock(&ktrace_mtx);
201 req = malloc(sizeof(struct ktr_request), M_KTRACE,
202 M_WAITOK);
203 mtx_lock(&ktrace_mtx);
204 STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
205 ktr_requestpool++;
206 }
207 return (ktr_requestpool);
208 }
209
210 static struct ktr_request *
211 ktr_getrequest(int type)
212 {
213 struct ktr_request *req;
214 struct thread *td = curthread;
215 struct proc *p = td->td_proc;
216 int pm;
217
218 td->td_inktrace = 1;
219 mtx_lock(&ktrace_mtx);
220 if (!KTRCHECK(td, type)) {
221 mtx_unlock(&ktrace_mtx);
222 td->td_inktrace = 0;
223 return (NULL);
224 }
225 req = STAILQ_FIRST(&ktr_free);
226 if (req != NULL) {
227 STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
228 req->ktr_header.ktr_type = type;
229 if (p->p_traceflag & KTRFAC_DROP) {
230 req->ktr_header.ktr_type |= KTR_DROP;
231 p->p_traceflag &= ~KTRFAC_DROP;
232 }
233 KASSERT(p->p_tracevp != NULL, ("ktrace: no trace vnode"));
234 KASSERT(p->p_tracecred != NULL, ("ktrace: no trace cred"));
235 req->ktr_vp = p->p_tracevp;
236 VREF(p->p_tracevp);
237 req->ktr_cred = crhold(p->p_tracecred);
238 mtx_unlock(&ktrace_mtx);
239 microtime(&req->ktr_header.ktr_time);
240 req->ktr_header.ktr_pid = p->p_pid;
241 bcopy(p->p_comm, req->ktr_header.ktr_comm, MAXCOMLEN + 1);
242 req->ktr_header.ktr_buffer = NULL;
243 req->ktr_header.ktr_len = 0;
244 } else {
245 p->p_traceflag |= KTRFAC_DROP;
246 pm = print_message;
247 print_message = 0;
248 mtx_unlock(&ktrace_mtx);
249 if (pm)
250 printf("Out of ktrace request objects.\n");
251 td->td_inktrace = 0;
252 }
253 return (req);
254 }
255
256 static void
257 ktr_submitrequest(struct ktr_request *req)
258 {
259
260 mtx_lock(&ktrace_mtx);
261 STAILQ_INSERT_TAIL(&ktr_todo, req, ktr_list);
262 sema_post(&ktrace_sema);
263 mtx_unlock(&ktrace_mtx);
264 curthread->td_inktrace = 0;
265 }
266
267 static void
268 ktr_freerequest(struct ktr_request *req)
269 {
270
271 crfree(req->ktr_cred);
272 if (req->ktr_vp != NULL) {
273 mtx_lock(&Giant);
274 vrele(req->ktr_vp);
275 mtx_unlock(&Giant);
276 }
277 if (req->ktr_header.ktr_buffer != NULL)
278 free(req->ktr_header.ktr_buffer, M_KTRACE);
279 mtx_lock(&ktrace_mtx);
280 STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
281 mtx_unlock(&ktrace_mtx);
282 }
283
284 static void
285 ktr_loop(void *dummy)
286 {
287 struct ktr_request *req;
288 struct thread *td;
289 struct ucred *cred;
290
291 /* Only cache these values once. */
292 td = curthread;
293 cred = td->td_ucred;
294 for (;;) {
295 sema_wait(&ktrace_sema);
296 mtx_lock(&ktrace_mtx);
297 req = STAILQ_FIRST(&ktr_todo);
298 STAILQ_REMOVE_HEAD(&ktr_todo, ktr_list);
299 KASSERT(req != NULL, ("got a NULL request"));
300 mtx_unlock(&ktrace_mtx);
301 /*
302 * It is not enough just to pass the cached cred
303 * to the VOP's in ktr_writerequest(). Some VFS
304 * operations use curthread->td_ucred, so we need
305 * to modify our thread's credentials as well.
306 * Evil.
307 */
308 td->td_ucred = req->ktr_cred;
309 ktr_writerequest(req);
310 td->td_ucred = cred;
311 ktr_freerequest(req);
312 }
313 }
314
315 /*
316 * MPSAFE
317 */
318 void
319 ktrsyscall(code, narg, args)
320 int code, narg;
321 register_t args[];
322 {
323 struct ktr_request *req;
324 struct ktr_syscall *ktp;
325 size_t buflen;
326 char *buf = NULL;
327
328 buflen = sizeof(register_t) * narg;
329 if (buflen > 0) {
330 buf = malloc(buflen, M_KTRACE, M_WAITOK);
331 bcopy(args, buf, buflen);
332 }
333 req = ktr_getrequest(KTR_SYSCALL);
334 if (req == NULL) {
335 if (buf != NULL)
336 free(buf, M_KTRACE);
337 return;
338 }
339 ktp = &req->ktr_data.ktr_syscall;
340 ktp->ktr_code = code;
341 ktp->ktr_narg = narg;
342 if (buflen > 0) {
343 req->ktr_header.ktr_len = buflen;
344 req->ktr_header.ktr_buffer = buf;
345 }
346 ktr_submitrequest(req);
347 }
348
349 /*
350 * MPSAFE
351 */
352 void
353 ktrsysret(code, error, retval)
354 int code, error;
355 register_t retval;
356 {
357 struct ktr_request *req;
358 struct ktr_sysret *ktp;
359
360 req = ktr_getrequest(KTR_SYSRET);
361 if (req == NULL)
362 return;
363 ktp = &req->ktr_data.ktr_sysret;
364 ktp->ktr_code = code;
365 ktp->ktr_error = error;
366 ktp->ktr_retval = retval; /* what about val2 ? */
367 ktr_submitrequest(req);
368 }
369
370 void
371 ktrnamei(path)
372 char *path;
373 {
374 struct ktr_request *req;
375 int namelen;
376 char *buf = NULL;
377
378 namelen = strlen(path);
379 if (namelen > 0) {
380 buf = malloc(namelen, M_KTRACE, M_WAITOK);
381 bcopy(path, buf, namelen);
382 }
383 req = ktr_getrequest(KTR_NAMEI);
384 if (req == NULL) {
385 if (buf != NULL)
386 free(buf, M_KTRACE);
387 return;
388 }
389 if (namelen > 0) {
390 req->ktr_header.ktr_len = namelen;
391 req->ktr_header.ktr_buffer = buf;
392 }
393 ktr_submitrequest(req);
394 }
395
396 /*
397 * Since the uio may not stay valid, we can not hand off this request to
398 * the thread and need to process it synchronously. However, we wish to
399 * keep the relative order of records in a trace file correct, so we
400 * do put this request on the queue (if it isn't empty) and then block.
401 * The ktrace thread waks us back up when it is time for this event to
402 * be posted and blocks until we have completed writing out the event
403 * and woken it back up.
404 */
405 void
406 ktrgenio(fd, rw, uio, error)
407 int fd;
408 enum uio_rw rw;
409 struct uio *uio;
410 int error;
411 {
412 struct ktr_request *req;
413 struct ktr_genio *ktg;
414 int datalen;
415 char *buf;
416
417 if (error)
418 return;
419 uio->uio_offset = 0;
420 uio->uio_rw = UIO_WRITE;
421 datalen = imin(uio->uio_resid, ktr_geniosize);
422 buf = malloc(datalen, M_KTRACE, M_WAITOK);
423 if (uiomove(buf, datalen, uio)) {
424 free(buf, M_KTRACE);
425 return;
426 }
427 req = ktr_getrequest(KTR_GENIO);
428 if (req == NULL) {
429 free(buf, M_KTRACE);
430 return;
431 }
432 ktg = &req->ktr_data.ktr_genio;
433 ktg->ktr_fd = fd;
434 ktg->ktr_rw = rw;
435 req->ktr_header.ktr_len = datalen;
436 req->ktr_header.ktr_buffer = buf;
437 ktr_submitrequest(req);
438 }
439
440 void
441 ktrpsig(sig, action, mask, code)
442 int sig;
443 sig_t action;
444 sigset_t *mask;
445 int code;
446 {
447 struct ktr_request *req;
448 struct ktr_psig *kp;
449
450 req = ktr_getrequest(KTR_PSIG);
451 if (req == NULL)
452 return;
453 kp = &req->ktr_data.ktr_psig;
454 kp->signo = (char)sig;
455 kp->action = action;
456 kp->mask = *mask;
457 kp->code = code;
458 ktr_submitrequest(req);
459 }
460
461 void
462 ktrcsw(out, user)
463 int out, user;
464 {
465 struct ktr_request *req;
466 struct ktr_csw *kc;
467
468 req = ktr_getrequest(KTR_CSW);
469 if (req == NULL)
470 return;
471 kc = &req->ktr_data.ktr_csw;
472 kc->out = out;
473 kc->user = user;
474 ktr_submitrequest(req);
475 }
476 #endif /* KTRACE */
477
478 /* Interface and common routines */
479
480 /*
481 * ktrace system call
482 *
483 * MPSAFE
484 */
485 #ifndef _SYS_SYSPROTO_H_
486 struct ktrace_args {
487 char *fname;
488 int ops;
489 int facs;
490 int pid;
491 };
492 #endif
493 /* ARGSUSED */
494 int
495 ktrace(td, uap)
496 struct thread *td;
497 register struct ktrace_args *uap;
498 {
499 #ifdef KTRACE
500 register struct vnode *vp = NULL;
501 register struct proc *p;
502 struct pgrp *pg;
503 int facs = uap->facs & ~KTRFAC_ROOT;
504 int ops = KTROP(uap->ops);
505 int descend = uap->ops & KTRFLAG_DESCEND;
506 int ret = 0;
507 int flags, error = 0;
508 struct nameidata nd;
509 struct ucred *cred;
510
511 /*
512 * Need something to (un)trace.
513 */
514 if (ops != KTROP_CLEARFILE && facs == 0)
515 return (EINVAL);
516
517 td->td_inktrace = 1;
518 if (ops != KTROP_CLEAR) {
519 /*
520 * an operation which requires a file argument.
521 */
522 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td);
523 flags = FREAD | FWRITE | O_NOFOLLOW;
524 mtx_lock(&Giant);
525 error = vn_open(&nd, &flags, 0);
526 if (error) {
527 mtx_unlock(&Giant);
528 td->td_inktrace = 0;
529 return (error);
530 }
531 NDFREE(&nd, NDF_ONLY_PNBUF);
532 vp = nd.ni_vp;
533 VOP_UNLOCK(vp, 0, td);
534 if (vp->v_type != VREG) {
535 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
536 mtx_unlock(&Giant);
537 td->td_inktrace = 0;
538 return (EACCES);
539 }
540 mtx_unlock(&Giant);
541 }
542 /*
543 * Clear all uses of the tracefile.
544 */
545 if (ops == KTROP_CLEARFILE) {
546 sx_slock(&allproc_lock);
547 LIST_FOREACH(p, &allproc, p_list) {
548 PROC_LOCK(p);
549 if (p->p_tracevp == vp) {
550 if (ktrcanset(td, p)) {
551 mtx_lock(&ktrace_mtx);
552 cred = p->p_tracecred;
553 p->p_tracecred = NULL;
554 p->p_tracevp = NULL;
555 p->p_traceflag = 0;
556 mtx_unlock(&ktrace_mtx);
557 PROC_UNLOCK(p);
558 mtx_lock(&Giant);
559 (void) vn_close(vp, FREAD|FWRITE,
560 cred, td);
561 mtx_unlock(&Giant);
562 crfree(cred);
563 } else {
564 PROC_UNLOCK(p);
565 error = EPERM;
566 }
567 } else
568 PROC_UNLOCK(p);
569 }
570 sx_sunlock(&allproc_lock);
571 goto done;
572 }
573 /*
574 * do it
575 */
576 sx_slock(&proctree_lock);
577 if (uap->pid < 0) {
578 /*
579 * by process group
580 */
581 pg = pgfind(-uap->pid);
582 if (pg == NULL) {
583 sx_sunlock(&proctree_lock);
584 error = ESRCH;
585 goto done;
586 }
587 /*
588 * ktrops() may call vrele(). Lock pg_members
589 * by the proctree_lock rather than pg_mtx.
590 */
591 PGRP_UNLOCK(pg);
592 LIST_FOREACH(p, &pg->pg_members, p_pglist)
593 if (descend)
594 ret |= ktrsetchildren(td, p, ops, facs, vp);
595 else
596 ret |= ktrops(td, p, ops, facs, vp);
597 } else {
598 /*
599 * by pid
600 */
601 p = pfind(uap->pid);
602 if (p == NULL) {
603 sx_sunlock(&proctree_lock);
604 error = ESRCH;
605 goto done;
606 }
607 /*
608 * The slock of the proctree lock will keep this process
609 * from going away, so unlocking the proc here is ok.
610 */
611 PROC_UNLOCK(p);
612 if (descend)
613 ret |= ktrsetchildren(td, p, ops, facs, vp);
614 else
615 ret |= ktrops(td, p, ops, facs, vp);
616 }
617 sx_sunlock(&proctree_lock);
618 if (!ret)
619 error = EPERM;
620 done:
621 if (vp != NULL) {
622 mtx_lock(&Giant);
623 (void) vn_close(vp, FWRITE, td->td_ucred, td);
624 mtx_unlock(&Giant);
625 }
626 td->td_inktrace = 0;
627 return (error);
628 #else /* !KTRACE */
629 return (ENOSYS);
630 #endif /* KTRACE */
631 }
632
633 /*
634 * utrace system call
635 *
636 * MPSAFE
637 */
638 /* ARGSUSED */
639 int
640 utrace(td, uap)
641 struct thread *td;
642 register struct utrace_args *uap;
643 {
644
645 #ifdef KTRACE
646 struct ktr_request *req;
647 void *cp;
648 int error;
649
650 if (!KTRPOINT(td, KTR_USER))
651 return (0);
652 if (uap->len > KTR_USER_MAXLEN)
653 return (EINVAL);
654 cp = malloc(uap->len, M_KTRACE, M_WAITOK);
655 error = copyin(uap->addr, cp, uap->len);
656 if (error) {
657 free(cp, M_KTRACE);
658 return (error);
659 }
660 req = ktr_getrequest(KTR_USER);
661 if (req == NULL) {
662 free(cp, M_KTRACE);
663 return (0);
664 }
665 req->ktr_header.ktr_buffer = cp;
666 req->ktr_header.ktr_len = uap->len;
667 ktr_submitrequest(req);
668 return (0);
669 #else /* !KTRACE */
670 return (ENOSYS);
671 #endif /* KTRACE */
672 }
673
674 #ifdef KTRACE
675 static int
676 ktrops(td, p, ops, facs, vp)
677 struct thread *td;
678 struct proc *p;
679 int ops, facs;
680 struct vnode *vp;
681 {
682 struct vnode *tracevp = NULL;
683 struct ucred *tracecred = NULL;
684
685 PROC_LOCK(p);
686 if (!ktrcanset(td, p)) {
687 PROC_UNLOCK(p);
688 return (0);
689 }
690 mtx_lock(&ktrace_mtx);
691 if (ops == KTROP_SET) {
692 if (p->p_tracevp != vp) {
693 /*
694 * if trace file already in use, relinquish below
695 */
696 tracevp = p->p_tracevp;
697 VREF(vp);
698 p->p_tracevp = vp;
699 }
700 if (p->p_tracecred != td->td_ucred) {
701 tracecred = p->p_tracecred;
702 p->p_tracecred = crhold(td->td_ucred);
703 }
704 p->p_traceflag |= facs;
705 if (td->td_ucred->cr_uid == 0)
706 p->p_traceflag |= KTRFAC_ROOT;
707 } else {
708 /* KTROP_CLEAR */
709 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
710 /* no more tracing */
711 p->p_traceflag = 0;
712 tracevp = p->p_tracevp;
713 p->p_tracevp = NULL;
714 tracecred = p->p_tracecred;
715 p->p_tracecred = NULL;
716 }
717 }
718 mtx_unlock(&ktrace_mtx);
719 PROC_UNLOCK(p);
720 if (tracevp != NULL) {
721 mtx_lock(&Giant);
722 vrele(tracevp);
723 mtx_unlock(&Giant);
724 }
725 if (tracecred != NULL)
726 crfree(tracecred);
727
728 return (1);
729 }
730
731 static int
732 ktrsetchildren(td, top, ops, facs, vp)
733 struct thread *td;
734 struct proc *top;
735 int ops, facs;
736 struct vnode *vp;
737 {
738 register struct proc *p;
739 register int ret = 0;
740
741 p = top;
742 sx_assert(&proctree_lock, SX_LOCKED);
743 for (;;) {
744 ret |= ktrops(td, p, ops, facs, vp);
745 /*
746 * If this process has children, descend to them next,
747 * otherwise do any siblings, and if done with this level,
748 * follow back up the tree (but not past top).
749 */
750 if (!LIST_EMPTY(&p->p_children))
751 p = LIST_FIRST(&p->p_children);
752 else for (;;) {
753 if (p == top)
754 return (ret);
755 if (LIST_NEXT(p, p_sibling)) {
756 p = LIST_NEXT(p, p_sibling);
757 break;
758 }
759 p = p->p_pptr;
760 }
761 }
762 /*NOTREACHED*/
763 }
764
765 static void
766 ktr_writerequest(struct ktr_request *req)
767 {
768 struct ktr_header *kth;
769 struct vnode *vp;
770 struct proc *p;
771 struct thread *td;
772 struct ucred *cred;
773 struct uio auio;
774 struct iovec aiov[3];
775 struct mount *mp;
776 int datalen, buflen, vrele_count;
777 int error;
778
779 vp = req->ktr_vp;
780 /*
781 * If vp is NULL, the vp has been cleared out from under this
782 * request, so just drop it.
783 */
784 if (vp == NULL)
785 return;
786 kth = &req->ktr_header;
787 datalen = data_lengths[(ushort)kth->ktr_type & ~KTR_DROP];
788 buflen = kth->ktr_len;
789 cred = req->ktr_cred;
790 td = curthread;
791 auio.uio_iov = &aiov[0];
792 auio.uio_offset = 0;
793 auio.uio_segflg = UIO_SYSSPACE;
794 auio.uio_rw = UIO_WRITE;
795 aiov[0].iov_base = (caddr_t)kth;
796 aiov[0].iov_len = sizeof(struct ktr_header);
797 auio.uio_resid = sizeof(struct ktr_header);
798 auio.uio_iovcnt = 1;
799 auio.uio_td = td;
800 if (datalen != 0) {
801 aiov[1].iov_base = (caddr_t)&req->ktr_data;
802 aiov[1].iov_len = datalen;
803 auio.uio_resid += datalen;
804 auio.uio_iovcnt++;
805 kth->ktr_len += datalen;
806 }
807 if (buflen != 0) {
808 KASSERT(kth->ktr_buffer != NULL, ("ktrace: nothing to write"));
809 aiov[auio.uio_iovcnt].iov_base = kth->ktr_buffer;
810 aiov[auio.uio_iovcnt].iov_len = buflen;
811 auio.uio_resid += buflen;
812 auio.uio_iovcnt++;
813 }
814 mtx_lock(&Giant);
815 vn_start_write(vp, &mp, V_WAIT);
816 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
817 (void)VOP_LEASE(vp, td, cred, LEASE_WRITE);
818 #ifdef MAC
819 error = mac_check_vnode_write(cred, NOCRED, vp);
820 if (error == 0)
821 #endif
822 error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, cred);
823 VOP_UNLOCK(vp, 0, td);
824 vn_finished_write(mp);
825 mtx_unlock(&Giant);
826 if (!error)
827 return;
828 /*
829 * If error encountered, give up tracing on this vnode. We defer
830 * all the vrele()'s on the vnode until after we are finished walking
831 * the various lists to avoid needlessly holding locks.
832 */
833 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
834 error);
835 vrele_count = 0;
836 /*
837 * First, clear this vnode from being used by any processes in the
838 * system.
839 * XXX - If one process gets an EPERM writing to the vnode, should
840 * we really do this? Other processes might have suitable
841 * credentials for the operation.
842 */
843 cred = NULL;
844 sx_slock(&allproc_lock);
845 LIST_FOREACH(p, &allproc, p_list) {
846 PROC_LOCK(p);
847 if (p->p_tracevp == vp) {
848 mtx_lock(&ktrace_mtx);
849 p->p_tracevp = NULL;
850 p->p_traceflag = 0;
851 cred = p->p_tracecred;
852 p->p_tracecred = NULL;
853 mtx_unlock(&ktrace_mtx);
854 vrele_count++;
855 }
856 PROC_UNLOCK(p);
857 if (cred != NULL) {
858 crfree(cred);
859 cred = NULL;
860 }
861 }
862 sx_sunlock(&allproc_lock);
863 /*
864 * Second, clear this vnode from any pending requests.
865 */
866 mtx_lock(&ktrace_mtx);
867 STAILQ_FOREACH(req, &ktr_todo, ktr_list) {
868 if (req->ktr_vp == vp) {
869 req->ktr_vp = NULL;
870 vrele_count++;
871 }
872 }
873 mtx_unlock(&ktrace_mtx);
874 mtx_lock(&Giant);
875 while (vrele_count-- > 0)
876 vrele(vp);
877 mtx_unlock(&Giant);
878 }
879
880 /*
881 * Return true if caller has permission to set the ktracing state
882 * of target. Essentially, the target can't possess any
883 * more permissions than the caller. KTRFAC_ROOT signifies that
884 * root previously set the tracing status on the target process, and
885 * so, only root may further change it.
886 */
887 static int
888 ktrcanset(td, targetp)
889 struct thread *td;
890 struct proc *targetp;
891 {
892
893 PROC_LOCK_ASSERT(targetp, MA_OWNED);
894 if (targetp->p_traceflag & KTRFAC_ROOT &&
895 suser_cred(td->td_ucred, PRISON_ROOT))
896 return (0);
897
898 if (p_candebug(td, targetp) != 0)
899 return (0);
900
901 return (1);
902 }
903
904 #endif /* KTRACE */
Cache object: 1040153cc2958791793286b7afb0f447
|