libhammer.3: Fix typo.
[dragonfly.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  * 3. 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  * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.6 2002/07/05 22:36:38 darrenr Exp $
31  */
32
33 #include "opt_ktrace.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/uio.h>
38 #include <sys/sysmsg.h>
39 #include <sys/kernel.h>
40 #include <sys/proc.h>
41 #include <sys/fcntl.h>
42 #include <sys/lock.h>
43 #include <sys/nlookup.h>
44 #include <sys/vnode.h>
45 #include <sys/ktrace.h>
46 #include <sys/malloc.h>
47 #include <sys/syslog.h>
48 #include <sys/sysent.h>
49
50 #include <vm/vm_zone.h>
51
52 static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE");
53
54 #ifdef KTRACE
55 static void ktrgetheader (struct ktr_header *kth, int type);
56 static struct ktr_syscall *ktrgetsyscall(struct ktr_header *kth,
57                                 struct ktr_syscall *ktp_cache, int narg);
58 static void ktrputsyscall(struct ktr_syscall *ktp_cache,
59                                 struct ktr_syscall *ktp);
60 static void ktrwrite (struct lwp *, struct ktr_header *, struct uio *);
61 static int ktrcanset (struct thread *,struct proc *);
62 static int ktrsetchildren (struct thread *, struct proc *,
63                                 int, int, ktrace_node_t);
64 static int ktrops (struct thread *,struct proc *,int,int, ktrace_node_t);
65
66 /*
67  * MPSAFE
68  */
69 static
70 void
71 ktrgetheader(struct ktr_header *kth, int type)
72 {
73         thread_t td = curthread;
74         struct proc *p = td->td_proc;
75         struct lwp *lp = td->td_lwp;
76
77         kth->ktr_type = type;
78         /* XXX threaded flag is a hack at the moment */
79         kth->ktr_flags = (p->p_nthreads > 1) ? KTRH_THREADED : 0;
80         kth->ktr_flags |= KTRH_CPUID_ENCODE(td->td_gd->gd_cpuid);
81         /*microtime(&kth->ktr_time); set in ktrwrite */
82         kth->ktr_pid = p->p_pid;
83         kth->ktr_tid = lp->lwp_tid;
84         bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1);
85 }
86
87 static
88 struct ktr_syscall *
89 ktrgetsyscall(struct ktr_header *kth, struct ktr_syscall *ktp_cache, int narg)
90 {
91         size_t len;
92
93         len = offsetof(struct ktr_syscall, ktr_args[narg]);
94         if (len > sizeof(*ktp_cache))
95                 ktp_cache = kmalloc(len, M_KTRACE, M_WAITOK);
96         kth->ktr_buf = (caddr_t)ktp_cache;
97         kth->ktr_len = (int)len;
98         return (ktp_cache);
99 }
100
101 static
102 void
103 ktrputsyscall(struct ktr_syscall *ktp_cache, struct ktr_syscall *ktp)
104 {
105         if (ktp != ktp_cache)
106                 kfree(ktp, M_KTRACE);
107 }
108
109 void
110 ktrsyscall(struct lwp *lp, int code, int narg, union sysunion *uap)
111 {
112         struct ktr_header kth;
113         struct ktr_syscall ktp_cache;
114         struct ktr_syscall *ktp;
115         register_t *argp;
116         register_t *args = (void *)uap;
117         int i;
118
119         /*
120          * Setting the active bit prevents a ktrace recursion from the
121          * ktracing op itself.
122          */
123         lp->lwp_traceflag |= KTRFAC_ACTIVE;
124         ktrgetheader(&kth, KTR_SYSCALL);
125
126         ktp = ktrgetsyscall(&kth, &ktp_cache, narg);
127         ktp->ktr_code = code;
128         ktp->ktr_narg = narg;
129         argp = &ktp->ktr_args[0];
130         for (i = 0; i < narg; i++)
131                 *argp++ = args[i];
132         ktrwrite(lp, &kth, NULL);
133
134         ktrputsyscall(&ktp_cache, ktp);
135         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
136 }
137
138 void
139 ktrsysret(struct lwp *lp, int code, int error, register_t retval)
140 {
141         struct ktr_header kth;
142         struct ktr_sysret ktp;
143
144         lp->lwp_traceflag |= KTRFAC_ACTIVE;
145         ktrgetheader(&kth, KTR_SYSRET);
146
147         ktp.ktr_code = code;
148         ktp.ktr_error = error;
149         if (error == 0)
150                 ktp.ktr_retval = retval;                /* what about val2 ? */
151         else
152                 ktp.ktr_retval = 0;
153
154         kth.ktr_buf = (caddr_t)&ktp;
155         kth.ktr_len = (int)sizeof(struct ktr_sysret);
156
157         ktrwrite(lp, &kth, NULL);
158         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
159 }
160
161 void
162 ktrnamei(struct lwp *lp, char *path)
163 {
164         struct ktr_header kth;
165
166         lp->lwp_traceflag |= KTRFAC_ACTIVE;
167         ktrgetheader(&kth, KTR_NAMEI);
168
169         kth.ktr_len = (int)strlen(path);
170         kth.ktr_buf = path;
171
172         ktrwrite(lp, &kth, NULL);
173         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
174 }
175
176 void
177 ktrgenio(struct lwp *lp, int fd, enum uio_rw rw, struct uio *uio, int error)
178 {
179         struct ktr_header kth;
180         struct ktr_genio ktg;
181
182         if (error)
183                 return;
184         lp->lwp_traceflag |= KTRFAC_ACTIVE;
185         ktrgetheader(&kth, KTR_GENIO);
186
187         ktg.ktr_fd = fd;
188         ktg.ktr_rw = rw;
189         kth.ktr_buf = (caddr_t)&ktg;
190         kth.ktr_len = (int)sizeof(struct ktr_genio);
191         uio->uio_offset = 0;
192         uio->uio_rw = UIO_WRITE;
193
194         ktrwrite(lp, &kth, uio);
195         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
196 }
197
198 void
199 ktrpsig(struct lwp *lp, int sig, sig_t action, sigset_t *mask, int code)
200 {
201         struct ktr_header kth;
202         struct ktr_psig kp;
203
204         lp->lwp_traceflag |= KTRFAC_ACTIVE;
205         ktrgetheader(&kth, KTR_PSIG);
206
207         kp.signo = (char)sig;
208         kp.action = action;
209         kp.mask = *mask;
210         kp.code = code;
211         kth.ktr_buf = (caddr_t)&kp;
212         kth.ktr_len = (int)sizeof(struct ktr_psig);
213
214         ktrwrite(lp, &kth, NULL);
215         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
216 }
217
218 void
219 ktrcsw(struct lwp *lp, int out, int user)
220 {
221         struct ktr_header kth;
222         struct ktr_csw kc;
223
224         lp->lwp_traceflag |= KTRFAC_ACTIVE;
225         ktrgetheader(&kth, KTR_CSW);
226
227         kc.out = out;
228         kc.user = user;
229         kth.ktr_buf = (caddr_t)&kc;
230         kth.ktr_len = (int)sizeof(struct ktr_csw);
231
232         ktrwrite(lp, &kth, NULL);
233         lp->lwp_traceflag &= ~KTRFAC_ACTIVE;
234 }
235 #endif
236
237 /* Interface and common routines */
238
239 #ifdef KTRACE
240 /*
241  * ktrace system call
242  */
243 struct ktrace_clear_info {
244         ktrace_node_t tracenode;
245         int rootclear;
246         int error;
247 };
248
249 static int ktrace_clear_callback(struct proc *p, void *data);
250
251 #endif
252
253 /*
254  * MPALMOSTSAFE
255  */
256 int
257 sys_ktrace(struct sysmsg *sysmsg, const struct ktrace_args *uap)
258 {
259 #ifdef KTRACE
260         struct ktrace_clear_info info;
261         struct thread *td = curthread;
262         struct proc *curp = td->td_proc;
263         struct proc *p;
264         struct pgrp *pg;
265         int facs = uap->facs & ~KTRFAC_ROOT;
266         int ops = KTROP(uap->ops);
267         int descend = uap->ops & KTRFLAG_DESCEND;
268         int ret = 0;
269         int error = 0;
270         struct nlookupdata nd;
271         ktrace_node_t tracenode = NULL;
272
273         lwkt_gettoken(&curp->p_token);
274         curp->p_traceflag |= KTRFAC_ACTIVE;
275
276         if (ops != KTROP_CLEAR) {
277                 /*
278                  * an operation which requires a file argument.
279                  */
280                 error = nlookup_init(&nd, uap->fname, 
281                                         UIO_USERSPACE, NLC_LOCKVP);
282                 if (error == 0)
283                         error = vn_open(&nd, NULL, FREAD|FWRITE|O_NOFOLLOW, 0);
284                 if (error == 0 && nd.nl_open_vp->v_type != VREG)
285                         error = EACCES;
286                 if (error) {
287                         curp->p_traceflag &= ~KTRFAC_ACTIVE;
288                         nlookup_done(&nd);
289                         goto done;
290                 }
291                 tracenode = kmalloc(sizeof(struct ktrace_node), M_KTRACE,
292                                     M_WAITOK | M_ZERO);
293                 tracenode->kn_vp = nd.nl_open_vp;
294                 tracenode->kn_refs = 1;
295                 nd.nl_open_vp = NULL;
296                 nlookup_done(&nd);
297                 vn_unlock(tracenode->kn_vp);
298         }
299         /*
300          * Clear all uses of the tracefile.  Not the most efficient operation
301          * in the world.
302          */
303         if (ops == KTROP_CLEARFILE) {
304                 info.tracenode = tracenode;
305                 info.error = 0;
306                 info.rootclear = 0;
307                 allproc_scan(ktrace_clear_callback, &info, 0);
308                 error = info.error;
309                 goto done;
310         }
311         /*
312          * need something to (un)trace (XXX - why is this here?)
313          */
314         if (!facs) {
315                 error = EINVAL;
316                 goto done;
317         }
318         /*
319          * do it
320          */
321         if (uap->pid < 0) {
322                 /*
323                  * By process group.  Process group is referenced, preventing
324                  * disposal.
325                  */
326                 pg = pgfind(-uap->pid);
327                 if (pg == NULL) {
328                         error = ESRCH;
329                         goto done;
330                 }
331                 lwkt_gettoken(&pg->pg_token);
332                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
333                         PHOLD(p);
334                         if (descend)
335                                 ret |= ktrsetchildren(td, p, ops, facs, tracenode);
336                         else
337                                 ret |= ktrops(td, p, ops, facs, tracenode);
338                         PRELE(p);
339                 }
340                 lwkt_reltoken(&pg->pg_token);
341                 pgrel(pg);
342         } else {
343                 /*
344                  * by pid
345                  */
346                 p = pfind(uap->pid);
347                 if (p == NULL) {
348                         error = ESRCH;
349                         goto done;
350                 }
351                 if (descend)
352                         ret |= ktrsetchildren(td, p, ops, facs, tracenode);
353                 else
354                         ret |= ktrops(td, p, ops, facs, tracenode);
355                 PRELE(p);
356         }
357         if (!ret)
358                 error = EPERM;
359 done:
360         if (tracenode)
361                 ktrdestroy(&tracenode);
362         curp->p_traceflag &= ~KTRFAC_ACTIVE;
363         lwkt_reltoken(&curp->p_token);
364         return (error);
365 #else
366         return ENOSYS;
367 #endif
368 }
369
370 #ifdef KTRACE
371
372 /*
373  * NOTE: NOT MPSAFE (yet)
374  */
375 static int
376 ktrace_clear_callback(struct proc *p, void *data)
377 {
378         struct ktrace_clear_info *info = data;
379
380         if (p->p_tracenode) {
381                 if (info->rootclear) {
382                         if (p->p_tracenode == info->tracenode) {
383                                 ktrdestroy(&p->p_tracenode);
384                                 p->p_traceflag = 0;
385                         }
386                 } else {
387                         if (p->p_tracenode->kn_vp == info->tracenode->kn_vp) {
388                                 if (ktrcanset(curthread, p)) {
389                                         ktrdestroy(&p->p_tracenode);
390                                         p->p_traceflag = 0;
391                                 } else {
392                                         info->error = EPERM;
393                                 }
394                         }
395                 }
396         }
397         return(0);
398 }
399
400 #endif
401
402 /*
403  * utrace system call
404  *
405  * MPALMOSTSAFE
406  */
407 int
408 sys_utrace(struct sysmsg *sysmsg, const struct utrace_args *uap)
409 {
410 #ifdef KTRACE
411         struct ktr_header kth;
412         struct thread *td = curthread;  /* XXX */
413         char cp_cache[64];
414         caddr_t cp;
415
416         if (!KTRPOINT(td, KTR_USER))
417                 return (0);
418         if (uap->len > KTR_USER_MAXLEN)
419                 return (EINVAL);
420         td->td_lwp->lwp_traceflag |= KTRFAC_ACTIVE;
421         ktrgetheader(&kth, KTR_USER);
422         if (uap->len <= sizeof(cp_cache))
423                 cp = cp_cache;
424         else
425                 cp = kmalloc(uap->len, M_KTRACE, M_WAITOK);
426
427         if (!copyin(uap->addr, cp, uap->len)) {
428                 kth.ktr_buf = cp;
429                 kth.ktr_len = uap->len;
430                 ktrwrite(td->td_lwp, &kth, NULL);
431         }
432         if (cp != cp_cache)
433                 kfree(cp, M_KTRACE);
434         td->td_lwp->lwp_traceflag &= ~KTRFAC_ACTIVE;
435
436         return (0);
437 #else
438         return (ENOSYS);
439 #endif
440 }
441
442 void
443 ktrdestroy(struct ktrace_node **tracenodep)
444 {
445         ktrace_node_t tracenode;
446
447         if ((tracenode = *tracenodep) != NULL) {
448                 *tracenodep = NULL;
449                 KKASSERT(tracenode->kn_refs > 0);
450                 if (atomic_fetchadd_int(&tracenode->kn_refs, -1) == 1) {
451                         vn_close(tracenode->kn_vp, FREAD|FWRITE, NULL);
452                         tracenode->kn_vp = NULL;
453                         kfree(tracenode, M_KTRACE);
454                 }
455         }
456 }
457
458 /*
459  * This allows a process to inherit a ref on a tracenode and is also used
460  * as a temporary ref to prevent a tracenode from being destroyed out from
461  * under an active operation.
462  */
463 ktrace_node_t
464 ktrinherit(ktrace_node_t tracenode)
465 {
466         if (tracenode) {
467                 KKASSERT(tracenode->kn_refs > 0);
468                 atomic_add_int(&tracenode->kn_refs, 1);
469         }
470         return(tracenode);
471 }
472
473 #ifdef KTRACE
474 static int
475 ktrops(struct thread *td, struct proc *p, int ops, int facs,
476        ktrace_node_t tracenode)
477 {
478         ktrace_node_t oldnode;
479
480         if (!ktrcanset(td, p))
481                 return (0);
482         if (ops == KTROP_SET) {
483                 if ((oldnode = p->p_tracenode) != tracenode) {
484                         p->p_tracenode = ktrinherit(tracenode);
485                         ktrdestroy(&oldnode);
486                 }
487                 p->p_traceflag |= facs;
488                 if (td->td_ucred->cr_uid == 0)
489                         p->p_traceflag |= KTRFAC_ROOT;
490         } else {
491                 /* KTROP_CLEAR */
492                 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
493                         /* no more tracing */
494                         p->p_traceflag = 0;
495                         ktrdestroy(&p->p_tracenode);
496                 }
497         }
498
499         return (1);
500 }
501
502 static int
503 ktrsetchildren(struct thread *td, struct proc *top, int ops, int facs,
504                ktrace_node_t tracenode)
505 {
506         struct proc *p;
507         struct proc *np;
508         int ret = 0;
509
510         p = top;
511         PHOLD(p);
512         lwkt_gettoken(&p->p_token);
513
514         for (;;) {
515                 ret |= ktrops(td, p, ops, facs, tracenode);
516
517                 /*
518                  * If this process has children, descend to them next,
519                  * otherwise do any siblings, and if done with this level,
520                  * follow back up the tree (but not past top).
521                  */
522                 if ((np = LIST_FIRST(&p->p_children)) != NULL) {
523                         PHOLD(np);
524                 }
525                 while (np == NULL) {
526                         if (p == top)
527                                 break;
528                         if ((np = LIST_NEXT(p, p_sibling)) != NULL) {
529                                 PHOLD(np);
530                                 break;
531                         }
532
533                         /*
534                          * recurse up to parent, set p in our inner
535                          * loop when doing this.  np can be NULL if
536                          * we race a reparenting to init (thus 'top'
537                          * is skipped past and never encountered).
538                          */
539                         np = p->p_pptr;
540                         if (np == NULL)
541                                 break;
542                         PHOLD(np);
543                         lwkt_reltoken(&p->p_token);
544                         PRELE(p);
545                         p = np;
546                         lwkt_gettoken(&p->p_token);
547                         np = NULL;
548                 }
549                 lwkt_reltoken(&p->p_token);
550                 PRELE(p);
551                 p = np;
552                 if (p == NULL)
553                         break;
554                 /* Already held, but we need the token too */
555                 lwkt_gettoken(&p->p_token);
556         }
557         return (ret);
558 }
559
560 static void
561 ktrwrite(struct lwp *lp, struct ktr_header *kth, struct uio *uio)
562 {
563         struct ktrace_clear_info info;
564         struct uio auio;
565         struct iovec aiov[2];
566         int error;
567         ktrace_node_t tracenode;
568
569         /*
570          * We have to ref our tracenode to prevent it from being ripped out
571          * from under us while we are trying to use it.   p_tracenode can
572          * go away at any time if another process gets a write error.
573          *
574          * XXX not MP safe
575          */
576         if (lp->lwp_proc->p_tracenode == NULL)
577                 return;
578         tracenode = ktrinherit(lp->lwp_proc->p_tracenode);
579         auio.uio_iov = &aiov[0];
580         auio.uio_offset = 0;
581         auio.uio_segflg = UIO_SYSSPACE;
582         auio.uio_rw = UIO_WRITE;
583         aiov[0].iov_base = (caddr_t)kth;
584         aiov[0].iov_len = sizeof(struct ktr_header);
585         auio.uio_resid = sizeof(struct ktr_header);
586         auio.uio_iovcnt = 1;
587         auio.uio_td = curthread;
588         if (kth->ktr_len > 0) {
589                 auio.uio_iovcnt++;
590                 aiov[1].iov_base = kth->ktr_buf;
591                 aiov[1].iov_len = kth->ktr_len;
592                 auio.uio_resid += kth->ktr_len;
593                 if (uio != NULL)
594                         kth->ktr_len += uio->uio_resid;
595         }
596
597         /*
598          * NOTE: Must set timestamp after obtaining lock to ensure no
599          *       timestamp reversals in the output file.
600          */
601         vn_lock(tracenode->kn_vp, LK_EXCLUSIVE | LK_RETRY);
602         microtime(&kth->ktr_time);
603         error = VOP_WRITE(tracenode->kn_vp, &auio,
604                           IO_UNIT | IO_APPEND, lp->lwp_thread->td_ucred);
605         if (error == 0 && uio != NULL) {
606                 error = VOP_WRITE(tracenode->kn_vp, uio,
607                               IO_UNIT | IO_APPEND, lp->lwp_thread->td_ucred);
608         }
609         vn_unlock(tracenode->kn_vp);
610         if (error) {
611                 /*
612                  * If an error occured, give up tracing on all processes
613                  * using this tracenode.  This is not MP safe but is
614                  * blocking-safe.
615                  */
616                 log(LOG_NOTICE,
617                     "ktrace write failed, errno %d, tracing stopped\n", error);
618                 info.tracenode = tracenode;
619                 info.error = 0;
620                 info.rootclear = 1;
621                 allproc_scan(ktrace_clear_callback, &info, 0);
622         }
623         ktrdestroy(&tracenode);
624 }
625
626 /*
627  * Return true if caller has permission to set the ktracing state
628  * of target.  Essentially, the target can't possess any
629  * more permissions than the caller.  KTRFAC_ROOT signifies that
630  * root previously set the tracing status on the target process, and
631  * so, only root may further change it.
632  *
633  * TODO: check groups.  use caller effective gid.
634  */
635 static int
636 ktrcanset(struct thread *calltd, struct proc *targetp)
637 {
638         struct ucred *caller = calltd->td_ucred;
639         struct ucred *target = targetp->p_ucred;
640
641         if (!PRISON_CHECK(caller, target))
642                 return (0);
643         if ((caller->cr_uid == target->cr_ruid &&
644              target->cr_ruid == target->cr_svuid &&
645              caller->cr_rgid == target->cr_rgid &&      /* XXX */
646              target->cr_rgid == target->cr_svgid &&
647              (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
648              (targetp->p_flags & P_SUGID) == 0) ||
649              caller->cr_uid == 0)
650                 return (1);
651
652         return (0);
653 }
654
655 #endif /* KTRACE */