The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_ktrace.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.
    4  * Copyright (c) 2005 Robert N. M. Watson
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 4. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)kern_ktrace.c       8.2 (Berkeley) 9/23/93
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/8.3/sys/kern/kern_ktrace.c 230159 2012-01-15 20:52:31Z eadler $");
   36 
   37 #include "opt_ktrace.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/kernel.h>
   43 #include <sys/kthread.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mount.h>
   48 #include <sys/namei.h>
   49 #include <sys/priv.h>
   50 #include <sys/proc.h>
   51 #include <sys/unistd.h>
   52 #include <sys/vnode.h>
   53 #include <sys/socket.h>
   54 #include <sys/stat.h>
   55 #include <sys/ktrace.h>
   56 #include <sys/sx.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/sysent.h>
   59 #include <sys/syslog.h>
   60 #include <sys/sysproto.h>
   61 
   62 #include <security/mac/mac_framework.h>
   63 
   64 /*
   65  * The ktrace facility allows the tracing of certain key events in user space
   66  * processes, such as system calls, signal delivery, context switches, and
   67  * user generated events using utrace(2).  It works by streaming event
   68  * records and data to a vnode associated with the process using the
   69  * ktrace(2) system call.  In general, records can be written directly from
   70  * the context that generates the event.  One important exception to this is
   71  * during a context switch, where sleeping is not permitted.  To handle this
   72  * case, trace events are generated using in-kernel ktr_request records, and
   73  * then delivered to disk at a convenient moment -- either immediately, the
   74  * next traceable event, at system call return, or at process exit.
   75  *
   76  * When dealing with multiple threads or processes writing to the same event
   77  * log, ordering guarantees are weak: specifically, if an event has multiple
   78  * records (i.e., system call enter and return), they may be interlaced with
   79  * records from another event.  Process and thread ID information is provided
   80  * in the record, and user applications can de-interlace events if required.
   81  */
   82 
   83 static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE");
   84 
   85 #ifdef KTRACE
   86 
   87 #ifndef KTRACE_REQUEST_POOL
   88 #define KTRACE_REQUEST_POOL     100
   89 #endif
   90 
   91 struct ktr_request {
   92         struct  ktr_header ktr_header;
   93         void    *ktr_buffer;
   94         union {
   95                 struct  ktr_proc_ctor ktr_proc_ctor;
   96                 struct  ktr_syscall ktr_syscall;
   97                 struct  ktr_sysret ktr_sysret;
   98                 struct  ktr_genio ktr_genio;
   99                 struct  ktr_psig ktr_psig;
  100                 struct  ktr_csw ktr_csw;
  101         } ktr_data;
  102         STAILQ_ENTRY(ktr_request) ktr_list;
  103 };
  104 
  105 static int data_lengths[] = {
  106         0,                                      /* none */
  107         offsetof(struct ktr_syscall, ktr_args), /* KTR_SYSCALL */
  108         sizeof(struct ktr_sysret),              /* KTR_SYSRET */
  109         0,                                      /* KTR_NAMEI */
  110         sizeof(struct ktr_genio),               /* KTR_GENIO */
  111         sizeof(struct ktr_psig),                /* KTR_PSIG */
  112         sizeof(struct ktr_csw),                 /* KTR_CSW */
  113         0,                                      /* KTR_USER */
  114         0,                                      /* KTR_STRUCT */
  115         0,                                      /* KTR_SYSCTL */
  116         sizeof(struct ktr_proc_ctor),           /* KTR_PROCCTOR */
  117         0,                                      /* KTR_PROCDTOR */
  118 };
  119 
  120 static STAILQ_HEAD(, ktr_request) ktr_free;
  121 
  122 static SYSCTL_NODE(_kern, OID_AUTO, ktrace, CTLFLAG_RD, 0, "KTRACE options");
  123 
  124 static u_int ktr_requestpool = KTRACE_REQUEST_POOL;
  125 TUNABLE_INT("kern.ktrace.request_pool", &ktr_requestpool);
  126 
  127 static u_int ktr_geniosize = PAGE_SIZE;
  128 TUNABLE_INT("kern.ktrace.genio_size", &ktr_geniosize);
  129 SYSCTL_UINT(_kern_ktrace, OID_AUTO, genio_size, CTLFLAG_RW, &ktr_geniosize,
  130     0, "Maximum size of genio event payload");
  131 
  132 static int print_message = 1;
  133 static struct mtx ktrace_mtx;
  134 static struct sx ktrace_sx;
  135 
  136 static void ktrace_init(void *dummy);
  137 static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
  138 static u_int ktrace_resize_pool(u_int oldsize, u_int newsize);
  139 static struct ktr_request *ktr_getrequest_entered(struct thread *td, int type);
  140 static struct ktr_request *ktr_getrequest(int type);
  141 static void ktr_submitrequest(struct thread *td, struct ktr_request *req);
  142 static void ktr_freeproc(struct proc *p, struct ucred **uc,
  143     struct vnode **vp);
  144 static void ktr_freerequest(struct ktr_request *req);
  145 static void ktr_freerequest_locked(struct ktr_request *req);
  146 static void ktr_writerequest(struct thread *td, struct ktr_request *req);
  147 static int ktrcanset(struct thread *,struct proc *);
  148 static int ktrsetchildren(struct thread *,struct proc *,int,int,struct vnode *);
  149 static int ktrops(struct thread *,struct proc *,int,int,struct vnode *);
  150 static void ktrprocctor_entered(struct thread *, struct proc *);
  151 
  152 /*
  153  * ktrace itself generates events, such as context switches, which we do not
  154  * wish to trace.  Maintain a flag, TDP_INKTRACE, on each thread to determine
  155  * whether or not it is in a region where tracing of events should be
  156  * suppressed.
  157  */
  158 static void
  159 ktrace_enter(struct thread *td)
  160 {
  161 
  162         KASSERT(!(td->td_pflags & TDP_INKTRACE), ("ktrace_enter: flag set"));
  163         td->td_pflags |= TDP_INKTRACE;
  164 }
  165 
  166 static void
  167 ktrace_exit(struct thread *td)
  168 {
  169 
  170         KASSERT(td->td_pflags & TDP_INKTRACE, ("ktrace_exit: flag not set"));
  171         td->td_pflags &= ~TDP_INKTRACE;
  172 }
  173 
  174 static void
  175 ktrace_assert(struct thread *td)
  176 {
  177 
  178         KASSERT(td->td_pflags & TDP_INKTRACE, ("ktrace_assert: flag not set"));
  179 }
  180 
  181 static void
  182 ktrace_init(void *dummy)
  183 {
  184         struct ktr_request *req;
  185         int i;
  186 
  187         mtx_init(&ktrace_mtx, "ktrace", NULL, MTX_DEF | MTX_QUIET);
  188         sx_init(&ktrace_sx, "ktrace_sx");
  189         STAILQ_INIT(&ktr_free);
  190         for (i = 0; i < ktr_requestpool; i++) {
  191                 req = malloc(sizeof(struct ktr_request), M_KTRACE, M_WAITOK);
  192                 STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
  193         }
  194 }
  195 SYSINIT(ktrace_init, SI_SUB_KTRACE, SI_ORDER_ANY, ktrace_init, NULL);
  196 
  197 static int
  198 sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS)
  199 {
  200         struct thread *td;
  201         u_int newsize, oldsize, wantsize;
  202         int error;
  203 
  204         /* Handle easy read-only case first to avoid warnings from GCC. */
  205         if (!req->newptr) {
  206                 oldsize = ktr_requestpool;
  207                 return (SYSCTL_OUT(req, &oldsize, sizeof(u_int)));
  208         }
  209 
  210         error = SYSCTL_IN(req, &wantsize, sizeof(u_int));
  211         if (error)
  212                 return (error);
  213         td = curthread;
  214         ktrace_enter(td);
  215         oldsize = ktr_requestpool;
  216         newsize = ktrace_resize_pool(oldsize, wantsize);
  217         ktrace_exit(td);
  218         error = SYSCTL_OUT(req, &oldsize, sizeof(u_int));
  219         if (error)
  220                 return (error);
  221         if (wantsize > oldsize && newsize < wantsize)
  222                 return (ENOSPC);
  223         return (0);
  224 }
  225 SYSCTL_PROC(_kern_ktrace, OID_AUTO, request_pool, CTLTYPE_UINT|CTLFLAG_RW,
  226     &ktr_requestpool, 0, sysctl_kern_ktrace_request_pool, "IU", "");
  227 
  228 static u_int
  229 ktrace_resize_pool(u_int oldsize, u_int newsize)
  230 {
  231         STAILQ_HEAD(, ktr_request) ktr_new;
  232         struct ktr_request *req;
  233         int bound;
  234 
  235         print_message = 1;
  236         bound = newsize - oldsize;
  237         if (bound == 0)
  238                 return (ktr_requestpool);
  239         if (bound < 0) {
  240                 mtx_lock(&ktrace_mtx);
  241                 /* Shrink pool down to newsize if possible. */
  242                 while (bound++ < 0) {
  243                         req = STAILQ_FIRST(&ktr_free);
  244                         if (req == NULL)
  245                                 break;
  246                         STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
  247                         ktr_requestpool--;
  248                         free(req, M_KTRACE);
  249                 }
  250         } else {
  251                 /* Grow pool up to newsize. */
  252                 STAILQ_INIT(&ktr_new);
  253                 while (bound-- > 0) {
  254                         req = malloc(sizeof(struct ktr_request), M_KTRACE,
  255                             M_WAITOK);
  256                         STAILQ_INSERT_HEAD(&ktr_new, req, ktr_list);
  257                 }
  258                 mtx_lock(&ktrace_mtx);
  259                 STAILQ_CONCAT(&ktr_free, &ktr_new);
  260                 ktr_requestpool += (newsize - oldsize);
  261         }
  262         mtx_unlock(&ktrace_mtx);
  263         return (ktr_requestpool);
  264 }
  265 
  266 /* ktr_getrequest() assumes that ktr_comm[] is the same size as td_name[]. */
  267 CTASSERT(sizeof(((struct ktr_header *)NULL)->ktr_comm) ==
  268     (sizeof((struct thread *)NULL)->td_name));
  269 
  270 static struct ktr_request *
  271 ktr_getrequest_entered(struct thread *td, int type)
  272 {
  273         struct ktr_request *req;
  274         struct proc *p = td->td_proc;
  275         int pm;
  276 
  277         mtx_lock(&ktrace_mtx);
  278         if (!KTRCHECK(td, type)) {
  279                 mtx_unlock(&ktrace_mtx);
  280                 return (NULL);
  281         }
  282         req = STAILQ_FIRST(&ktr_free);
  283         if (req != NULL) {
  284                 STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
  285                 req->ktr_header.ktr_type = type;
  286                 if (p->p_traceflag & KTRFAC_DROP) {
  287                         req->ktr_header.ktr_type |= KTR_DROP;
  288                         p->p_traceflag &= ~KTRFAC_DROP;
  289                 }
  290                 mtx_unlock(&ktrace_mtx);
  291                 microtime(&req->ktr_header.ktr_time);
  292                 req->ktr_header.ktr_pid = p->p_pid;
  293                 req->ktr_header.ktr_tid = td->td_tid;
  294                 bcopy(td->td_name, req->ktr_header.ktr_comm,
  295                     sizeof(req->ktr_header.ktr_comm));
  296                 req->ktr_buffer = NULL;
  297                 req->ktr_header.ktr_len = 0;
  298         } else {
  299                 p->p_traceflag |= KTRFAC_DROP;
  300                 pm = print_message;
  301                 print_message = 0;
  302                 mtx_unlock(&ktrace_mtx);
  303                 if (pm)
  304                         printf("Out of ktrace request objects.\n");
  305         }
  306         return (req);
  307 }
  308 
  309 static struct ktr_request *
  310 ktr_getrequest(int type)
  311 {
  312         struct thread *td = curthread;
  313         struct ktr_request *req;
  314 
  315         ktrace_enter(td);
  316         req = ktr_getrequest_entered(td, type);
  317         if (req == NULL)
  318                 ktrace_exit(td);
  319 
  320         return (req);
  321 }
  322 
  323 /*
  324  * Some trace generation environments don't permit direct access to VFS,
  325  * such as during a context switch where sleeping is not allowed.  Under these
  326  * circumstances, queue a request to the thread to be written asynchronously
  327  * later.
  328  */
  329 static void
  330 ktr_enqueuerequest(struct thread *td, struct ktr_request *req)
  331 {
  332 
  333         mtx_lock(&ktrace_mtx);
  334         STAILQ_INSERT_TAIL(&td->td_proc->p_ktr, req, ktr_list);
  335         mtx_unlock(&ktrace_mtx);
  336 }
  337 
  338 /*
  339  * Drain any pending ktrace records from the per-thread queue to disk.  This
  340  * is used both internally before committing other records, and also on
  341  * system call return.  We drain all the ones we can find at the time when
  342  * drain is requested, but don't keep draining after that as those events
  343  * may be approximately "after" the current event.
  344  */
  345 static void
  346 ktr_drain(struct thread *td)
  347 {
  348         struct ktr_request *queued_req;
  349         STAILQ_HEAD(, ktr_request) local_queue;
  350 
  351         ktrace_assert(td);
  352         sx_assert(&ktrace_sx, SX_XLOCKED);
  353 
  354         STAILQ_INIT(&local_queue);      /* XXXRW: needed? */
  355 
  356         if (!STAILQ_EMPTY(&td->td_proc->p_ktr)) {
  357                 mtx_lock(&ktrace_mtx);
  358                 STAILQ_CONCAT(&local_queue, &td->td_proc->p_ktr);
  359                 mtx_unlock(&ktrace_mtx);
  360 
  361                 while ((queued_req = STAILQ_FIRST(&local_queue))) {
  362                         STAILQ_REMOVE_HEAD(&local_queue, ktr_list);
  363                         ktr_writerequest(td, queued_req);
  364                         ktr_freerequest(queued_req);
  365                 }
  366         }
  367 }
  368 
  369 /*
  370  * Submit a trace record for immediate commit to disk -- to be used only
  371  * where entering VFS is OK.  First drain any pending records that may have
  372  * been cached in the thread.
  373  */
  374 static void
  375 ktr_submitrequest(struct thread *td, struct ktr_request *req)
  376 {
  377 
  378         ktrace_assert(td);
  379 
  380         sx_xlock(&ktrace_sx);
  381         ktr_drain(td);
  382         ktr_writerequest(td, req);
  383         ktr_freerequest(req);
  384         sx_xunlock(&ktrace_sx);
  385         ktrace_exit(td);
  386 }
  387 
  388 static void
  389 ktr_freerequest(struct ktr_request *req)
  390 {
  391 
  392         mtx_lock(&ktrace_mtx);
  393         ktr_freerequest_locked(req);
  394         mtx_unlock(&ktrace_mtx);
  395 }
  396 
  397 static void
  398 ktr_freerequest_locked(struct ktr_request *req)
  399 {
  400 
  401         mtx_assert(&ktrace_mtx, MA_OWNED);
  402         if (req->ktr_buffer != NULL)
  403                 free(req->ktr_buffer, M_KTRACE);
  404         STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
  405 }
  406 
  407 /*
  408  * Disable tracing for a process and release all associated resources.
  409  * The caller is responsible for releasing a reference on the returned
  410  * vnode and credentials.
  411  */
  412 static void
  413 ktr_freeproc(struct proc *p, struct ucred **uc, struct vnode **vp)
  414 {
  415         struct ktr_request *req;
  416 
  417         PROC_LOCK_ASSERT(p, MA_OWNED);
  418         mtx_assert(&ktrace_mtx, MA_OWNED);
  419         *uc = p->p_tracecred;
  420         p->p_tracecred = NULL;
  421         if (vp != NULL)
  422                 *vp = p->p_tracevp;
  423         p->p_tracevp = NULL;
  424         p->p_traceflag = 0;
  425         while ((req = STAILQ_FIRST(&p->p_ktr)) != NULL) {
  426                 STAILQ_REMOVE_HEAD(&p->p_ktr, ktr_list);
  427                 ktr_freerequest_locked(req);
  428         }
  429 }
  430 
  431 void
  432 ktrsyscall(code, narg, args)
  433         int code, narg;
  434         register_t args[];
  435 {
  436         struct ktr_request *req;
  437         struct ktr_syscall *ktp;
  438         size_t buflen;
  439         char *buf = NULL;
  440 
  441         buflen = sizeof(register_t) * narg;
  442         if (buflen > 0) {
  443                 buf = malloc(buflen, M_KTRACE, M_WAITOK);
  444                 bcopy(args, buf, buflen);
  445         }
  446         req = ktr_getrequest(KTR_SYSCALL);
  447         if (req == NULL) {
  448                 if (buf != NULL)
  449                         free(buf, M_KTRACE);
  450                 return;
  451         }
  452         ktp = &req->ktr_data.ktr_syscall;
  453         ktp->ktr_code = code;
  454         ktp->ktr_narg = narg;
  455         if (buflen > 0) {
  456                 req->ktr_header.ktr_len = buflen;
  457                 req->ktr_buffer = buf;
  458         }
  459         ktr_submitrequest(curthread, req);
  460 }
  461 
  462 void
  463 ktrsysret(code, error, retval)
  464         int code, error;
  465         register_t retval;
  466 {
  467         struct ktr_request *req;
  468         struct ktr_sysret *ktp;
  469 
  470         req = ktr_getrequest(KTR_SYSRET);
  471         if (req == NULL)
  472                 return;
  473         ktp = &req->ktr_data.ktr_sysret;
  474         ktp->ktr_code = code;
  475         ktp->ktr_error = error;
  476         ktp->ktr_retval = ((error == 0) ? retval: 0);           /* what about val2 ? */
  477         ktr_submitrequest(curthread, req);
  478 }
  479 
  480 /*
  481  * When a setuid process execs, disable tracing.
  482  *
  483  * XXX: We toss any pending asynchronous records.
  484  */
  485 void
  486 ktrprocexec(struct proc *p, struct ucred **uc, struct vnode **vp)
  487 {
  488 
  489         PROC_LOCK_ASSERT(p, MA_OWNED);
  490         mtx_lock(&ktrace_mtx);
  491         ktr_freeproc(p, uc, vp);
  492         mtx_unlock(&ktrace_mtx);
  493 }
  494 
  495 /*
  496  * When a process exits, drain per-process asynchronous trace records
  497  * and disable tracing.
  498  */
  499 void
  500 ktrprocexit(struct thread *td)
  501 {
  502         struct ktr_request *req;
  503         struct proc *p;
  504         struct ucred *cred;
  505         struct vnode *vp;
  506         int vfslocked;
  507 
  508         p = td->td_proc;
  509         if (p->p_traceflag == 0)
  510                 return;
  511 
  512         ktrace_enter(td);
  513         req = ktr_getrequest_entered(td, KTR_PROCDTOR);
  514         if (req != NULL)
  515                 ktr_enqueuerequest(td, req);
  516         sx_xlock(&ktrace_sx);
  517         ktr_drain(td);
  518         sx_xunlock(&ktrace_sx);
  519         PROC_LOCK(p);
  520         mtx_lock(&ktrace_mtx);
  521         ktr_freeproc(p, &cred, &vp);
  522         mtx_unlock(&ktrace_mtx);
  523         PROC_UNLOCK(p);
  524         if (vp != NULL) {
  525                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  526                 vrele(vp);
  527                 VFS_UNLOCK_GIANT(vfslocked);
  528         }
  529         if (cred != NULL)
  530                 crfree(cred);
  531         ktrace_exit(td);
  532 }
  533 
  534 static void
  535 ktrprocctor_entered(struct thread *td, struct proc *p)
  536 {
  537         struct ktr_proc_ctor *ktp;
  538         struct ktr_request *req;
  539         struct thread *td2;
  540 
  541         ktrace_assert(td);
  542         td2 = FIRST_THREAD_IN_PROC(p);
  543         req = ktr_getrequest_entered(td2, KTR_PROCCTOR);
  544         if (req == NULL)
  545                 return;
  546         ktp = &req->ktr_data.ktr_proc_ctor;
  547         ktp->sv_flags = p->p_sysent->sv_flags;
  548         ktr_enqueuerequest(td2, req);
  549 }
  550 
  551 void
  552 ktrprocctor(struct proc *p)
  553 {
  554         struct thread *td = curthread;
  555 
  556         if ((p->p_traceflag & KTRFAC_MASK) == 0)
  557                 return;
  558 
  559         ktrace_enter(td);
  560         ktrprocctor_entered(td, p);
  561         ktrace_exit(td);
  562 }
  563 
  564 /*
  565  * When a process forks, enable tracing in the new process if needed.
  566  */
  567 void
  568 ktrprocfork(struct proc *p1, struct proc *p2)
  569 {
  570 
  571         PROC_LOCK(p1);
  572         mtx_lock(&ktrace_mtx);
  573         KASSERT(p2->p_tracevp == NULL, ("new process has a ktrace vnode"));
  574         if (p1->p_traceflag & KTRFAC_INHERIT) {
  575                 p2->p_traceflag = p1->p_traceflag;
  576                 if ((p2->p_tracevp = p1->p_tracevp) != NULL) {
  577                         VREF(p2->p_tracevp);
  578                         KASSERT(p1->p_tracecred != NULL,
  579                             ("ktrace vnode with no cred"));
  580                         p2->p_tracecred = crhold(p1->p_tracecred);
  581                 }
  582         }
  583         mtx_unlock(&ktrace_mtx);
  584         PROC_UNLOCK(p1);
  585 
  586         ktrprocctor(p2);
  587 }
  588 
  589 /*
  590  * When a thread returns, drain any asynchronous records generated by the
  591  * system call.
  592  */
  593 void
  594 ktruserret(struct thread *td)
  595 {
  596 
  597         ktrace_enter(td);
  598         sx_xlock(&ktrace_sx);
  599         ktr_drain(td);
  600         sx_xunlock(&ktrace_sx);
  601         ktrace_exit(td);
  602 }
  603 
  604 void
  605 ktrnamei(path)
  606         char *path;
  607 {
  608         struct ktr_request *req;
  609         int namelen;
  610         char *buf = NULL;
  611 
  612         namelen = strlen(path);
  613         if (namelen > 0) {
  614                 buf = malloc(namelen, M_KTRACE, M_WAITOK);
  615                 bcopy(path, buf, namelen);
  616         }
  617         req = ktr_getrequest(KTR_NAMEI);
  618         if (req == NULL) {
  619                 if (buf != NULL)
  620                         free(buf, M_KTRACE);
  621                 return;
  622         }
  623         if (namelen > 0) {
  624                 req->ktr_header.ktr_len = namelen;
  625                 req->ktr_buffer = buf;
  626         }
  627         ktr_submitrequest(curthread, req);
  628 }
  629 
  630 void
  631 ktrsysctl(name, namelen)
  632         int *name;
  633         u_int namelen;
  634 {
  635         struct ktr_request *req;
  636         u_int mib[CTL_MAXNAME + 2];
  637         char *mibname;
  638         size_t mibnamelen;
  639         int error;
  640 
  641         /* Lookup name of mib. */    
  642         KASSERT(namelen <= CTL_MAXNAME, ("sysctl MIB too long"));
  643         mib[0] = 0;
  644         mib[1] = 1;
  645         bcopy(name, mib + 2, namelen * sizeof(*name));
  646         mibnamelen = 128;
  647         mibname = malloc(mibnamelen, M_KTRACE, M_WAITOK);
  648         error = kernel_sysctl(curthread, mib, namelen + 2, mibname, &mibnamelen,
  649             NULL, 0, &mibnamelen, 0);
  650         if (error) {
  651                 free(mibname, M_KTRACE);
  652                 return;
  653         }
  654         req = ktr_getrequest(KTR_SYSCTL);
  655         if (req == NULL) {
  656                 free(mibname, M_KTRACE);
  657                 return;
  658         }
  659         req->ktr_header.ktr_len = mibnamelen;
  660         req->ktr_buffer = mibname;
  661         ktr_submitrequest(curthread, req);
  662 }
  663 
  664 void
  665 ktrgenio(fd, rw, uio, error)
  666         int fd;
  667         enum uio_rw rw;
  668         struct uio *uio;
  669         int error;
  670 {
  671         struct ktr_request *req;
  672         struct ktr_genio *ktg;
  673         int datalen;
  674         char *buf;
  675 
  676         if (error) {
  677                 free(uio, M_IOV);
  678                 return;
  679         }
  680         uio->uio_offset = 0;
  681         uio->uio_rw = UIO_WRITE;
  682         datalen = imin(uio->uio_resid, ktr_geniosize);
  683         buf = malloc(datalen, M_KTRACE, M_WAITOK);
  684         error = uiomove(buf, datalen, uio);
  685         free(uio, M_IOV);
  686         if (error) {
  687                 free(buf, M_KTRACE);
  688                 return;
  689         }
  690         req = ktr_getrequest(KTR_GENIO);
  691         if (req == NULL) {
  692                 free(buf, M_KTRACE);
  693                 return;
  694         }
  695         ktg = &req->ktr_data.ktr_genio;
  696         ktg->ktr_fd = fd;
  697         ktg->ktr_rw = rw;
  698         req->ktr_header.ktr_len = datalen;
  699         req->ktr_buffer = buf;
  700         ktr_submitrequest(curthread, req);
  701 }
  702 
  703 void
  704 ktrpsig(sig, action, mask, code)
  705         int sig;
  706         sig_t action;
  707         sigset_t *mask;
  708         int code;
  709 {
  710         struct thread *td = curthread;
  711         struct ktr_request *req;
  712         struct ktr_psig *kp;
  713 
  714         req = ktr_getrequest(KTR_PSIG);
  715         if (req == NULL)
  716                 return;
  717         kp = &req->ktr_data.ktr_psig;
  718         kp->signo = (char)sig;
  719         kp->action = action;
  720         kp->mask = *mask;
  721         kp->code = code;
  722         ktr_enqueuerequest(td, req);
  723         ktrace_exit(td);
  724 }
  725 
  726 void
  727 ktrcsw(out, user)
  728         int out, user;
  729 {
  730         struct thread *td = curthread;
  731         struct ktr_request *req;
  732         struct ktr_csw *kc;
  733 
  734         req = ktr_getrequest(KTR_CSW);
  735         if (req == NULL)
  736                 return;
  737         kc = &req->ktr_data.ktr_csw;
  738         kc->out = out;
  739         kc->user = user;
  740         ktr_enqueuerequest(td, req);
  741         ktrace_exit(td);
  742 }
  743 
  744 void
  745 ktrstruct(name, namelen, data, datalen)
  746         const char *name;
  747         size_t namelen;
  748         void *data;
  749         size_t datalen;
  750 {
  751         struct ktr_request *req;
  752         char *buf = NULL;
  753         size_t buflen;
  754 
  755         if (!data)
  756                 datalen = 0;
  757         buflen = namelen + 1 + datalen;
  758         buf = malloc(buflen, M_KTRACE, M_WAITOK);
  759         bcopy(name, buf, namelen);
  760         buf[namelen] = '\0';
  761         bcopy(data, buf + namelen + 1, datalen);
  762         if ((req = ktr_getrequest(KTR_STRUCT)) == NULL) {
  763                 free(buf, M_KTRACE);
  764                 return;
  765         }
  766         req->ktr_buffer = buf;
  767         req->ktr_header.ktr_len = buflen;
  768         ktr_submitrequest(curthread, req);
  769 }
  770 #endif /* KTRACE */
  771 
  772 /* Interface and common routines */
  773 
  774 #ifndef _SYS_SYSPROTO_H_
  775 struct ktrace_args {
  776         char    *fname;
  777         int     ops;
  778         int     facs;
  779         int     pid;
  780 };
  781 #endif
  782 /* ARGSUSED */
  783 int
  784 ktrace(td, uap)
  785         struct thread *td;
  786         register struct ktrace_args *uap;
  787 {
  788 #ifdef KTRACE
  789         register struct vnode *vp = NULL;
  790         register struct proc *p;
  791         struct pgrp *pg;
  792         int facs = uap->facs & ~KTRFAC_ROOT;
  793         int ops = KTROP(uap->ops);
  794         int descend = uap->ops & KTRFLAG_DESCEND;
  795         int nfound, ret = 0;
  796         int flags, error = 0, vfslocked;
  797         struct nameidata nd;
  798         struct ucred *cred;
  799 
  800         /*
  801          * Need something to (un)trace.
  802          */
  803         if (ops != KTROP_CLEARFILE && facs == 0)
  804                 return (EINVAL);
  805 
  806         ktrace_enter(td);
  807         if (ops != KTROP_CLEAR) {
  808                 /*
  809                  * an operation which requires a file argument.
  810                  */
  811                 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE,
  812                     uap->fname, td);
  813                 flags = FREAD | FWRITE | O_NOFOLLOW;
  814                 error = vn_open(&nd, &flags, 0, NULL);
  815                 if (error) {
  816                         ktrace_exit(td);
  817                         return (error);
  818                 }
  819                 vfslocked = NDHASGIANT(&nd);
  820                 NDFREE(&nd, NDF_ONLY_PNBUF);
  821                 vp = nd.ni_vp;
  822                 VOP_UNLOCK(vp, 0);
  823                 if (vp->v_type != VREG) {
  824                         (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
  825                         VFS_UNLOCK_GIANT(vfslocked);
  826                         ktrace_exit(td);
  827                         return (EACCES);
  828                 }
  829                 VFS_UNLOCK_GIANT(vfslocked);
  830         }
  831         /*
  832          * Clear all uses of the tracefile.
  833          */
  834         if (ops == KTROP_CLEARFILE) {
  835                 int vrele_count;
  836 
  837                 vrele_count = 0;
  838                 sx_slock(&allproc_lock);
  839                 FOREACH_PROC_IN_SYSTEM(p) {
  840                         PROC_LOCK(p);
  841                         if (p->p_tracevp == vp) {
  842                                 if (ktrcanset(td, p)) {
  843                                         mtx_lock(&ktrace_mtx);
  844                                         ktr_freeproc(p, &cred, NULL);
  845                                         mtx_unlock(&ktrace_mtx);
  846                                         vrele_count++;
  847                                         crfree(cred);
  848                                 } else
  849                                         error = EPERM;
  850                         }
  851                         PROC_UNLOCK(p);
  852                 }
  853                 sx_sunlock(&allproc_lock);
  854                 if (vrele_count > 0) {
  855                         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  856                         while (vrele_count-- > 0)
  857                                 vrele(vp);
  858                         VFS_UNLOCK_GIANT(vfslocked);
  859                 }
  860                 goto done;
  861         }
  862         /*
  863          * do it
  864          */
  865         sx_slock(&proctree_lock);
  866         if (uap->pid < 0) {
  867                 /*
  868                  * by process group
  869                  */
  870                 pg = pgfind(-uap->pid);
  871                 if (pg == NULL) {
  872                         sx_sunlock(&proctree_lock);
  873                         error = ESRCH;
  874                         goto done;
  875                 }
  876                 /*
  877                  * ktrops() may call vrele(). Lock pg_members
  878                  * by the proctree_lock rather than pg_mtx.
  879                  */
  880                 PGRP_UNLOCK(pg);
  881                 nfound = 0;
  882                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  883                         PROC_LOCK(p);
  884                         if (p->p_state == PRS_NEW ||
  885                             p_cansee(td, p) != 0) {
  886                                 PROC_UNLOCK(p); 
  887                                 continue;
  888                         }
  889                         PROC_UNLOCK(p); 
  890                         nfound++;
  891                         if (descend)
  892                                 ret |= ktrsetchildren(td, p, ops, facs, vp);
  893                         else
  894                                 ret |= ktrops(td, p, ops, facs, vp);
  895                 }
  896                 if (nfound == 0) {
  897                         sx_sunlock(&proctree_lock);
  898                         error = ESRCH;
  899                         goto done;
  900                 }
  901         } else {
  902                 /*
  903                  * by pid
  904                  */
  905                 p = pfind(uap->pid);
  906                 if (p == NULL) {
  907                         sx_sunlock(&proctree_lock);
  908                         error = ESRCH;
  909                         goto done;
  910                 }
  911                 error = p_cansee(td, p);
  912                 /*
  913                  * The slock of the proctree lock will keep this process
  914                  * from going away, so unlocking the proc here is ok.
  915                  */
  916                 PROC_UNLOCK(p);
  917                 if (error) {
  918                         sx_sunlock(&proctree_lock);
  919                         goto done;
  920                 }
  921                 if (descend)
  922                         ret |= ktrsetchildren(td, p, ops, facs, vp);
  923                 else
  924                         ret |= ktrops(td, p, ops, facs, vp);
  925         }
  926         sx_sunlock(&proctree_lock);
  927         if (!ret)
  928                 error = EPERM;
  929 done:
  930         if (vp != NULL) {
  931                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  932                 (void) vn_close(vp, FWRITE, td->td_ucred, td);
  933                 VFS_UNLOCK_GIANT(vfslocked);
  934         }
  935         ktrace_exit(td);
  936         return (error);
  937 #else /* !KTRACE */
  938         return (ENOSYS);
  939 #endif /* KTRACE */
  940 }
  941 
  942 /* ARGSUSED */
  943 int
  944 utrace(td, uap)
  945         struct thread *td;
  946         register struct utrace_args *uap;
  947 {
  948 
  949 #ifdef KTRACE
  950         struct ktr_request *req;
  951         void *cp;
  952         int error;
  953 
  954         if (!KTRPOINT(td, KTR_USER))
  955                 return (0);
  956         if (uap->len > KTR_USER_MAXLEN)
  957                 return (EINVAL);
  958         cp = malloc(uap->len, M_KTRACE, M_WAITOK);
  959         error = copyin(uap->addr, cp, uap->len);
  960         if (error) {
  961                 free(cp, M_KTRACE);
  962                 return (error);
  963         }
  964         req = ktr_getrequest(KTR_USER);
  965         if (req == NULL) {
  966                 free(cp, M_KTRACE);
  967                 return (ENOMEM);
  968         }
  969         req->ktr_buffer = cp;
  970         req->ktr_header.ktr_len = uap->len;
  971         ktr_submitrequest(td, req);
  972         return (0);
  973 #else /* !KTRACE */
  974         return (ENOSYS);
  975 #endif /* KTRACE */
  976 }
  977 
  978 #ifdef KTRACE
  979 static int
  980 ktrops(td, p, ops, facs, vp)
  981         struct thread *td;
  982         struct proc *p;
  983         int ops, facs;
  984         struct vnode *vp;
  985 {
  986         struct vnode *tracevp = NULL;
  987         struct ucred *tracecred = NULL;
  988 
  989         PROC_LOCK(p);
  990         if (!ktrcanset(td, p)) {
  991                 PROC_UNLOCK(p);
  992                 return (0);
  993         }
  994         mtx_lock(&ktrace_mtx);
  995         if (ops == KTROP_SET) {
  996                 if (p->p_tracevp != vp) {
  997                         /*
  998                          * if trace file already in use, relinquish below
  999                          */
 1000                         tracevp = p->p_tracevp;
 1001                         VREF(vp);
 1002                         p->p_tracevp = vp;
 1003                 }
 1004                 if (p->p_tracecred != td->td_ucred) {
 1005                         tracecred = p->p_tracecred;
 1006                         p->p_tracecred = crhold(td->td_ucred);
 1007                 }
 1008                 p->p_traceflag |= facs;
 1009                 if (priv_check(td, PRIV_KTRACE) == 0)
 1010                         p->p_traceflag |= KTRFAC_ROOT;
 1011         } else {
 1012                 /* KTROP_CLEAR */
 1013                 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0)
 1014                         /* no more tracing */
 1015                         ktr_freeproc(p, &tracecred, &tracevp);
 1016         }
 1017         mtx_unlock(&ktrace_mtx);
 1018         if ((p->p_traceflag & KTRFAC_MASK) != 0)
 1019                 ktrprocctor_entered(td, p);
 1020         PROC_UNLOCK(p);
 1021         if (tracevp != NULL) {
 1022                 int vfslocked;
 1023 
 1024                 vfslocked = VFS_LOCK_GIANT(tracevp->v_mount);
 1025                 vrele(tracevp);
 1026                 VFS_UNLOCK_GIANT(vfslocked);
 1027         }
 1028         if (tracecred != NULL)
 1029                 crfree(tracecred);
 1030 
 1031         return (1);
 1032 }
 1033 
 1034 static int
 1035 ktrsetchildren(td, top, ops, facs, vp)
 1036         struct thread *td;
 1037         struct proc *top;
 1038         int ops, facs;
 1039         struct vnode *vp;
 1040 {
 1041         register struct proc *p;
 1042         register int ret = 0;
 1043 
 1044         p = top;
 1045         sx_assert(&proctree_lock, SX_LOCKED);
 1046         for (;;) {
 1047                 ret |= ktrops(td, p, ops, facs, vp);
 1048                 /*
 1049                  * If this process has children, descend to them next,
 1050                  * otherwise do any siblings, and if done with this level,
 1051                  * follow back up the tree (but not past top).
 1052                  */
 1053                 if (!LIST_EMPTY(&p->p_children))
 1054                         p = LIST_FIRST(&p->p_children);
 1055                 else for (;;) {
 1056                         if (p == top)
 1057                                 return (ret);
 1058                         if (LIST_NEXT(p, p_sibling)) {
 1059                                 p = LIST_NEXT(p, p_sibling);
 1060                                 break;
 1061                         }
 1062                         p = p->p_pptr;
 1063                 }
 1064         }
 1065         /*NOTREACHED*/
 1066 }
 1067 
 1068 static void
 1069 ktr_writerequest(struct thread *td, struct ktr_request *req)
 1070 {
 1071         struct ktr_header *kth;
 1072         struct vnode *vp;
 1073         struct proc *p;
 1074         struct ucred *cred;
 1075         struct uio auio;
 1076         struct iovec aiov[3];
 1077         struct mount *mp;
 1078         int datalen, buflen, vrele_count;
 1079         int error, vfslocked;
 1080 
 1081         /*
 1082          * We hold the vnode and credential for use in I/O in case ktrace is
 1083          * disabled on the process as we write out the request.
 1084          *
 1085          * XXXRW: This is not ideal: we could end up performing a write after
 1086          * the vnode has been closed.
 1087          */
 1088         mtx_lock(&ktrace_mtx);
 1089         vp = td->td_proc->p_tracevp;
 1090         cred = td->td_proc->p_tracecred;
 1091 
 1092         /*
 1093          * If vp is NULL, the vp has been cleared out from under this
 1094          * request, so just drop it.  Make sure the credential and vnode are
 1095          * in sync: we should have both or neither.
 1096          */
 1097         if (vp == NULL) {
 1098                 KASSERT(cred == NULL, ("ktr_writerequest: cred != NULL"));
 1099                 mtx_unlock(&ktrace_mtx);
 1100                 return;
 1101         }
 1102         VREF(vp);
 1103         KASSERT(cred != NULL, ("ktr_writerequest: cred == NULL"));
 1104         crhold(cred);
 1105         mtx_unlock(&ktrace_mtx);
 1106 
 1107         kth = &req->ktr_header;
 1108         KASSERT(((u_short)kth->ktr_type & ~KTR_DROP) <
 1109             sizeof(data_lengths) / sizeof(data_lengths[0]),
 1110             ("data_lengths array overflow"));
 1111         datalen = data_lengths[(u_short)kth->ktr_type & ~KTR_DROP];
 1112         buflen = kth->ktr_len;
 1113         auio.uio_iov = &aiov[0];
 1114         auio.uio_offset = 0;
 1115         auio.uio_segflg = UIO_SYSSPACE;
 1116         auio.uio_rw = UIO_WRITE;
 1117         aiov[0].iov_base = (caddr_t)kth;
 1118         aiov[0].iov_len = sizeof(struct ktr_header);
 1119         auio.uio_resid = sizeof(struct ktr_header);
 1120         auio.uio_iovcnt = 1;
 1121         auio.uio_td = td;
 1122         if (datalen != 0) {
 1123                 aiov[1].iov_base = (caddr_t)&req->ktr_data;
 1124                 aiov[1].iov_len = datalen;
 1125                 auio.uio_resid += datalen;
 1126                 auio.uio_iovcnt++;
 1127                 kth->ktr_len += datalen;
 1128         }
 1129         if (buflen != 0) {
 1130                 KASSERT(req->ktr_buffer != NULL, ("ktrace: nothing to write"));
 1131                 aiov[auio.uio_iovcnt].iov_base = req->ktr_buffer;
 1132                 aiov[auio.uio_iovcnt].iov_len = buflen;
 1133                 auio.uio_resid += buflen;
 1134                 auio.uio_iovcnt++;
 1135         }
 1136 
 1137         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 1138         vn_start_write(vp, &mp, V_WAIT);
 1139         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 1140 #ifdef MAC
 1141         error = mac_vnode_check_write(cred, NOCRED, vp);
 1142         if (error == 0)
 1143 #endif
 1144                 error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, cred);
 1145         VOP_UNLOCK(vp, 0);
 1146         vn_finished_write(mp);
 1147         crfree(cred);
 1148         if (!error) {
 1149                 vrele(vp);
 1150                 VFS_UNLOCK_GIANT(vfslocked);
 1151                 return;
 1152         }
 1153         VFS_UNLOCK_GIANT(vfslocked);
 1154 
 1155         /*
 1156          * If error encountered, give up tracing on this vnode.  We defer
 1157          * all the vrele()'s on the vnode until after we are finished walking
 1158          * the various lists to avoid needlessly holding locks.
 1159          * NB: at this point we still hold the vnode reference that must
 1160          * not go away as we need the valid vnode to compare with. Thus let
 1161          * vrele_count start at 1 and the reference will be freed
 1162          * by the loop at the end after our last use of vp.
 1163          */
 1164         log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
 1165             error);
 1166         vrele_count = 1;
 1167         /*
 1168          * First, clear this vnode from being used by any processes in the
 1169          * system.
 1170          * XXX - If one process gets an EPERM writing to the vnode, should
 1171          * we really do this?  Other processes might have suitable
 1172          * credentials for the operation.
 1173          */
 1174         cred = NULL;
 1175         sx_slock(&allproc_lock);
 1176         FOREACH_PROC_IN_SYSTEM(p) {
 1177                 PROC_LOCK(p);
 1178                 if (p->p_tracevp == vp) {
 1179                         mtx_lock(&ktrace_mtx);
 1180                         ktr_freeproc(p, &cred, NULL);
 1181                         mtx_unlock(&ktrace_mtx);
 1182                         vrele_count++;
 1183                 }
 1184                 PROC_UNLOCK(p);
 1185                 if (cred != NULL) {
 1186                         crfree(cred);
 1187                         cred = NULL;
 1188                 }
 1189         }
 1190         sx_sunlock(&allproc_lock);
 1191 
 1192         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 1193         while (vrele_count-- > 0)
 1194                 vrele(vp);
 1195         VFS_UNLOCK_GIANT(vfslocked);
 1196 }
 1197 
 1198 /*
 1199  * Return true if caller has permission to set the ktracing state
 1200  * of target.  Essentially, the target can't possess any
 1201  * more permissions than the caller.  KTRFAC_ROOT signifies that
 1202  * root previously set the tracing status on the target process, and
 1203  * so, only root may further change it.
 1204  */
 1205 static int
 1206 ktrcanset(td, targetp)
 1207         struct thread *td;
 1208         struct proc *targetp;
 1209 {
 1210 
 1211         PROC_LOCK_ASSERT(targetp, MA_OWNED);
 1212         if (targetp->p_traceflag & KTRFAC_ROOT &&
 1213             priv_check(td, PRIV_KTRACE))
 1214                 return (0);
 1215 
 1216         if (p_candebug(td, targetp) != 0)
 1217                 return (0);
 1218 
 1219         return (1);
 1220 }
 1221 
 1222 #endif /* KTRACE */

Cache object: ef5bda79a544b7ac817704ab2e202d30


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.