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 /*      $NetBSD: kern_ktrace.c,v 1.112.2.1 2008/04/11 06:35:02 jdc Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  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  * 3. 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.5 (Berkeley) 5/14/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.112.2.1 2008/04/11 06:35:02 jdc Exp $");
   36 
   37 #include "opt_ktrace.h"
   38 #include "opt_compat_mach.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/proc.h>
   43 #include <sys/file.h>
   44 #include <sys/namei.h>
   45 #include <sys/vnode.h>
   46 #include <sys/kernel.h>
   47 #include <sys/kthread.h>
   48 #include <sys/ktrace.h>
   49 #include <sys/malloc.h>
   50 #include <sys/syslog.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/ioctl.h>
   53 #include <sys/callout.h>
   54 #include <sys/kauth.h>
   55 
   56 #include <sys/mount.h>
   57 #include <sys/sa.h>
   58 #include <sys/syscallargs.h>
   59 
   60 #ifdef KTRACE
   61 
   62 /*
   63  * XXX:
   64  *      - need better error reporting?
   65  *      - p->p_tracep access lock.  lock p_lock, lock ktd if !NULL, inc ref.
   66  *      - userland utility to sort ktrace.out by timestamp.
   67  *      - keep minimum information in ktrace_entry when rest of alloc failed.
   68  *      - enlarge ktrace_entry so that small entry won't require additional
   69  *        alloc?
   70  *      - per trace control of configurable parameters.
   71  */
   72 
   73 struct ktrace_entry {
   74         TAILQ_ENTRY(ktrace_entry) kte_list;
   75         struct ktr_header kte_kth;
   76         void *kte_buf;
   77 };
   78 
   79 struct ktr_desc {
   80         TAILQ_ENTRY(ktr_desc) ktd_list;
   81         int ktd_flags;
   82 #define KTDF_WAIT               0x0001
   83 #define KTDF_DONE               0x0002
   84 #define KTDF_BLOCKING           0x0004
   85 #define KTDF_INTERACTIVE        0x0008
   86         int ktd_error;
   87 #define KTDE_ENOMEM             0x0001
   88 #define KTDE_ENOSPC             0x0002
   89         int ktd_errcnt;
   90         int ktd_ref;                    /* # of reference */
   91         int ktd_qcount;                 /* # of entry in the queue */
   92 
   93         /*
   94          * Params to control behaviour.
   95          */
   96         int ktd_delayqcnt;              /* # of entry allowed to delay */
   97         int ktd_wakedelay;              /* delay of wakeup in *tick* */
   98         int ktd_intrwakdl;              /* ditto, but when interactive */
   99 
  100         struct file *ktd_fp;            /* trace output file */
  101         struct proc *ktd_proc;          /* our kernel thread */
  102         TAILQ_HEAD(, ktrace_entry) ktd_queue;
  103         struct callout ktd_wakch;       /* delayed wakeup */
  104         struct simplelock ktd_slock;
  105 };
  106 
  107 static void     ktrinitheader(struct ktr_header *, struct lwp *, int);
  108 static void     ktrwrite(struct ktr_desc *, struct ktrace_entry *);
  109 static int      ktrace_common(struct lwp *, int, int, int, struct file *);
  110 static int      ktrops(struct lwp *, struct proc *, int, int,
  111                     struct ktr_desc *);
  112 static int      ktrsetchildren(struct lwp *, struct proc *, int, int,
  113                     struct ktr_desc *);
  114 static int      ktrcanset(struct lwp *, struct proc *);
  115 static int      ktrsamefile(struct file *, struct file *);
  116 
  117 static struct ktr_desc *
  118                 ktd_lookup(struct file *);
  119 static void     ktdrel(struct ktr_desc *);
  120 static void     ktdref(struct ktr_desc *);
  121 static void     ktraddentry(struct lwp *, struct ktrace_entry *, int);
  122 /* Flags for ktraddentry (3rd arg) */
  123 #define KTA_NOWAIT              0x0000
  124 #define KTA_WAITOK              0x0001
  125 #define KTA_LARGE               0x0002
  126 static void     ktefree(struct ktrace_entry *);
  127 static void     ktd_logerrl(struct ktr_desc *, int);
  128 static void     ktd_logerr(struct proc *, int);
  129 static void     ktrace_thread(void *);
  130 
  131 /*
  132  * Default vaules.
  133  */
  134 #define KTD_MAXENTRY            1000    /* XXX: tune */
  135 #define KTD_TIMEOUT             5       /* XXX: tune */
  136 #define KTD_DELAYQCNT           100     /* XXX: tune */
  137 #define KTD_WAKEDELAY           5000    /* XXX: tune */
  138 #define KTD_INTRWAKDL           100     /* XXX: tune */
  139 
  140 /*
  141  * Patchable variables.
  142  */
  143 int ktd_maxentry = KTD_MAXENTRY;        /* max # of entry in the queue */
  144 int ktd_timeout = KTD_TIMEOUT;          /* timeout in seconds */
  145 int ktd_delayqcnt = KTD_DELAYQCNT;      /* # of entry allowed to delay */
  146 int ktd_wakedelay = KTD_WAKEDELAY;      /* delay of wakeup in *ms* */
  147 int ktd_intrwakdl = KTD_INTRWAKDL;      /* ditto, but when interactive */
  148 
  149 static struct simplelock ktdq_slock = SIMPLELOCK_INITIALIZER;
  150 static TAILQ_HEAD(, ktr_desc) ktdq = TAILQ_HEAD_INITIALIZER(ktdq);
  151 
  152 MALLOC_DEFINE(M_KTRACE, "ktrace", "ktrace data buffer");
  153 POOL_INIT(kte_pool, sizeof(struct ktrace_entry), 0, 0, 0,
  154     "ktepl", &pool_allocator_nointr);
  155 
  156 static inline void
  157 ktd_wakeup(struct ktr_desc *ktd)
  158 {
  159 
  160         callout_stop(&ktd->ktd_wakch);
  161         wakeup(ktd);
  162 }
  163 
  164 static void
  165 ktd_logerrl(struct ktr_desc *ktd, int error)
  166 {
  167 
  168         ktd->ktd_error |= error;
  169         ktd->ktd_errcnt++;
  170 }
  171 
  172 static void
  173 ktd_logerr(struct proc *p, int error)
  174 {
  175         struct ktr_desc *ktd = p->p_tracep;
  176 
  177         if (ktd == NULL)
  178                 return;
  179 
  180         simple_lock(&ktd->ktd_slock);
  181         ktd_logerrl(ktd, error);
  182         simple_unlock(&ktd->ktd_slock);
  183 }
  184 
  185 /*
  186  * Release a reference.  Called with ktd_slock held.
  187  */
  188 void
  189 ktdrel(struct ktr_desc *ktd)
  190 {
  191 
  192         KDASSERT(ktd->ktd_ref != 0);
  193         KASSERT(ktd->ktd_ref > 0);
  194         if (--ktd->ktd_ref <= 0) {
  195                 ktd->ktd_flags |= KTDF_DONE;
  196                 wakeup(ktd);
  197         }
  198         simple_unlock(&ktd->ktd_slock);
  199 }
  200 
  201 void
  202 ktdref(struct ktr_desc *ktd)
  203 {
  204 
  205         simple_lock(&ktd->ktd_slock);
  206         ktd->ktd_ref++;
  207         simple_unlock(&ktd->ktd_slock);
  208 }
  209 
  210 struct ktr_desc *
  211 ktd_lookup(struct file *fp)
  212 {
  213         struct ktr_desc *ktd;
  214 
  215         simple_lock(&ktdq_slock);
  216         for (ktd = TAILQ_FIRST(&ktdq); ktd != NULL;
  217             ktd = TAILQ_NEXT(ktd, ktd_list)) {
  218                 simple_lock(&ktd->ktd_slock);
  219                 if (ktrsamefile(ktd->ktd_fp, fp)) {
  220                         ktd->ktd_ref++;
  221                         simple_unlock(&ktd->ktd_slock);
  222                         break;
  223                 }
  224                 simple_unlock(&ktd->ktd_slock);
  225         }
  226         simple_unlock(&ktdq_slock);
  227         return (ktd);
  228 }
  229 
  230 void
  231 ktraddentry(struct lwp *l, struct ktrace_entry *kte, int flags)
  232 {
  233         struct proc *p = l->l_proc;
  234         struct ktr_desc *ktd;
  235 #ifdef DEBUG
  236         struct timeval t1, t2;
  237 #endif
  238 
  239         if (p->p_traceflag & KTRFAC_TRC_EMUL) {
  240                 /* Add emulation trace before first entry for this process */
  241                 p->p_traceflag &= ~KTRFAC_TRC_EMUL;
  242                 ktremul(l);
  243         }
  244 
  245         /*
  246          * Tracing may be canceled while we were sleeping waiting for
  247          * memory.
  248          */
  249         ktd = p->p_tracep;
  250         if (ktd == NULL)
  251                 goto freekte;
  252 
  253         /*
  254          * Bump reference count so that the object will remain while
  255          * we are here.  Note that the trace is controlled by other
  256          * process.
  257          */
  258         ktdref(ktd);
  259 
  260         simple_lock(&ktd->ktd_slock);
  261         if (ktd->ktd_flags & KTDF_DONE)
  262                 goto relktd;
  263 
  264         if (ktd->ktd_qcount > ktd_maxentry) {
  265                 ktd_logerrl(ktd, KTDE_ENOSPC);
  266                 goto relktd;
  267         }
  268         TAILQ_INSERT_TAIL(&ktd->ktd_queue, kte, kte_list);
  269         ktd->ktd_qcount++;
  270         if (ktd->ktd_flags & KTDF_BLOCKING)
  271                 goto skip_sync;
  272 
  273         if (flags & KTA_WAITOK &&
  274             (/* flags & KTA_LARGE */0 || ktd->ktd_flags & KTDF_WAIT ||
  275             ktd->ktd_qcount > ktd_maxentry >> 1))
  276                 /*
  277                  * Sync with writer thread since we're requesting rather
  278                  * big one or many requests are pending.
  279                  */
  280                 do {
  281                         ktd->ktd_flags |= KTDF_WAIT;
  282                         ktd_wakeup(ktd);
  283 #ifdef DEBUG
  284                         getmicrouptime(&t1);
  285 #endif
  286                         if (ltsleep(&ktd->ktd_flags, PWAIT, "ktrsync",
  287                             ktd_timeout * hz, &ktd->ktd_slock) != 0) {
  288                                 ktd->ktd_flags |= KTDF_BLOCKING;
  289                                 /*
  290                                  * Maybe the writer thread is blocking
  291                                  * completely for some reason, but
  292                                  * don't stop target process forever.
  293                                  */
  294                                 log(LOG_NOTICE, "ktrace timeout\n");
  295                                 break;
  296                         }
  297 #ifdef DEBUG
  298                         getmicrouptime(&t2);
  299                         timersub(&t2, &t1, &t2);
  300                         if (t2.tv_sec > 0)
  301                                 log(LOG_NOTICE,
  302                                     "ktrace long wait: %ld.%06ld\n",
  303                                     t2.tv_sec, t2.tv_usec);
  304 #endif
  305                 } while (p->p_tracep == ktd &&
  306                     (ktd->ktd_flags & (KTDF_WAIT | KTDF_DONE)) == KTDF_WAIT);
  307         else {
  308                 /* Schedule delayed wakeup */
  309                 if (ktd->ktd_qcount > ktd->ktd_delayqcnt)
  310                         ktd_wakeup(ktd);        /* Wakeup now */
  311                 else if (!callout_pending(&ktd->ktd_wakch))
  312                         callout_reset(&ktd->ktd_wakch,
  313                             ktd->ktd_flags & KTDF_INTERACTIVE ?
  314                             ktd->ktd_intrwakdl : ktd->ktd_wakedelay,
  315                             (void (*)(void *))wakeup, ktd);
  316         }
  317 
  318 skip_sync:
  319         ktdrel(ktd);
  320         return;
  321 
  322 relktd:
  323         ktdrel(ktd);
  324 
  325 freekte:
  326         ktefree(kte);
  327 }
  328 
  329 void
  330 ktefree(struct ktrace_entry *kte)
  331 {
  332 
  333         if (kte->kte_buf != NULL)
  334                 free(kte->kte_buf, M_KTRACE);
  335         pool_put(&kte_pool, kte);
  336 }
  337 
  338 /*
  339  * "deep" compare of two files for the purposes of clearing a trace.
  340  * Returns true if they're the same open file, or if they point at the
  341  * same underlying vnode/socket.
  342  */
  343 
  344 int
  345 ktrsamefile(struct file *f1, struct file *f2)
  346 {
  347 
  348         return ((f1 == f2) ||
  349             ((f1 != NULL) && (f2 != NULL) &&
  350                 (f1->f_type == f2->f_type) &&
  351                 (f1->f_data == f2->f_data)));
  352 }
  353 
  354 void
  355 ktrderef(struct proc *p)
  356 {
  357         struct ktr_desc *ktd = p->p_tracep;
  358 
  359         p->p_traceflag = 0;
  360         if (ktd == NULL)
  361                 return;
  362         p->p_tracep = NULL;
  363 
  364         simple_lock(&ktd->ktd_slock);
  365         wakeup(&ktd->ktd_flags);
  366         ktdrel(ktd);
  367 }
  368 
  369 void
  370 ktradref(struct proc *p)
  371 {
  372         struct ktr_desc *ktd = p->p_tracep;
  373 
  374         ktdref(ktd);
  375 }
  376 
  377 void
  378 ktrinitheader(struct ktr_header *kth, struct lwp *l, int type)
  379 {
  380         struct proc *p = l->l_proc;
  381 
  382         (void)memset(kth, 0, sizeof(*kth));
  383         kth->ktr_type = type;
  384         kth->ktr_pid = p->p_pid;
  385         memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
  386 
  387         kth->ktr_version = KTRFAC_VERSION(p->p_traceflag);
  388 
  389         switch (KTRFAC_VERSION(p->p_traceflag)) {
  390         case 0:
  391                 /* This is the original format */
  392                 microtime(&kth->ktr_tv);
  393                 break;
  394         case 1:
  395                 kth->ktr_lid = l->l_lid;
  396                 nanotime(&kth->ktr_time);
  397                 break;
  398         default:
  399                 break;
  400         }
  401 }
  402 
  403 void
  404 ktrsyscall(struct lwp *l, register_t code, register_t realcode,
  405     const struct sysent *callp, register_t args[])
  406 {
  407         struct proc *p = l->l_proc;
  408         struct ktrace_entry *kte;
  409         struct ktr_header *kth;
  410         struct ktr_syscall *ktp;
  411         register_t *argp;
  412         int argsize;
  413         size_t len;
  414         u_int i;
  415 
  416         if (callp == NULL)
  417                 callp = p->p_emul->e_sysent;
  418 
  419         argsize = callp[code].sy_argsize;
  420 #ifdef _LP64
  421         if (p->p_flag & P_32)
  422                 argsize = argsize << 1;
  423 #endif
  424         len = sizeof(struct ktr_syscall) + argsize;
  425 
  426         p->p_traceflag |= KTRFAC_ACTIVE;
  427         kte = pool_get(&kte_pool, PR_WAITOK);
  428         kth = &kte->kte_kth;
  429         ktrinitheader(kth, l, KTR_SYSCALL);
  430 
  431         ktp = malloc(len, M_KTRACE, M_WAITOK);
  432         ktp->ktr_code = realcode;
  433         ktp->ktr_argsize = argsize;
  434         argp = (register_t *)(ktp + 1);
  435         for (i = 0; i < (argsize / sizeof(*argp)); i++)
  436                 *argp++ = args[i];
  437         kth->ktr_len = len;
  438         kte->kte_buf = ktp;
  439 
  440         ktraddentry(l, kte, KTA_WAITOK);
  441         p->p_traceflag &= ~KTRFAC_ACTIVE;
  442 }
  443 
  444 void
  445 ktrsysret(struct lwp *l, register_t code, int error, register_t *retval)
  446 {
  447         struct proc *p = l->l_proc;
  448         struct ktrace_entry *kte;
  449         struct ktr_header *kth;
  450         struct ktr_sysret *ktp;
  451 
  452         p->p_traceflag |= KTRFAC_ACTIVE;
  453         kte = pool_get(&kte_pool, PR_WAITOK);
  454         kth = &kte->kte_kth;
  455         ktrinitheader(kth, l, KTR_SYSRET);
  456 
  457         ktp = malloc(sizeof(struct ktr_sysret), M_KTRACE, M_WAITOK);
  458         ktp->ktr_code = code;
  459         ktp->ktr_eosys = 0;                     /* XXX unused */
  460         ktp->ktr_error = error;
  461         ktp->ktr_retval = retval ? retval[0] : 0;
  462         ktp->ktr_retval_1 = retval ? retval[1] : 0;
  463 
  464         kth->ktr_len = sizeof(struct ktr_sysret);
  465         kte->kte_buf = ktp;
  466 
  467         ktraddentry(l, kte, KTA_WAITOK);
  468         p->p_traceflag &= ~KTRFAC_ACTIVE;
  469 }
  470 
  471 /*
  472  * XXX: ndp->ni_pathlen should be passed.
  473  */
  474 void
  475 ktrnamei(struct lwp *l, char *path)
  476 {
  477 
  478         ktrkmem(l, KTR_NAMEI, path, strlen(path));
  479 }
  480 
  481 void
  482 ktremul(struct lwp *l)
  483 {
  484         const char *emul = l->l_proc->p_emul->e_name;
  485 
  486         ktrkmem(l, KTR_EMUL, emul, strlen(emul));
  487 }
  488 
  489 void
  490 ktrkmem(struct lwp *l, int type, const void *bf, size_t len)
  491 {
  492         struct proc *p = l->l_proc;
  493         struct ktrace_entry *kte;
  494         struct ktr_header *kth;
  495 
  496         p->p_traceflag |= KTRFAC_ACTIVE;
  497         kte = pool_get(&kte_pool, PR_WAITOK);
  498         kth = &kte->kte_kth;
  499         ktrinitheader(kth, l, type);
  500 
  501         kth->ktr_len = len;
  502         kte->kte_buf = malloc(len, M_KTRACE, M_WAITOK);
  503         memcpy(kte->kte_buf, bf, len);
  504 
  505         ktraddentry(l, kte, KTA_WAITOK);
  506         p->p_traceflag &= ~KTRFAC_ACTIVE;
  507 }
  508 
  509 void
  510 ktrgenio(struct lwp *l, int fd, enum uio_rw rw, struct iovec *iov,
  511     int len, int error)
  512 {
  513         struct proc *p = l->l_proc;
  514         struct ktrace_entry *kte;
  515         struct ktr_header *kth;
  516         struct ktr_genio *ktp;
  517         int resid = len, cnt;
  518         caddr_t cp;
  519         int buflen;
  520 
  521         if (error)
  522                 return;
  523 
  524         p->p_traceflag |= KTRFAC_ACTIVE;
  525 
  526 next:
  527         buflen = min(PAGE_SIZE, resid + sizeof(struct ktr_genio));
  528 
  529         kte = pool_get(&kte_pool, PR_WAITOK);
  530         kth = &kte->kte_kth;
  531         ktrinitheader(kth, l, KTR_GENIO);
  532 
  533         ktp = malloc(buflen, M_KTRACE, M_WAITOK);
  534         ktp->ktr_fd = fd;
  535         ktp->ktr_rw = rw;
  536 
  537         kte->kte_buf = ktp;
  538 
  539         cp = (caddr_t)(ktp + 1);
  540         buflen -= sizeof(struct ktr_genio);
  541         kth->ktr_len = sizeof(struct ktr_genio);
  542 
  543         while (buflen > 0) {
  544                 cnt = min(iov->iov_len, buflen);
  545                 if (copyin(iov->iov_base, cp, cnt) != 0)
  546                         goto out;
  547                 kth->ktr_len += cnt;
  548                 buflen -= cnt;
  549                 resid -= cnt;
  550                 iov->iov_len -= cnt;
  551                 if (iov->iov_len == 0)
  552                         iov++;
  553                 else
  554                         iov->iov_base = (caddr_t)iov->iov_base + cnt;
  555         }
  556 
  557         /*
  558          * Don't push so many entry at once.  It will cause kmem map
  559          * shortage.
  560          */
  561         ktraddentry(l, kte, KTA_WAITOK | KTA_LARGE);
  562         if (resid > 0) {
  563 #if 0 /* XXX NJWLWP */
  564                 KDASSERT(p->p_cpu != NULL);
  565                 KDASSERT(p->p_cpu == curcpu());
  566 #endif
  567                 /* XXX NJWLWP */
  568                 if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
  569                         preempt(1);
  570 
  571                 goto next;
  572         }
  573 
  574         p->p_traceflag &= ~KTRFAC_ACTIVE;
  575         return;
  576 
  577 out:
  578         ktefree(kte);
  579         p->p_traceflag &= ~KTRFAC_ACTIVE;
  580 }
  581 
  582 void
  583 ktrpsig(struct lwp *l, int sig, sig_t action, const sigset_t *mask,
  584     const ksiginfo_t *ksi)
  585 {
  586         struct proc *p = l->l_proc;
  587         struct ktrace_entry *kte;
  588         struct ktr_header *kth;
  589         struct {
  590                 struct ktr_psig kp;
  591                 siginfo_t       si;
  592         } *kbuf;
  593 
  594         p->p_traceflag |= KTRFAC_ACTIVE;
  595         kte = pool_get(&kte_pool, PR_WAITOK);
  596         kth = &kte->kte_kth;
  597         ktrinitheader(kth, l, KTR_PSIG);
  598 
  599         kbuf = malloc(sizeof(*kbuf), M_KTRACE, M_WAITOK);
  600         kbuf->kp.signo = (char)sig;
  601         kbuf->kp.action = action;
  602         kbuf->kp.mask = *mask;
  603         kte->kte_buf = kbuf;
  604         if (ksi) {
  605                 kbuf->kp.code = KSI_TRAPCODE(ksi);
  606                 (void)memset(&kbuf->si, 0, sizeof(kbuf->si));
  607                 kbuf->si._info = ksi->ksi_info;
  608                 kth->ktr_len = sizeof(*kbuf);
  609         } else {
  610                 kbuf->kp.code = 0;
  611                 kth->ktr_len = sizeof(struct ktr_psig);
  612         }
  613 
  614         ktraddentry(l, kte, KTA_WAITOK);
  615         p->p_traceflag &= ~KTRFAC_ACTIVE;
  616 }
  617 
  618 void
  619 ktrcsw(struct lwp *l, int out, int user)
  620 {
  621         struct proc *p = l->l_proc;
  622         struct ktrace_entry *kte;
  623         struct ktr_header *kth;
  624         struct ktr_csw *kc;
  625 
  626         p->p_traceflag |= KTRFAC_ACTIVE;
  627 
  628         /*
  629          * We can't sleep if we're already going to sleep (if original
  630          * condition is met during sleep, we hang up).
  631          */
  632         kte = pool_get(&kte_pool, out ? PR_NOWAIT : PR_WAITOK);
  633         if (kte == NULL) {
  634                 ktd_logerr(p, KTDE_ENOMEM);
  635                 goto out;
  636         }
  637         kth = &kte->kte_kth;
  638         ktrinitheader(kth, l, KTR_CSW);
  639 
  640         kc = malloc(sizeof(struct ktr_csw), M_KTRACE,
  641             out ? M_NOWAIT : M_WAITOK);
  642         if (kc == NULL) {
  643                 ktd_logerr(p, KTDE_ENOMEM);
  644                 goto free_kte;
  645         }
  646         kc->out = out;
  647         kc->user = user;
  648         kth->ktr_len = sizeof(struct ktr_csw);
  649         kte->kte_buf = kc;
  650 
  651         ktraddentry(l, kte, out ? KTA_NOWAIT : KTA_WAITOK);
  652         p->p_traceflag &= ~KTRFAC_ACTIVE;
  653         return;
  654 
  655 free_kte:
  656         pool_put(&kte_pool, kte);
  657 out:
  658         p->p_traceflag &= ~KTRFAC_ACTIVE;
  659 }
  660 
  661 int
  662 ktruser(struct lwp *l, const char *id, void *addr, size_t len, int ustr)
  663 {
  664         struct proc *p = l->l_proc;
  665         struct ktrace_entry *kte;
  666         struct ktr_header *kth;
  667         struct ktr_user *ktp;
  668         caddr_t user_dta;
  669         int error;
  670 
  671         if (len > KTR_USER_MAXLEN)
  672                 return ENOSPC;
  673 
  674         p->p_traceflag |= KTRFAC_ACTIVE;
  675         kte = pool_get(&kte_pool, PR_WAITOK);
  676         kth = &kte->kte_kth;
  677         ktrinitheader(kth, l, KTR_USER);
  678 
  679         ktp = malloc(sizeof(struct ktr_user) + len, M_KTRACE, M_WAITOK);
  680         if (ustr) {
  681                 if (copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL) != 0)
  682                         ktp->ktr_id[0] = '\0';
  683         } else
  684                 strncpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
  685         ktp->ktr_id[KTR_USER_MAXIDLEN-1] = '\0';
  686 
  687         user_dta = (caddr_t)(ktp + 1);
  688         if ((error = copyin(addr, (void *)user_dta, len)) != 0)
  689                 len = 0;
  690 
  691         kth->ktr_len = sizeof(struct ktr_user) + len;
  692         kte->kte_buf = ktp;
  693 
  694         ktraddentry(l, kte, KTA_WAITOK);
  695         p->p_traceflag &= ~KTRFAC_ACTIVE;
  696         return error;
  697 }
  698 
  699 void
  700 ktrmmsg(struct lwp *l, const void *msgh, size_t size)
  701 {
  702         ktrkmem(l, KTR_MMSG, msgh, size);
  703 }
  704 
  705 void
  706 ktrmool(struct lwp *l, const void *kaddr, size_t size, const void *uaddr)
  707 {
  708         struct proc *p = l->l_proc;
  709         struct ktrace_entry *kte;
  710         struct ktr_header *kth;
  711         struct ktr_mool *kp;
  712         struct ktr_mool *bf;
  713 
  714         p->p_traceflag |= KTRFAC_ACTIVE;
  715         kte = pool_get(&kte_pool, PR_WAITOK);
  716         kth = &kte->kte_kth;
  717         ktrinitheader(kth, l, KTR_MOOL);
  718 
  719         kp = malloc(size + sizeof(*kp), M_KTRACE, M_WAITOK);
  720         kp->uaddr = uaddr;
  721         kp->size = size;
  722         bf = kp + 1; /* Skip uaddr and size */
  723         (void)memcpy(bf, kaddr, size);
  724 
  725         kth->ktr_len = size + sizeof(*kp);
  726         kte->kte_buf = kp;
  727 
  728         ktraddentry(l, kte, KTA_WAITOK);
  729         p->p_traceflag &= ~KTRFAC_ACTIVE;
  730 }
  731 
  732 void
  733 ktrsaupcall(struct lwp *l, int type, int nevent, int nint, void *sas,
  734     void *ap, void *ksas)
  735 {
  736         struct proc *p = l->l_proc;
  737         struct ktrace_entry *kte;
  738         struct ktr_header *kth;
  739         struct ktr_saupcall *ktp;
  740         size_t len;
  741         struct sa_t **sapp;
  742         int i;
  743 
  744         p->p_traceflag |= KTRFAC_ACTIVE;
  745         kte = pool_get(&kte_pool, PR_WAITOK);
  746         kth = &kte->kte_kth;
  747         ktrinitheader(kth, l, KTR_SAUPCALL);
  748 
  749         len = sizeof(struct ktr_saupcall);
  750         ktp = malloc(len + sizeof(struct sa_t) * (nevent + nint + 1), M_KTRACE,
  751             M_WAITOK);
  752 
  753         ktp->ktr_type = type;
  754         ktp->ktr_nevent = nevent;
  755         ktp->ktr_nint = nint;
  756         ktp->ktr_sas = sas;
  757         ktp->ktr_ap = ap;
  758         /*
  759          *  Copy the sa_t's
  760          */
  761         sapp = (struct sa_t **) ksas;
  762 
  763         for (i = nevent + nint; i >= 0; i--) {
  764                 memcpy((char *)ktp + len, *sapp, sizeof(struct sa_t));
  765                 len += sizeof(struct sa_t);
  766                 sapp++;
  767         }
  768 
  769         kth->ktr_len = len;
  770         kte->kte_buf = ktp;
  771 
  772         ktraddentry(l, kte, KTA_WAITOK);
  773         p->p_traceflag &= ~KTRFAC_ACTIVE;
  774 }
  775 
  776 void
  777 ktrmib(l, name, namelen)
  778         struct lwp *l;
  779         const int *name;
  780         u_int namelen;
  781 {
  782         struct proc *p = l->l_proc;
  783         struct ktrace_entry *kte;
  784         struct ktr_header *kth;
  785         int *namep;
  786         size_t size;
  787 
  788         p->p_traceflag |= KTRFAC_ACTIVE;
  789         kte = pool_get(&kte_pool, PR_WAITOK);
  790         kth = &kte->kte_kth;
  791         ktrinitheader(kth, l, KTR_MIB);
  792 
  793         size = namelen * sizeof(*name);
  794         namep = malloc(size, M_KTRACE, M_WAITOK);
  795         (void)memcpy(namep, name, namelen * sizeof(*name));
  796 
  797         kth->ktr_len = size;
  798         kte->kte_buf = namep;
  799 
  800         ktraddentry(l, kte, KTA_WAITOK);
  801         p->p_traceflag &= ~KTRFAC_ACTIVE;
  802 }
  803 
  804 /* Interface and common routines */
  805 
  806 int
  807 ktrace_common(struct lwp *curl, int ops, int facs, int pid, struct file *fp)
  808 {
  809         struct proc *curp;
  810         struct proc *p;
  811         struct pgrp *pg;
  812         struct ktr_desc *ktd = NULL;
  813         int ret = 0;
  814         int error = 0;
  815         int descend;
  816 
  817         curp = curl->l_proc;
  818         curp->p_traceflag |= KTRFAC_ACTIVE;
  819         descend = ops & KTRFLAG_DESCEND;
  820         facs = facs & ~((unsigned) KTRFAC_ROOT);
  821 
  822         switch (KTROP(ops)) {
  823 
  824         case KTROP_CLEARFILE:
  825                 /*
  826                  * Clear all uses of the tracefile
  827                  */
  828 
  829                 ktd = ktd_lookup(fp);
  830                 if (ktd == NULL)
  831                         goto done;
  832 
  833                 proclist_lock_read();
  834                 PROCLIST_FOREACH(p, &allproc) {
  835                         if (p->p_tracep == ktd) {
  836                                 if (ktrcanset(curl, p))
  837                                         ktrderef(p);
  838                                 else
  839                                         error = EPERM;
  840                         }
  841                 }
  842                 proclist_unlock_read();
  843                 goto done;
  844 
  845         case KTROP_SET:
  846                 ktd = ktd_lookup(fp);
  847                 if (ktd == NULL) {
  848                         ktd = malloc(sizeof(struct ktr_desc),
  849                             M_KTRACE, M_WAITOK);
  850                         TAILQ_INIT(&ktd->ktd_queue);
  851                         simple_lock_init(&ktd->ktd_slock);
  852                         callout_init(&ktd->ktd_wakch);
  853                         ktd->ktd_flags = ktd->ktd_qcount =
  854                             ktd->ktd_error = ktd->ktd_errcnt = 0;
  855                         ktd->ktd_ref = 1;
  856                         ktd->ktd_delayqcnt = ktd_delayqcnt;
  857                         ktd->ktd_wakedelay = mstohz(ktd_wakedelay);
  858                         ktd->ktd_intrwakdl = mstohz(ktd_intrwakdl);
  859                         /*
  860                          * XXX: not correct.  needs an way to detect
  861                          * whether ktruss or ktrace.
  862                          */
  863                         if (fp->f_type == DTYPE_PIPE)
  864                                 ktd->ktd_flags |= KTDF_INTERACTIVE;
  865 
  866                         error = kthread_create1(ktrace_thread, ktd,
  867                             &ktd->ktd_proc, "ktr %p", ktd);
  868                         if (error != 0) {
  869                                 free(ktd, M_KTRACE);
  870                                 goto done;
  871                         }
  872 
  873                         simple_lock(&fp->f_slock);
  874                         fp->f_count++;
  875                         simple_unlock(&fp->f_slock);
  876                         ktd->ktd_fp = fp;
  877 
  878                         simple_lock(&ktdq_slock);
  879                         TAILQ_INSERT_TAIL(&ktdq, ktd, ktd_list);
  880                         simple_unlock(&ktdq_slock);
  881                 }
  882                 break;
  883 
  884         case KTROP_CLEAR:
  885                 break;
  886         }
  887 
  888         /*
  889          * need something to (un)trace (XXX - why is this here?)
  890          */
  891         if (!facs) {
  892                 error = EINVAL;
  893                 goto done;
  894         }
  895 
  896         /*
  897          * do it
  898          */
  899         if (pid < 0) {
  900                 /*
  901                  * by process group
  902                  */
  903                 pg = pg_find(-pid, PFIND_UNLOCK_FAIL);
  904                 if (pg == NULL) {
  905                         error = ESRCH;
  906                         goto done;
  907                 }
  908                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  909                         if (descend)
  910                                 ret |= ktrsetchildren(curl, p, ops, facs, ktd);
  911                         else
  912                                 ret |= ktrops(curl, p, ops, facs, ktd);
  913                 }
  914 
  915         } else {
  916                 /*
  917                  * by pid
  918                  */
  919                 p = p_find(pid, PFIND_UNLOCK_FAIL);
  920                 if (p == NULL) {
  921                         error = ESRCH;
  922                         goto done;
  923                 }
  924                 if (descend)
  925                         ret |= ktrsetchildren(curl, p, ops, facs, ktd);
  926                 else
  927                         ret |= ktrops(curl, p, ops, facs, ktd);
  928         }
  929         proclist_unlock_read(); /* taken by p{g}_find */
  930         if (!ret)
  931                 error = EPERM;
  932 done:
  933         if (ktd != NULL) {
  934                 if (error != 0) {
  935                         /*
  936                          * Wakeup the thread so that it can be die if we
  937                          * can't trace any process.
  938                          */
  939                         ktd_wakeup(ktd);
  940                 }
  941                 if (KTROP(ops) == KTROP_SET || KTROP(ops) == KTROP_CLEARFILE) {
  942                             simple_lock(&ktd->ktd_slock);
  943                             ktdrel(ktd);
  944                 }
  945         }
  946         curp->p_traceflag &= ~KTRFAC_ACTIVE;
  947         return (error);
  948 }
  949 
  950 /*
  951  * fktrace system call
  952  */
  953 /* ARGSUSED */
  954 int
  955 sys_fktrace(struct lwp *l, void *v, register_t *retval)
  956 {
  957         struct sys_fktrace_args /* {
  958                 syscallarg(int) fd;
  959                 syscallarg(int) ops;
  960                 syscallarg(int) facs;
  961                 syscallarg(int) pid;
  962         } */ *uap = v;
  963         struct file *fp = NULL;
  964         struct filedesc *fdp = l->l_proc->p_fd;
  965         int error;
  966 
  967         fdp = l->l_proc->p_fd;
  968         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
  969                 return (EBADF);
  970 
  971         FILE_USE(fp);
  972 
  973         if ((fp->f_flag & FWRITE) == 0)
  974                 error = EBADF;
  975         else
  976                 error = ktrace_common(l, SCARG(uap, ops),
  977                     SCARG(uap, facs), SCARG(uap, pid), fp);
  978 
  979         FILE_UNUSE(fp, l);
  980 
  981         return error;
  982 }
  983 
  984 /*
  985  * ktrace system call
  986  */
  987 /* ARGSUSED */
  988 int
  989 sys_ktrace(struct lwp *l, void *v, register_t *retval)
  990 {
  991         struct sys_ktrace_args /* {
  992                 syscallarg(const char *) fname;
  993                 syscallarg(int) ops;
  994                 syscallarg(int) facs;
  995                 syscallarg(int) pid;
  996         } */ *uap = v;
  997         struct proc *curp = l->l_proc;
  998         struct vnode *vp = NULL;
  999         struct file *fp = NULL;
 1000         struct nameidata nd;
 1001         int error = 0;
 1002         int fd;
 1003 
 1004         curp->p_traceflag |= KTRFAC_ACTIVE;
 1005         if (KTROP(SCARG(uap, ops)) != KTROP_CLEAR) {
 1006                 /*
 1007                  * an operation which requires a file argument.
 1008                  */
 1009                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
 1010                     l);
 1011                 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
 1012                         curp->p_traceflag &= ~KTRFAC_ACTIVE;
 1013                         return (error);
 1014                 }
 1015                 vp = nd.ni_vp;
 1016                 VOP_UNLOCK(vp, 0);
 1017                 if (vp->v_type != VREG) {
 1018                         (void) vn_close(vp, FREAD|FWRITE, l->l_cred, l);
 1019                         curp->p_traceflag &= ~KTRFAC_ACTIVE;
 1020                         return (EACCES);
 1021                 }
 1022                 /*
 1023                  * XXX This uses up a file descriptor slot in the
 1024                  * tracing process for the duration of this syscall.
 1025                  * This is not expected to be a problem.  If
 1026                  * falloc(NULL, ...) DTRT we could skip that part, but
 1027                  * that would require changing its interface to allow
 1028                  * the caller to pass in a ucred..
 1029                  *
 1030                  * This will FILE_USE the fp it returns, if any.
 1031                  * Keep it in use until we return.
 1032                  */
 1033                 if ((error = falloc(l, &fp, &fd)) != 0)
 1034                         goto done;
 1035 
 1036                 fp->f_flag = FWRITE;
 1037                 fp->f_type = DTYPE_VNODE;
 1038                 fp->f_ops = &vnops;
 1039                 fp->f_data = (caddr_t)vp;
 1040                 FILE_SET_MATURE(fp);
 1041                 vp = NULL;
 1042         }
 1043         error = ktrace_common(l, SCARG(uap, ops), SCARG(uap, facs),
 1044             SCARG(uap, pid), fp);
 1045 done:
 1046         if (vp != NULL)
 1047                 (void) vn_close(vp, FWRITE, l->l_cred, l);
 1048         if (fp != NULL) {
 1049                 FILE_UNUSE(fp, l);      /* release file */
 1050                 fdrelease(l, fd);       /* release fd table slot */
 1051         }
 1052         return (error);
 1053 }
 1054 
 1055 int
 1056 ktrops(struct lwp *curl, struct proc *p, int ops, int facs,
 1057     struct ktr_desc *ktd)
 1058 {
 1059         int vers = ops & KTRFAC_VER_MASK;
 1060 
 1061         if (!ktrcanset(curl, p))
 1062                 return (0);
 1063 
 1064         switch (vers) {
 1065         case KTRFACv0:
 1066         case KTRFACv1:
 1067                 break;
 1068         default:
 1069                 return EINVAL;
 1070         }
 1071 
 1072         if (KTROP(ops) == KTROP_SET) {
 1073                 if (p->p_tracep != ktd) {
 1074                         /*
 1075                          * if trace file already in use, relinquish
 1076                          */
 1077                         ktrderef(p);
 1078                         p->p_tracep = ktd;
 1079                         ktradref(p);
 1080                 }
 1081                 p->p_traceflag |= facs;
 1082                 if (kauth_cred_geteuid(curl->l_cred) == 0)
 1083                         p->p_traceflag |= KTRFAC_ROOT;
 1084         } else {
 1085                 /* KTROP_CLEAR */
 1086                 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
 1087                         /* no more tracing */
 1088                         ktrderef(p);
 1089                 }
 1090         }
 1091 
 1092         if (p->p_traceflag)
 1093                 p->p_traceflag |= vers;
 1094         /*
 1095          * Emit an emulation record, every time there is a ktrace
 1096          * change/attach request.
 1097          */
 1098         if (KTRPOINT(p, KTR_EMUL))
 1099                 p->p_traceflag |= KTRFAC_TRC_EMUL;
 1100 #ifdef __HAVE_SYSCALL_INTERN
 1101         (*p->p_emul->e_syscall_intern)(p);
 1102 #endif
 1103 
 1104         return (1);
 1105 }
 1106 
 1107 int
 1108 ktrsetchildren(struct lwp *curl, struct proc *top, int ops, int facs,
 1109     struct ktr_desc *ktd)
 1110 {
 1111         struct proc *p;
 1112         int ret = 0;
 1113 
 1114         p = top;
 1115         for (;;) {
 1116                 ret |= ktrops(curl, p, ops, facs, ktd);
 1117                 /*
 1118                  * If this process has children, descend to them next,
 1119                  * otherwise do any siblings, and if done with this level,
 1120                  * follow back up the tree (but not past top).
 1121                  */
 1122                 if (LIST_FIRST(&p->p_children) != NULL) {
 1123                         p = LIST_FIRST(&p->p_children);
 1124                         continue;
 1125                 }
 1126                 for (;;) {
 1127                         if (p == top)
 1128                                 return (ret);
 1129                         if (LIST_NEXT(p, p_sibling) != NULL) {
 1130                                 p = LIST_NEXT(p, p_sibling);
 1131                                 break;
 1132                         }
 1133                         p = p->p_pptr;
 1134                 }
 1135         }
 1136         /*NOTREACHED*/
 1137 }
 1138 
 1139 void
 1140 ktrwrite(struct ktr_desc *ktd, struct ktrace_entry *kte)
 1141 {
 1142         struct uio auio;
 1143         struct iovec aiov[64], *iov;
 1144         struct ktrace_entry *top = kte;
 1145         struct ktr_header *kth;
 1146         struct file *fp = ktd->ktd_fp;
 1147         struct proc *p;
 1148         int error;
 1149 next:
 1150         auio.uio_iov = iov = &aiov[0];
 1151         auio.uio_offset = 0;
 1152         auio.uio_rw = UIO_WRITE;
 1153         auio.uio_resid = 0;
 1154         auio.uio_iovcnt = 0;
 1155         UIO_SETUP_SYSSPACE(&auio);
 1156         do {
 1157                 kth = &kte->kte_kth;
 1158 
 1159                 if (kth->ktr_version == 0) {
 1160                         /*
 1161                          * Convert back to the old format fields
 1162                          */
 1163                         TIMESPEC_TO_TIMEVAL(&kth->ktr_tv, &kth->ktr_time);
 1164                         kth->ktr_unused = NULL;
 1165                 }
 1166                 iov->iov_base = (caddr_t)kth;
 1167                 iov++->iov_len = sizeof(struct ktr_header);
 1168                 auio.uio_resid += sizeof(struct ktr_header);
 1169                 auio.uio_iovcnt++;
 1170                 if (kth->ktr_len > 0) {
 1171                         iov->iov_base = kte->kte_buf;
 1172                         iov++->iov_len = kth->ktr_len;
 1173                         auio.uio_resid += kth->ktr_len;
 1174                         auio.uio_iovcnt++;
 1175                 }
 1176         } while ((kte = TAILQ_NEXT(kte, kte_list)) != NULL &&
 1177             auio.uio_iovcnt < sizeof(aiov) / sizeof(aiov[0]) - 1);
 1178 
 1179 again:
 1180         simple_lock(&fp->f_slock);
 1181         FILE_USE(fp);
 1182         error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
 1183             fp->f_cred, FOF_UPDATE_OFFSET);
 1184         FILE_UNUSE(fp, NULL);
 1185         switch (error) {
 1186 
 1187         case 0:
 1188                 if (auio.uio_resid > 0)
 1189                         goto again;
 1190                 if (kte != NULL)
 1191                         goto next;
 1192                 break;
 1193 
 1194         case EWOULDBLOCK:
 1195                 preempt(1);
 1196                 goto again;
 1197 
 1198         default:
 1199                 /*
 1200                  * If error encountered, give up tracing on this
 1201                  * vnode.  Don't report EPIPE as this can easily
 1202                  * happen with fktrace()/ktruss.
 1203                  */
 1204 #ifndef DEBUG
 1205                 if (error != EPIPE)
 1206 #endif
 1207                         log(LOG_NOTICE,
 1208                             "ktrace write failed, errno %d, tracing stopped\n",
 1209                             error);
 1210                 proclist_lock_read();
 1211                 PROCLIST_FOREACH(p, &allproc) {
 1212                         if (p->p_tracep == ktd)
 1213                                 ktrderef(p);
 1214                 }
 1215                 proclist_unlock_read();
 1216         }
 1217 
 1218         while ((kte = top) != NULL) {
 1219                 top = TAILQ_NEXT(top, kte_list);
 1220                 ktefree(kte);
 1221         }
 1222 }
 1223 
 1224 void
 1225 ktrace_thread(void *arg)
 1226 {
 1227         struct ktr_desc *ktd = arg;
 1228         struct file *fp = ktd->ktd_fp;
 1229         struct ktrace_entry *kte;
 1230         int ktrerr, errcnt;
 1231 
 1232         for (;;) {
 1233                 simple_lock(&ktd->ktd_slock);
 1234                 kte = TAILQ_FIRST(&ktd->ktd_queue);
 1235                 if (kte == NULL) {
 1236                         if (ktd->ktd_flags & KTDF_WAIT) {
 1237                                 ktd->ktd_flags &= ~(KTDF_WAIT | KTDF_BLOCKING);
 1238                                 wakeup(&ktd->ktd_flags);
 1239                         }
 1240                         if (ktd->ktd_ref == 0)
 1241                                 break;
 1242                         ltsleep(ktd, PWAIT | PNORELOCK, "ktrwait", 0,
 1243                             &ktd->ktd_slock);
 1244                         continue;
 1245                 }
 1246                 TAILQ_INIT(&ktd->ktd_queue);
 1247                 ktd->ktd_qcount = 0;
 1248                 ktrerr = ktd->ktd_error;
 1249                 errcnt = ktd->ktd_errcnt;
 1250                 ktd->ktd_error = ktd->ktd_errcnt = 0;
 1251                 simple_unlock(&ktd->ktd_slock);
 1252 
 1253                 if (ktrerr) {
 1254                         log(LOG_NOTICE,
 1255                             "ktrace failed, fp %p, error 0x%x, total %d\n",
 1256                             fp, ktrerr, errcnt);
 1257                 }
 1258                 ktrwrite(ktd, kte);
 1259         }
 1260         simple_unlock(&ktd->ktd_slock);
 1261 
 1262         simple_lock(&ktdq_slock);
 1263         TAILQ_REMOVE(&ktdq, ktd, ktd_list);
 1264         simple_unlock(&ktdq_slock);
 1265 
 1266         simple_lock(&fp->f_slock);
 1267         FILE_USE(fp);
 1268 
 1269         /*
 1270          * ktrace file descriptor can't be watched (are not visible to
 1271          * userspace), so no kqueue stuff here
 1272          * XXX: The above comment is wrong, because the fktrace file
 1273          * descriptor is available in userland.
 1274          */
 1275         closef(fp, NULL);
 1276 
 1277         callout_stop(&ktd->ktd_wakch);
 1278         free(ktd, M_KTRACE);
 1279 
 1280         kthread_exit(0);
 1281 }
 1282 
 1283 /*
 1284  * Return true if caller has permission to set the ktracing state
 1285  * of target.  Essentially, the target can't possess any
 1286  * more permissions than the caller.  KTRFAC_ROOT signifies that
 1287  * root previously set the tracing status on the target process, and
 1288  * so, only root may further change it.
 1289  *
 1290  * TODO: check groups.  use caller effective gid.
 1291  */
 1292 int
 1293 ktrcanset(struct lwp *calll, struct proc *targetp)
 1294 {
 1295         if (kauth_authorize_process(calll->l_cred, KAUTH_PROCESS_CANKTRACE,
 1296             targetp, NULL, NULL, NULL) == 0)
 1297                 return (1);
 1298 
 1299         return (0);
 1300 }
 1301 #endif /* KTRACE */
 1302 
 1303 /*
 1304  * Put user defined entry to ktrace records.
 1305  */
 1306 int
 1307 sys_utrace(struct lwp *l, void *v, register_t *retval)
 1308 {
 1309 #ifdef KTRACE
 1310         struct sys_utrace_args /* {
 1311                 syscallarg(const char *) label;
 1312                 syscallarg(void *) addr;
 1313                 syscallarg(size_t) len;
 1314         } */ *uap = v;
 1315         struct proc *p = l->l_proc;
 1316 
 1317         if (!KTRPOINT(p, KTR_USER))
 1318                 return (0);
 1319 
 1320         return ktruser(l, SCARG(uap, label), SCARG(uap, addr),
 1321             SCARG(uap, len), 1);
 1322 #else /* !KTRACE */
 1323         return ENOSYS;
 1324 #endif /* KTRACE */
 1325 }

Cache object: 9b9a6ac9a30e95539d379c1a9944c151


[ 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.