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