LCOV - code coverage report
Current view: top level - kern - kern_ktrace.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 348 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: kern_ktrace.c,v 1.99 2018/08/05 14:23:57 beck Exp $   */
       2             : /*      $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $        */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1989, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. Neither the name of the University nor the names of its contributors
      17             :  *    may be used to endorse or promote products derived from this software
      18             :  *    without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      21             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      24             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      26             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      27             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      28             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      29             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      30             :  * SUCH DAMAGE.
      31             :  *
      32             :  *      @(#)kern_ktrace.c       8.2 (Berkeley) 9/23/93
      33             :  */
      34             : 
      35             : #include <sys/param.h>
      36             : #include <sys/systm.h>
      37             : #include <sys/proc.h>
      38             : #include <sys/sched.h>
      39             : #include <sys/fcntl.h>
      40             : #include <sys/namei.h>
      41             : #include <sys/vnode.h>
      42             : #include <sys/lock.h>
      43             : #include <sys/ktrace.h>
      44             : #include <sys/malloc.h>
      45             : #include <sys/syslog.h>
      46             : #include <sys/sysctl.h>
      47             : #include <sys/pledge.h>
      48             : 
      49             : #include <sys/mount.h>
      50             : #include <sys/syscall.h>
      51             : #include <sys/syscallargs.h>
      52             : 
      53             : #include <uvm/uvm_extern.h>
      54             : 
      55             : void    ktrinitheaderraw(struct ktr_header *, uint, pid_t, pid_t);
      56             : void    ktrinitheader(struct ktr_header *, struct proc *, int);
      57             : void    ktrstart(struct proc *, struct vnode *, struct ucred *);
      58             : int     ktrops(struct proc *, struct process *, int, int, struct vnode *,
      59             :             struct ucred *);
      60             : int     ktrsetchildren(struct proc *, struct process *, int, int,
      61             :             struct vnode *, struct ucred *);
      62             : int     ktrwrite(struct proc *, struct ktr_header *, const void *, size_t);
      63             : int     ktrwrite2(struct proc *, struct ktr_header *, const void *, size_t,
      64             :             const void *, size_t);
      65             : int     ktrwriteraw(struct proc *, struct vnode *, struct ucred *,
      66             :             struct ktr_header *, struct iovec *);
      67             : int     ktrcanset(struct proc *, struct process *);
      68             : 
      69             : /*
      70             :  * Clear the trace settings in a correct way (to avoid races).
      71             :  */
      72             : void
      73           0 : ktrcleartrace(struct process *pr)
      74             : {
      75             :         struct vnode *vp;
      76             :         struct ucred *cred;
      77             : 
      78           0 :         if (pr->ps_tracevp != NULL) {
      79             :                 vp = pr->ps_tracevp;
      80           0 :                 cred = pr->ps_tracecred;
      81             : 
      82           0 :                 pr->ps_traceflag = 0;
      83           0 :                 pr->ps_tracevp = NULL;
      84           0 :                 pr->ps_tracecred = NULL;
      85             : 
      86           0 :                 vrele(vp);
      87           0 :                 crfree(cred);
      88           0 :         }
      89           0 : }
      90             : 
      91             : /*
      92             :  * Change the trace setting in a correct way (to avoid races).
      93             :  */
      94             : void
      95           0 : ktrsettrace(struct process *pr, int facs, struct vnode *newvp,
      96             :     struct ucred *newcred)
      97             : {
      98             :         struct vnode *oldvp;
      99             :         struct ucred *oldcred;
     100             : 
     101           0 :         KASSERT(newvp != NULL);
     102           0 :         KASSERT(newcred != NULL);
     103             : 
     104           0 :         pr->ps_traceflag |= facs;
     105             : 
     106             :         /* nothing to change about where the trace goes? */
     107           0 :         if (pr->ps_tracevp == newvp && pr->ps_tracecred == newcred)
     108           0 :                 return; 
     109             : 
     110           0 :         vref(newvp);
     111           0 :         crhold(newcred);
     112             : 
     113           0 :         oldvp = pr->ps_tracevp;
     114           0 :         oldcred = pr->ps_tracecred;
     115             : 
     116           0 :         pr->ps_tracevp = newvp;
     117           0 :         pr->ps_tracecred = newcred;
     118             : 
     119           0 :         if (oldvp != NULL) {
     120           0 :                 vrele(oldvp);
     121           0 :                 crfree(oldcred);
     122           0 :         }
     123           0 : }
     124             : 
     125             : void
     126           0 : ktrinitheaderraw(struct ktr_header *kth, uint type, pid_t pid, pid_t tid)
     127             : {
     128           0 :         memset(kth, 0, sizeof(struct ktr_header));
     129           0 :         kth->ktr_type = type;
     130           0 :         nanotime(&kth->ktr_time);
     131           0 :         kth->ktr_pid = pid;
     132           0 :         kth->ktr_tid = tid;
     133           0 : }
     134             : 
     135             : void
     136           0 : ktrinitheader(struct ktr_header *kth, struct proc *p, int type)
     137             : {
     138           0 :         struct process *pr = p->p_p;
     139             : 
     140           0 :         ktrinitheaderraw(kth, type, pr->ps_pid, p->p_tid + THREAD_PID_OFFSET);
     141           0 :         memcpy(kth->ktr_comm, pr->ps_comm, MAXCOMLEN);
     142           0 : }
     143             : 
     144             : void
     145           0 : ktrstart(struct proc *p, struct vnode *vp, struct ucred *cred)
     146             : {
     147           0 :         struct ktr_header kth;
     148             : 
     149           0 :         ktrinitheaderraw(&kth, htobe32(KTR_START), -1, -1);
     150           0 :         ktrwriteraw(p, vp, cred, &kth, NULL);
     151           0 : }
     152             : 
     153             : void
     154           0 : ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[])
     155             : {
     156           0 :         struct  ktr_header kth;
     157             :         struct  ktr_syscall *ktp;
     158           0 :         size_t len = sizeof(struct ktr_syscall) + argsize;
     159             :         register_t *argp;
     160             :         u_int nargs = 0;
     161             :         int i;
     162             : 
     163           0 :         if (code == SYS_sysctl) {
     164             :                 /*
     165             :                  * The sysctl encoding stores the mib[]
     166             :                  * array because it is interesting.
     167             :                  */
     168           0 :                 if (args[1] > 0)
     169           0 :                         nargs = lmin(args[1], CTL_MAXNAME);
     170           0 :                 len += nargs * sizeof(int);
     171           0 :         }
     172           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     173           0 :         ktrinitheader(&kth, p, KTR_SYSCALL);
     174           0 :         ktp = malloc(len, M_TEMP, M_WAITOK);
     175           0 :         ktp->ktr_code = code;
     176           0 :         ktp->ktr_argsize = argsize;
     177           0 :         argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
     178           0 :         for (i = 0; i < (argsize / sizeof *argp); i++)
     179           0 :                 *argp++ = args[i];
     180           0 :         if (nargs && copyin((void *)args[0], argp, nargs * sizeof(int)))
     181           0 :                 memset(argp, 0, nargs * sizeof(int));
     182           0 :         ktrwrite(p, &kth, ktp, len);
     183           0 :         free(ktp, M_TEMP, len);
     184           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     185           0 : }
     186             : 
     187             : void
     188           0 : ktrsysret(struct proc *p, register_t code, int error,
     189             :     const register_t retval[2])
     190             : {
     191           0 :         struct ktr_header kth;
     192           0 :         struct ktr_sysret ktp;
     193             :         int len;
     194             : 
     195           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     196           0 :         ktrinitheader(&kth, p, KTR_SYSRET);
     197           0 :         ktp.ktr_code = code;
     198           0 :         ktp.ktr_error = error;
     199           0 :         if (error)
     200           0 :                 len = 0;
     201             :         else if (code == SYS_lseek)
     202             :                 /* the one exception: lseek on ILP32 needs more */
     203             :                 len = sizeof(long long);
     204             :         else
     205             :                 len = sizeof(register_t);
     206           0 :         ktrwrite2(p, &kth, &ktp, sizeof(ktp), retval, len);
     207           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     208           0 : }
     209             : 
     210             : void
     211           0 : ktrnamei(struct proc *p, char *path)
     212             : {
     213           0 :         struct ktr_header kth;
     214             : 
     215           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     216           0 :         ktrinitheader(&kth, p, KTR_NAMEI);
     217           0 :         ktrwrite(p, &kth, path, strlen(path));
     218           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     219           0 : }
     220             : 
     221             : void
     222           0 : ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov,
     223             :     ssize_t len)
     224             : {
     225           0 :         struct ktr_header kth;
     226           0 :         struct ktr_genio ktp;
     227             :         caddr_t cp;
     228             :         int count, error;
     229             :         int buflen;
     230             : 
     231           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     232             : 
     233             :         /* beware overflow */
     234           0 :         if (len > PAGE_SIZE)
     235           0 :                 buflen = PAGE_SIZE;
     236             :         else
     237           0 :                 buflen = len + sizeof(struct ktr_genio);
     238             : 
     239           0 :         ktrinitheader(&kth, p, KTR_GENIO);
     240           0 :         ktp.ktr_fd = fd;
     241           0 :         ktp.ktr_rw = rw;
     242             : 
     243           0 :         cp = malloc(buflen, M_TEMP, M_WAITOK);
     244           0 :         while (len > 0) {
     245             :                 /*
     246             :                  * Don't allow this process to hog the cpu when doing
     247             :                  * huge I/O.
     248             :                  */
     249           0 :                 sched_pause(preempt);
     250             : 
     251           0 :                 count = lmin(iov->iov_len, buflen);
     252           0 :                 if (count > len)
     253           0 :                         count = len;
     254           0 :                 if (copyin(iov->iov_base, cp, count))
     255             :                         break;
     256             : 
     257           0 :                 KERNEL_LOCK();
     258           0 :                 error = ktrwrite2(p, &kth, &ktp, sizeof(ktp), cp, count);
     259           0 :                 KERNEL_UNLOCK();
     260           0 :                 if (error != 0)
     261             :                         break;
     262             : 
     263           0 :                 iov->iov_len -= count;
     264           0 :                 iov->iov_base = (caddr_t)iov->iov_base + count;
     265             : 
     266           0 :                 if (iov->iov_len == 0)
     267           0 :                         iov++;
     268             : 
     269           0 :                 len -= count;
     270             :         }
     271             : 
     272           0 :         free(cp, M_TEMP, buflen);
     273           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     274           0 : }
     275             : 
     276             : void
     277           0 : ktrpsig(struct proc *p, int sig, sig_t action, int mask, int code,
     278             :     siginfo_t *si)
     279             : {
     280           0 :         struct ktr_header kth;
     281           0 :         struct ktr_psig kp;
     282             : 
     283           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     284           0 :         ktrinitheader(&kth, p, KTR_PSIG);
     285           0 :         kp.signo = (char)sig;
     286           0 :         kp.action = action;
     287           0 :         kp.mask = mask;
     288           0 :         kp.code = code;
     289           0 :         kp.si = *si;
     290             : 
     291           0 :         ktrwrite(p, &kth, &kp, sizeof(kp));
     292           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     293           0 : }
     294             : 
     295             : void
     296           0 : ktrstruct(struct proc *p, const char *name, const void *data, size_t datalen)
     297             : {
     298           0 :         struct ktr_header kth;
     299             : 
     300           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     301           0 :         ktrinitheader(&kth, p, KTR_STRUCT);
     302             : 
     303           0 :         if (data == NULL)
     304           0 :                 datalen = 0;
     305           0 :         KERNEL_LOCK();
     306           0 :         ktrwrite2(p, &kth, name, strlen(name) + 1, data, datalen);
     307           0 :         KERNEL_UNLOCK();
     308           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     309           0 : }
     310             : 
     311             : int
     312           0 : ktruser(struct proc *p, const char *id, const void *addr, size_t len)
     313             : {
     314           0 :         struct ktr_header kth;
     315           0 :         struct ktr_user ktp;
     316             :         int error;
     317             :         void *memp;
     318             : #define STK_PARAMS      128
     319           0 :         long long stkbuf[STK_PARAMS / sizeof(long long)];
     320             : 
     321           0 :         if (!KTRPOINT(p, KTR_USER))
     322           0 :                 return (0);
     323           0 :         if (len > KTR_USER_MAXLEN)
     324           0 :                 return (EINVAL);
     325             : 
     326           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     327           0 :         ktrinitheader(&kth, p, KTR_USER);
     328           0 :         memset(ktp.ktr_id, 0, KTR_USER_MAXIDLEN);
     329           0 :         error = copyinstr(id, ktp.ktr_id, KTR_USER_MAXIDLEN, NULL);
     330           0 :         if (error == 0) {
     331           0 :                 if (len > sizeof(stkbuf))
     332           0 :                         memp = malloc(len, M_TEMP, M_WAITOK);
     333             :                 else
     334           0 :                         memp = stkbuf;
     335           0 :                 error = copyin(addr, memp, len);
     336           0 :                 if (error == 0)
     337           0 :                         ktrwrite2(p, &kth, &ktp, sizeof(ktp), memp, len);
     338           0 :                 if (memp != stkbuf)
     339           0 :                         free(memp, M_TEMP, len);
     340             :         }
     341           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     342           0 :         return (error);
     343           0 : }
     344             : 
     345             : void
     346           0 : ktrexec(struct proc *p, int type, const char *data, ssize_t len)
     347             : {
     348           0 :         struct ktr_header kth;
     349             :         int count;
     350             :         int buflen;
     351             :         
     352           0 :         assert(type == KTR_EXECARGS || type == KTR_EXECENV);
     353           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     354             : 
     355             :         /* beware overflow */
     356           0 :         if (len > PAGE_SIZE)
     357           0 :                 buflen = PAGE_SIZE;
     358             :         else
     359           0 :                 buflen = len;
     360             : 
     361           0 :         ktrinitheader(&kth, p, type);
     362             : 
     363           0 :         while (len > 0) {
     364             :                 /*
     365             :                  * Don't allow this process to hog the cpu when doing
     366             :                  * huge I/O.
     367             :                  */
     368           0 :                 sched_pause(preempt);
     369             : 
     370           0 :                 count = lmin(len, buflen);
     371           0 :                 if (ktrwrite(p, &kth, data, count) != 0)
     372             :                         break;
     373             : 
     374           0 :                 len -= count;
     375           0 :                 data += count;
     376             :         }
     377             : 
     378           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     379           0 : }
     380             : 
     381             : void
     382           0 : ktrpledge(struct proc *p, int error, uint64_t code, int syscall)
     383             : {
     384           0 :         struct ktr_header kth;
     385           0 :         struct ktr_pledge kp;
     386             : 
     387           0 :         atomic_setbits_int(&p->p_flag, P_INKTR);
     388           0 :         ktrinitheader(&kth, p, KTR_PLEDGE);
     389           0 :         kp.error = error;
     390           0 :         kp.code = code;
     391           0 :         kp.syscall = syscall;
     392             : 
     393           0 :         KERNEL_LOCK();
     394           0 :         ktrwrite(p, &kth, &kp, sizeof(kp));
     395           0 :         KERNEL_UNLOCK();
     396           0 :         atomic_clearbits_int(&p->p_flag, P_INKTR);
     397           0 : }
     398             : 
     399             : /* Interface and common routines */
     400             : 
     401             : int
     402           0 : doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p)
     403             : {
     404             :         struct process *pr = NULL;
     405             :         struct ucred *cred = NULL;
     406             :         struct pgrp *pg;
     407           0 :         int descend = ops & KTRFLAG_DESCEND;
     408             :         int ret = 0;
     409             :         int error = 0;
     410             : 
     411           0 :         facs = facs & ~((unsigned)KTRFAC_ROOT);
     412           0 :         ops = KTROP(ops);
     413             : 
     414           0 :         if (ops != KTROP_CLEAR) {
     415             :                 /*
     416             :                  * an operation which requires a file argument.
     417             :                  */
     418           0 :                 cred = p->p_ucred;
     419           0 :                 if (!vp) {
     420             :                         error = EINVAL;
     421           0 :                         goto done;
     422             :                 }
     423           0 :                 if (vp->v_type != VREG) {
     424             :                         error = EACCES;
     425           0 :                         goto done;
     426             :                 }
     427             :         }
     428             :         /*
     429             :          * Clear all uses of the tracefile
     430             :          */
     431           0 :         if (ops == KTROP_CLEARFILE) {
     432           0 :                 LIST_FOREACH(pr, &allprocess, ps_list) {
     433           0 :                         if (pr->ps_tracevp == vp) {
     434           0 :                                 if (ktrcanset(p, pr))
     435           0 :                                         ktrcleartrace(pr);
     436             :                                 else
     437             :                                         error = EPERM;
     438             :                         }
     439             :                 }
     440             :                 goto done;
     441             :         }
     442             :         /*
     443             :          * need something to (un)trace (XXX - why is this here?)
     444             :          */
     445           0 :         if (!facs) {
     446             :                 error = EINVAL;
     447           0 :                 goto done;
     448             :         }
     449           0 :         if (ops == KTROP_SET) {
     450           0 :                 if (suser(p) == 0)
     451           0 :                         facs |= KTRFAC_ROOT;
     452           0 :                 ktrstart(p, vp, cred);
     453           0 :         }
     454             :         /*
     455             :          * do it
     456             :          */
     457           0 :         if (pid < 0) {
     458             :                 /*
     459             :                  * by process group
     460             :                  */
     461           0 :                 pg = pgfind(-pid);
     462           0 :                 if (pg == NULL) {
     463             :                         error = ESRCH;
     464           0 :                         goto done;
     465             :                 }
     466           0 :                 LIST_FOREACH(pr, &pg->pg_members, ps_pglist) {
     467           0 :                         if (descend)
     468           0 :                                 ret |= ktrsetchildren(p, pr, ops, facs, vp,
     469             :                                     cred);
     470             :                         else
     471           0 :                                 ret |= ktrops(p, pr, ops, facs, vp, cred);
     472             :                 }
     473             :         } else {
     474             :                 /*
     475             :                  * by pid
     476             :                  */
     477           0 :                 pr = prfind(pid);
     478           0 :                 if (pr == NULL) {
     479             :                         error = ESRCH;
     480           0 :                         goto done;
     481             :                 }
     482           0 :                 if (descend)
     483           0 :                         ret |= ktrsetchildren(p, pr, ops, facs, vp, cred);
     484             :                 else
     485           0 :                         ret |= ktrops(p, pr, ops, facs, vp, cred);
     486             :         }
     487           0 :         if (!ret)
     488           0 :                 error = EPERM;
     489             : done:
     490           0 :         return (error);
     491             : }
     492             : 
     493             : /*
     494             :  * ktrace system call
     495             :  */
     496             : int
     497           0 : sys_ktrace(struct proc *p, void *v, register_t *retval)
     498             : {
     499             :         struct sys_ktrace_args /* {
     500             :                 syscallarg(const char *) fname;
     501             :                 syscallarg(int) ops;
     502             :                 syscallarg(int) facs;
     503             :                 syscallarg(pid_t) pid;
     504           0 :         } */ *uap = v;
     505             :         struct vnode *vp = NULL;
     506           0 :         const char *fname = SCARG(uap, fname);
     507             :         struct ucred *cred = NULL;
     508             :         int error;
     509             : 
     510           0 :         if (fname) {
     511           0 :                 struct nameidata nd;
     512             : 
     513           0 :                 cred = p->p_ucred;
     514           0 :                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, p);
     515           0 :                 nd.ni_pledge = PLEDGE_CPATH | PLEDGE_WPATH;
     516           0 :                 nd.ni_unveil = UNVEIL_CREATE | UNVEIL_WRITE;
     517           0 :                 if ((error = vn_open(&nd, FWRITE|O_NOFOLLOW, 0)) != 0)
     518           0 :                         return error;
     519           0 :                 vp = nd.ni_vp;
     520             : 
     521           0 :                 VOP_UNLOCK(vp);
     522           0 :         }
     523             : 
     524           0 :         error = doktrace(vp, SCARG(uap, ops), SCARG(uap, facs),
     525           0 :             SCARG(uap, pid), p);
     526           0 :         if (vp != NULL)
     527           0 :                 (void)vn_close(vp, FWRITE, cred, p);
     528             : 
     529           0 :         return error;
     530           0 : }
     531             : 
     532             : int
     533           0 : ktrops(struct proc *curp, struct process *pr, int ops, int facs,
     534             :     struct vnode *vp, struct ucred *cred)
     535             : {
     536           0 :         if (!ktrcanset(curp, pr))
     537           0 :                 return (0);
     538           0 :         if (ops == KTROP_SET)
     539           0 :                 ktrsettrace(pr, facs, vp, cred);
     540             :         else {  
     541             :                 /* KTROP_CLEAR */
     542           0 :                 pr->ps_traceflag &= ~facs;
     543           0 :                 if ((pr->ps_traceflag & KTRFAC_MASK) == 0) {
     544             :                         /* cleared all the facility bits, so stop completely */
     545           0 :                         ktrcleartrace(pr);
     546           0 :                 }
     547             :         }
     548             : 
     549           0 :         return (1);
     550           0 : }
     551             : 
     552             : int
     553           0 : ktrsetchildren(struct proc *curp, struct process *top, int ops, int facs,
     554             :     struct vnode *vp, struct ucred *cred)
     555             : {
     556             :         struct process *pr;
     557             :         int ret = 0;
     558             : 
     559             :         pr = top;
     560           0 :         for (;;) {
     561           0 :                 ret |= ktrops(curp, pr, ops, facs, vp, cred);
     562             :                 /*
     563             :                  * If this process has children, descend to them next,
     564             :                  * otherwise do any siblings, and if done with this level,
     565             :                  * follow back up the tree (but not past top).
     566             :                  */
     567           0 :                 if (!LIST_EMPTY(&pr->ps_children))
     568           0 :                         pr = LIST_FIRST(&pr->ps_children);
     569           0 :                 else for (;;) {
     570           0 :                         if (pr == top)
     571           0 :                                 return (ret);
     572           0 :                         if (LIST_NEXT(pr, ps_sibling) != NULL) {
     573             :                                 pr = LIST_NEXT(pr, ps_sibling);
     574             :                                 break;
     575             :                         }
     576           0 :                         pr = pr->ps_pptr;
     577             :                 }
     578             :         }
     579             :         /*NOTREACHED*/
     580             : }
     581             : 
     582             : int
     583           0 : ktrwrite(struct proc *p, struct ktr_header *kth, const void *aux, size_t len)
     584             : {
     585           0 :         struct vnode *vp = p->p_p->ps_tracevp;
     586           0 :         struct ucred *cred = p->p_p->ps_tracecred;
     587           0 :         struct iovec data[2];
     588             :         int error;
     589             : 
     590           0 :         if (vp == NULL)
     591           0 :                 return 0;
     592           0 :         crhold(cred);
     593           0 :         data[0].iov_base = (void *)aux;
     594           0 :         data[0].iov_len = len;
     595           0 :         data[1].iov_len = 0;
     596           0 :         kth->ktr_len = len;
     597           0 :         error = ktrwriteraw(p, vp, cred, kth, data);
     598           0 :         crfree(cred);
     599           0 :         return (error);
     600           0 : }
     601             : 
     602             : int
     603           0 : ktrwrite2(struct proc *p, struct ktr_header *kth, const void *aux1,
     604             :     size_t len1, const void *aux2, size_t len2)
     605             : {
     606           0 :         struct vnode *vp = p->p_p->ps_tracevp;
     607           0 :         struct ucred *cred = p->p_p->ps_tracecred;
     608           0 :         struct iovec data[2];
     609             :         int error;
     610             : 
     611           0 :         if (vp == NULL)
     612           0 :                 return 0;
     613           0 :         crhold(cred);
     614           0 :         data[0].iov_base = (void *)aux1;
     615           0 :         data[0].iov_len = len1;
     616           0 :         data[1].iov_base = (void *)aux2;
     617           0 :         data[1].iov_len = len2;
     618           0 :         kth->ktr_len = len1 + len2;
     619           0 :         error = ktrwriteraw(p, vp, cred, kth, data);
     620           0 :         crfree(cred);
     621           0 :         return (error);
     622           0 : }
     623             : 
     624             : int
     625           0 : ktrwriteraw(struct proc *curp, struct vnode *vp, struct ucred *cred,
     626             :     struct ktr_header *kth, struct iovec *data)
     627             : {
     628           0 :         struct uio auio;
     629           0 :         struct iovec aiov[3];
     630             :         struct process *pr;
     631             :         int error;
     632             : 
     633           0 :         KERNEL_ASSERT_LOCKED();
     634             : 
     635           0 :         auio.uio_iov = &aiov[0];
     636           0 :         auio.uio_offset = 0;
     637           0 :         auio.uio_segflg = UIO_SYSSPACE;
     638           0 :         auio.uio_rw = UIO_WRITE;
     639           0 :         aiov[0].iov_base = (caddr_t)kth;
     640           0 :         aiov[0].iov_len = sizeof(struct ktr_header);
     641           0 :         auio.uio_resid = sizeof(struct ktr_header);
     642           0 :         auio.uio_iovcnt = 1;
     643           0 :         auio.uio_procp = curp;
     644           0 :         if (kth->ktr_len > 0) {
     645           0 :                 aiov[1] = data[0];
     646           0 :                 aiov[2] = data[1];
     647           0 :                 auio.uio_iovcnt++;
     648           0 :                 if (aiov[2].iov_len > 0)
     649           0 :                         auio.uio_iovcnt++;
     650           0 :                 auio.uio_resid += kth->ktr_len;
     651           0 :         }
     652           0 :         vget(vp, LK_EXCLUSIVE | LK_RETRY);
     653           0 :         error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, cred);
     654           0 :         if (!error) {
     655           0 :                 vput(vp);
     656           0 :                 return (0);
     657             :         }
     658             :         /*
     659             :          * If error encountered, give up tracing on this vnode.
     660             :          */
     661           0 :         log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
     662             :             error);
     663           0 :         LIST_FOREACH(pr, &allprocess, ps_list)
     664           0 :                 if (pr->ps_tracevp == vp && pr->ps_tracecred == cred)
     665           0 :                         ktrcleartrace(pr);
     666             : 
     667           0 :         vput(vp);
     668           0 :         return (error);
     669           0 : }
     670             : 
     671             : /*
     672             :  * Return true if caller has permission to set the ktracing state
     673             :  * of target.  Essentially, the target can't possess any
     674             :  * more permissions than the caller.  KTRFAC_ROOT signifies that
     675             :  * root previously set the tracing status on the target process, and 
     676             :  * so, only root may further change it.
     677             :  *
     678             :  * TODO: check groups.  use caller effective gid.
     679             :  */
     680             : int
     681           0 : ktrcanset(struct proc *callp, struct process *targetpr)
     682             : {
     683           0 :         struct ucred *caller = callp->p_ucred;
     684           0 :         struct ucred *target = targetpr->ps_ucred;
     685             : 
     686           0 :         if ((caller->cr_uid == target->cr_ruid &&
     687           0 :             target->cr_ruid == target->cr_svuid &&
     688           0 :             caller->cr_rgid == target->cr_rgid && /* XXX */
     689           0 :             target->cr_rgid == target->cr_svgid &&
     690           0 :             (targetpr->ps_traceflag & KTRFAC_ROOT) == 0 &&
     691           0 :             !ISSET(targetpr->ps_flags, PS_SUGID)) ||
     692           0 :             caller->cr_uid == 0)
     693           0 :                 return (1);
     694             : 
     695           0 :         return (0);
     696           0 : }

Generated by: LCOV version 1.13