kern_ktrace.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /* $OpenBSD: kern_ktrace.c,v 1.75 2015/08/01 20:12:34 guenther Exp $ */
  2. /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */
  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.2 (Berkeley) 9/23/93
  32. */
  33. #include <sys/param.h>
  34. #include <sys/systm.h>
  35. #include <sys/proc.h>
  36. #include <sys/sched.h>
  37. #include <sys/file.h>
  38. #include <sys/namei.h>
  39. #include <sys/vnode.h>
  40. #include <sys/lock.h>
  41. #include <sys/ktrace.h>
  42. #include <sys/malloc.h>
  43. #include <sys/syslog.h>
  44. #include <sys/sysctl.h>
  45. #include <sys/mount.h>
  46. #include <sys/syscall.h>
  47. #include <sys/syscallargs.h>
  48. #include <uvm/uvm_extern.h>
  49. void ktrinitheaderraw(struct ktr_header *, uint, pid_t, pid_t);
  50. void ktrinitheader(struct ktr_header *, struct proc *, int);
  51. void ktrstart(struct proc *, struct vnode *, struct ucred *);
  52. void ktremulraw(struct proc *, struct process *, pid_t);
  53. int ktrops(struct proc *, struct process *, int, int, struct vnode *,
  54. struct ucred *);
  55. int ktrsetchildren(struct proc *, struct process *, int, int,
  56. struct vnode *, struct ucred *);
  57. int ktrwrite(struct proc *, struct ktr_header *, const void *, size_t);
  58. int ktrwrite2(struct proc *, struct ktr_header *, const void *, size_t,
  59. const void *, size_t);
  60. int ktrwriteraw(struct proc *, struct vnode *, struct ucred *,
  61. struct ktr_header *, struct iovec *);
  62. int ktrcanset(struct proc *, struct process *);
  63. /*
  64. * Clear the trace settings in a correct way (to avoid races).
  65. */
  66. void
  67. ktrcleartrace(struct process *pr)
  68. {
  69. struct vnode *vp;
  70. struct ucred *cred;
  71. if (pr->ps_tracevp != NULL) {
  72. vp = pr->ps_tracevp;
  73. cred = pr->ps_tracecred;
  74. pr->ps_traceflag = 0;
  75. pr->ps_tracevp = NULL;
  76. pr->ps_tracecred = NULL;
  77. vrele(vp);
  78. crfree(cred);
  79. }
  80. }
  81. /*
  82. * Change the trace setting in a correct way (to avoid races).
  83. */
  84. void
  85. ktrsettrace(struct process *pr, int facs, struct vnode *newvp,
  86. struct ucred *newcred)
  87. {
  88. struct vnode *oldvp;
  89. struct ucred *oldcred;
  90. KASSERT(newvp != NULL);
  91. KASSERT(newcred != NULL);
  92. pr->ps_traceflag |= facs;
  93. /* nothing to change about where the trace goes? */
  94. if (pr->ps_tracevp == newvp && pr->ps_tracecred == newcred)
  95. return;
  96. vref(newvp);
  97. crhold(newcred);
  98. oldvp = pr->ps_tracevp;
  99. oldcred = pr->ps_tracecred;
  100. pr->ps_tracevp = newvp;
  101. pr->ps_tracecred = newcred;
  102. if (oldvp != NULL) {
  103. vrele(oldvp);
  104. crfree(oldcred);
  105. }
  106. }
  107. void
  108. ktrinitheaderraw(struct ktr_header *kth, uint type, pid_t pid, pid_t tid)
  109. {
  110. memset(kth, 0, sizeof(struct ktr_header));
  111. kth->ktr_type = type;
  112. nanotime(&kth->ktr_time);
  113. kth->ktr_pid = pid;
  114. kth->ktr_tid = tid;
  115. }
  116. void
  117. ktrinitheader(struct ktr_header *kth, struct proc *p, int type)
  118. {
  119. ktrinitheaderraw(kth, type, p->p_p->ps_pid,
  120. p->p_pid + THREAD_PID_OFFSET);
  121. memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
  122. }
  123. void
  124. ktrstart(struct proc *p, struct vnode *vp, struct ucred *cred)
  125. {
  126. struct ktr_header kth;
  127. ktrinitheaderraw(&kth, htobe32(KTR_START), -1, -1);
  128. ktrwriteraw(p, vp, cred, &kth, NULL);
  129. }
  130. void
  131. ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[])
  132. {
  133. struct ktr_header kth;
  134. struct ktr_syscall *ktp;
  135. size_t len = sizeof(struct ktr_syscall) + argsize;
  136. register_t *argp;
  137. u_int nargs = 0;
  138. int i;
  139. if (code == SYS___sysctl && (p->p_p->ps_emul->e_flags & EMUL_NATIVE)) {
  140. /*
  141. * The native sysctl encoding stores the mib[]
  142. * array because it is interesting.
  143. */
  144. if (args[1] > 0)
  145. nargs = lmin(args[1], CTL_MAXNAME);
  146. len += nargs * sizeof(int);
  147. }
  148. atomic_setbits_int(&p->p_flag, P_INKTR);
  149. ktrinitheader(&kth, p, KTR_SYSCALL);
  150. ktp = malloc(len, M_TEMP, M_WAITOK);
  151. ktp->ktr_code = code;
  152. ktp->ktr_argsize = argsize;
  153. argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
  154. for (i = 0; i < (argsize / sizeof *argp); i++)
  155. *argp++ = args[i];
  156. if (nargs && copyin((void *)args[0], argp, nargs * sizeof(int)))
  157. memset(argp, 0, nargs * sizeof(int));
  158. ktrwrite(p, &kth, ktp, len);
  159. free(ktp, M_TEMP, len);
  160. atomic_clearbits_int(&p->p_flag, P_INKTR);
  161. }
  162. void
  163. ktrsysret(struct proc *p, register_t code, int error,
  164. const register_t retval[2])
  165. {
  166. struct ktr_header kth;
  167. struct ktr_sysret ktp;
  168. int len;
  169. atomic_setbits_int(&p->p_flag, P_INKTR);
  170. ktrinitheader(&kth, p, KTR_SYSRET);
  171. ktp.ktr_code = code;
  172. ktp.ktr_error = error;
  173. if (error)
  174. len = 0;
  175. else if (code == SYS_lseek)
  176. /* the one exception: lseek on ILP32 needs more */
  177. len = sizeof(long long);
  178. else
  179. len = sizeof(register_t);
  180. ktrwrite2(p, &kth, &ktp, sizeof(ktp), retval, len);
  181. atomic_clearbits_int(&p->p_flag, P_INKTR);
  182. }
  183. void
  184. ktrnamei(struct proc *p, char *path)
  185. {
  186. struct ktr_header kth;
  187. atomic_setbits_int(&p->p_flag, P_INKTR);
  188. ktrinitheader(&kth, p, KTR_NAMEI);
  189. ktrwrite(p, &kth, path, strlen(path));
  190. atomic_clearbits_int(&p->p_flag, P_INKTR);
  191. }
  192. void
  193. ktremulraw(struct proc *curp, struct process *pr, pid_t tid)
  194. {
  195. struct ktr_header kth;
  196. char *emul = pr->ps_emul->e_name;
  197. struct iovec data[2];
  198. ktrinitheaderraw(&kth, KTR_EMUL, pr->ps_pid, tid);
  199. data[0].iov_base = emul;
  200. data[0].iov_len = strlen(emul);
  201. data[1].iov_len = 0;
  202. kth.ktr_len = data[0].iov_len;
  203. ktrwriteraw(curp, pr->ps_tracevp, pr->ps_tracecred, &kth, data);
  204. }
  205. void
  206. ktremul(struct proc *p)
  207. {
  208. atomic_setbits_int(&p->p_flag, P_INKTR);
  209. ktremulraw(p, p->p_p, p->p_pid + THREAD_PID_OFFSET);
  210. atomic_clearbits_int(&p->p_flag, P_INKTR);
  211. }
  212. void
  213. ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov,
  214. ssize_t len)
  215. {
  216. struct ktr_header kth;
  217. struct ktr_genio ktp;
  218. caddr_t cp;
  219. int count;
  220. int buflen;
  221. atomic_setbits_int(&p->p_flag, P_INKTR);
  222. /* beware overflow */
  223. if (len > PAGE_SIZE)
  224. buflen = PAGE_SIZE;
  225. else
  226. buflen = len + sizeof(struct ktr_genio);
  227. ktrinitheader(&kth, p, KTR_GENIO);
  228. ktp.ktr_fd = fd;
  229. ktp.ktr_rw = rw;
  230. cp = malloc(buflen, M_TEMP, M_WAITOK);
  231. while (len > 0) {
  232. /*
  233. * Don't allow this process to hog the cpu when doing
  234. * huge I/O.
  235. */
  236. if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD)
  237. preempt(NULL);
  238. count = lmin(iov->iov_len, buflen);
  239. if (count > len)
  240. count = len;
  241. if (copyin(iov->iov_base, cp, count))
  242. break;
  243. if (ktrwrite2(p, &kth, &ktp, sizeof(ktp), cp, count) != 0)
  244. break;
  245. iov->iov_len -= count;
  246. iov->iov_base = (caddr_t)iov->iov_base + count;
  247. if (iov->iov_len == 0)
  248. iov++;
  249. len -= count;
  250. }
  251. free(cp, M_TEMP, buflen);
  252. atomic_clearbits_int(&p->p_flag, P_INKTR);
  253. }
  254. void
  255. ktrpsig(struct proc *p, int sig, sig_t action, int mask, int code,
  256. siginfo_t *si)
  257. {
  258. struct ktr_header kth;
  259. struct ktr_psig kp;
  260. atomic_setbits_int(&p->p_flag, P_INKTR);
  261. ktrinitheader(&kth, p, KTR_PSIG);
  262. kp.signo = (char)sig;
  263. kp.action = action;
  264. kp.mask = mask;
  265. kp.code = code;
  266. kp.si = *si;
  267. ktrwrite(p, &kth, &kp, sizeof(kp));
  268. atomic_clearbits_int(&p->p_flag, P_INKTR);
  269. }
  270. void
  271. ktrcsw(struct proc *p, int out, int user)
  272. {
  273. struct ktr_header kth;
  274. struct ktr_csw kc;
  275. atomic_setbits_int(&p->p_flag, P_INKTR);
  276. ktrinitheader(&kth, p, KTR_CSW);
  277. kc.out = out;
  278. kc.user = user;
  279. ktrwrite(p, &kth, &kc, sizeof(kc));
  280. atomic_clearbits_int(&p->p_flag, P_INKTR);
  281. }
  282. void
  283. ktrstruct(struct proc *p, const char *name, const void *data, size_t datalen)
  284. {
  285. struct ktr_header kth;
  286. KERNEL_ASSERT_LOCKED();
  287. atomic_setbits_int(&p->p_flag, P_INKTR);
  288. ktrinitheader(&kth, p, KTR_STRUCT);
  289. if (data == NULL)
  290. datalen = 0;
  291. ktrwrite2(p, &kth, name, strlen(name) + 1, data, datalen);
  292. atomic_clearbits_int(&p->p_flag, P_INKTR);
  293. }
  294. int
  295. ktruser(struct proc *p, const char *id, const void *addr, size_t len)
  296. {
  297. struct ktr_header kth;
  298. struct ktr_user ktp;
  299. int error;
  300. void *memp;
  301. #define STK_PARAMS 128
  302. long long stkbuf[STK_PARAMS / sizeof(long long)];
  303. if (!KTRPOINT(p, KTR_USER))
  304. return (0);
  305. if (len > KTR_USER_MAXLEN)
  306. return (EINVAL);
  307. atomic_setbits_int(&p->p_flag, P_INKTR);
  308. ktrinitheader(&kth, p, KTR_USER);
  309. memset(ktp.ktr_id, 0, KTR_USER_MAXIDLEN);
  310. error = copyinstr(id, ktp.ktr_id, KTR_USER_MAXIDLEN, NULL);
  311. if (error == 0) {
  312. if (len > sizeof(stkbuf))
  313. memp = malloc(len, M_TEMP, M_WAITOK);
  314. else
  315. memp = stkbuf;
  316. error = copyin(addr, memp, len);
  317. if (error == 0)
  318. ktrwrite2(p, &kth, &ktp, sizeof(ktp), memp, len);
  319. if (memp != stkbuf)
  320. free(memp, M_TEMP, len);
  321. }
  322. atomic_clearbits_int(&p->p_flag, P_INKTR);
  323. return (error);
  324. }
  325. /* Interface and common routines */
  326. /*
  327. * ktrace system call
  328. */
  329. /* ARGSUSED */
  330. int
  331. sys_ktrace(struct proc *curp, void *v, register_t *retval)
  332. {
  333. struct sys_ktrace_args /* {
  334. syscallarg(const char *) fname;
  335. syscallarg(int) ops;
  336. syscallarg(int) facs;
  337. syscallarg(pid_t) pid;
  338. } */ *uap = v;
  339. struct vnode *vp = NULL;
  340. struct process *pr = NULL;
  341. struct ucred *cred = NULL;
  342. struct pgrp *pg;
  343. int facs = SCARG(uap, facs) & ~((unsigned) KTRFAC_ROOT);
  344. int ops = KTROP(SCARG(uap, ops));
  345. int descend = SCARG(uap, ops) & KTRFLAG_DESCEND;
  346. int ret = 0;
  347. int error = 0;
  348. struct nameidata nd;
  349. if (ops != KTROP_CLEAR) {
  350. /*
  351. * an operation which requires a file argument.
  352. */
  353. cred = curp->p_ucred;
  354. NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
  355. curp);
  356. if ((error = vn_open(&nd, FREAD|FWRITE|O_NOFOLLOW, 0)) != 0)
  357. goto done;
  358. vp = nd.ni_vp;
  359. VOP_UNLOCK(vp, 0, curp);
  360. if (vp->v_type != VREG) {
  361. error = EACCES;
  362. goto done;
  363. }
  364. }
  365. /*
  366. * Clear all uses of the tracefile
  367. */
  368. if (ops == KTROP_CLEARFILE) {
  369. LIST_FOREACH(pr, &allprocess, ps_list) {
  370. if (pr->ps_tracevp == vp) {
  371. if (ktrcanset(curp, pr))
  372. ktrcleartrace(pr);
  373. else
  374. error = EPERM;
  375. }
  376. }
  377. goto done;
  378. }
  379. /*
  380. * need something to (un)trace (XXX - why is this here?)
  381. */
  382. if (!facs) {
  383. error = EINVAL;
  384. goto done;
  385. }
  386. if (ops == KTROP_SET) {
  387. if (suser(curp, 0) == 0)
  388. facs |= KTRFAC_ROOT;
  389. ktrstart(curp, vp, cred);
  390. }
  391. /*
  392. * do it
  393. */
  394. if (SCARG(uap, pid) < 0) {
  395. /*
  396. * by process group
  397. */
  398. pg = pgfind(-SCARG(uap, pid));
  399. if (pg == NULL) {
  400. error = ESRCH;
  401. goto done;
  402. }
  403. LIST_FOREACH(pr, &pg->pg_members, ps_pglist) {
  404. if (descend)
  405. ret |= ktrsetchildren(curp, pr, ops, facs, vp,
  406. cred);
  407. else
  408. ret |= ktrops(curp, pr, ops, facs, vp, cred);
  409. }
  410. } else {
  411. /*
  412. * by pid
  413. */
  414. pr = prfind(SCARG(uap, pid));
  415. if (pr == NULL) {
  416. error = ESRCH;
  417. goto done;
  418. }
  419. if (descend)
  420. ret |= ktrsetchildren(curp, pr, ops, facs, vp, cred);
  421. else
  422. ret |= ktrops(curp, pr, ops, facs, vp, cred);
  423. }
  424. if (!ret)
  425. error = EPERM;
  426. done:
  427. if (vp != NULL)
  428. (void) vn_close(vp, FREAD|FWRITE, cred, curp);
  429. return (error);
  430. }
  431. int
  432. ktrops(struct proc *curp, struct process *pr, int ops, int facs,
  433. struct vnode *vp, struct ucred *cred)
  434. {
  435. if (!ktrcanset(curp, pr))
  436. return (0);
  437. if (ops == KTROP_SET)
  438. ktrsettrace(pr, facs, vp, cred);
  439. else {
  440. /* KTROP_CLEAR */
  441. pr->ps_traceflag &= ~facs;
  442. if ((pr->ps_traceflag & KTRFAC_MASK) == 0) {
  443. /* cleared all the facility bits, so stop completely */
  444. ktrcleartrace(pr);
  445. }
  446. }
  447. /*
  448. * Emit an emulation record every time there is a ktrace
  449. * change/attach request.
  450. */
  451. if (pr->ps_traceflag & KTRFAC_EMUL)
  452. ktremulraw(curp, pr, -1);
  453. return (1);
  454. }
  455. int
  456. ktrsetchildren(struct proc *curp, struct process *top, int ops, int facs,
  457. struct vnode *vp, struct ucred *cred)
  458. {
  459. struct process *pr;
  460. int ret = 0;
  461. pr = top;
  462. for (;;) {
  463. ret |= ktrops(curp, pr, ops, facs, vp, cred);
  464. /*
  465. * If this process has children, descend to them next,
  466. * otherwise do any siblings, and if done with this level,
  467. * follow back up the tree (but not past top).
  468. */
  469. if (!LIST_EMPTY(&pr->ps_children))
  470. pr = LIST_FIRST(&pr->ps_children);
  471. else for (;;) {
  472. if (pr == top)
  473. return (ret);
  474. if (LIST_NEXT(pr, ps_sibling) != NULL) {
  475. pr = LIST_NEXT(pr, ps_sibling);
  476. break;
  477. }
  478. pr = pr->ps_pptr;
  479. }
  480. }
  481. /*NOTREACHED*/
  482. }
  483. int
  484. ktrwrite(struct proc *p, struct ktr_header *kth, const void *aux, size_t len)
  485. {
  486. struct vnode *vp = p->p_p->ps_tracevp;
  487. struct ucred *cred = p->p_p->ps_tracecred;
  488. struct iovec data[2];
  489. int error;
  490. if (vp == NULL)
  491. return 0;
  492. crhold(cred);
  493. data[0].iov_base = (void *)aux;
  494. data[0].iov_len = len;
  495. data[1].iov_len = 0;
  496. kth->ktr_len = len;
  497. error = ktrwriteraw(p, vp, cred, kth, data);
  498. crfree(cred);
  499. return (error);
  500. }
  501. int
  502. ktrwrite2(struct proc *p, struct ktr_header *kth, const void *aux1,
  503. size_t len1, const void *aux2, size_t len2)
  504. {
  505. struct vnode *vp = p->p_p->ps_tracevp;
  506. struct ucred *cred = p->p_p->ps_tracecred;
  507. struct iovec data[2];
  508. int error;
  509. if (vp == NULL)
  510. return 0;
  511. crhold(cred);
  512. data[0].iov_base = (void *)aux1;
  513. data[0].iov_len = len1;
  514. data[1].iov_base = (void *)aux2;
  515. data[1].iov_len = len2;
  516. kth->ktr_len = len1 + len2;
  517. error = ktrwriteraw(p, vp, cred, kth, data);
  518. crfree(cred);
  519. return (error);
  520. }
  521. int
  522. ktrwriteraw(struct proc *curp, struct vnode *vp, struct ucred *cred,
  523. struct ktr_header *kth, struct iovec *data)
  524. {
  525. struct uio auio;
  526. struct iovec aiov[3];
  527. struct process *pr;
  528. int error;
  529. auio.uio_iov = &aiov[0];
  530. auio.uio_offset = 0;
  531. auio.uio_segflg = UIO_SYSSPACE;
  532. auio.uio_rw = UIO_WRITE;
  533. aiov[0].iov_base = (caddr_t)kth;
  534. aiov[0].iov_len = sizeof(struct ktr_header);
  535. auio.uio_resid = sizeof(struct ktr_header);
  536. auio.uio_iovcnt = 1;
  537. auio.uio_procp = curp;
  538. if (kth->ktr_len > 0) {
  539. aiov[1] = data[0];
  540. aiov[2] = data[1];
  541. auio.uio_iovcnt++;
  542. if (aiov[2].iov_len > 0)
  543. auio.uio_iovcnt++;
  544. auio.uio_resid += kth->ktr_len;
  545. }
  546. vget(vp, LK_EXCLUSIVE | LK_RETRY, curp);
  547. error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, cred);
  548. if (!error) {
  549. vput(vp);
  550. return (0);
  551. }
  552. /*
  553. * If error encountered, give up tracing on this vnode.
  554. */
  555. log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
  556. error);
  557. LIST_FOREACH(pr, &allprocess, ps_list)
  558. if (pr->ps_tracevp == vp && pr->ps_tracecred == cred)
  559. ktrcleartrace(pr);
  560. vput(vp);
  561. return (error);
  562. }
  563. /*
  564. * Return true if caller has permission to set the ktracing state
  565. * of target. Essentially, the target can't possess any
  566. * more permissions than the caller. KTRFAC_ROOT signifies that
  567. * root previously set the tracing status on the target process, and
  568. * so, only root may further change it.
  569. *
  570. * TODO: check groups. use caller effective gid.
  571. */
  572. int
  573. ktrcanset(struct proc *callp, struct process *targetpr)
  574. {
  575. struct ucred *caller = callp->p_ucred;
  576. struct ucred *target = targetpr->ps_ucred;
  577. if ((caller->cr_uid == target->cr_ruid &&
  578. target->cr_ruid == target->cr_svuid &&
  579. caller->cr_rgid == target->cr_rgid && /* XXX */
  580. target->cr_rgid == target->cr_svgid &&
  581. (targetpr->ps_traceflag & KTRFAC_ROOT) == 0 &&
  582. !ISSET(targetpr->ps_flags, PS_SUGID)) ||
  583. caller->cr_uid == 0)
  584. return (1);
  585. return (0);
  586. }