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