]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_ktrace.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / kern / kern_ktrace.c
CommitLineData
1c79356b 1/*
8ad349bb 2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
31/*
32 * Copyright (c) 1989, 1993
33 * The Regents of the University of California. All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93
9bccf70c 64 * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.4 2001/03/05 13:09:01 obrien Exp $
1c79356b
A
65 */
66
67
68#include <sys/param.h>
69#include <sys/systm.h>
9bccf70c 70#include <sys/types.h>
91447636
A
71#include <sys/proc_internal.h>
72#include <sys/kauth.h>
73#include <sys/file_internal.h>
1c79356b 74#include <sys/namei.h>
91447636 75#include <sys/vnode_internal.h>
9bccf70c 76#if KTRACE
1c79356b 77#include <sys/ktrace.h>
9bccf70c 78#endif
1c79356b
A
79#include <sys/malloc.h>
80#include <sys/syslog.h>
91447636
A
81#include <sys/sysproto.h>
82#include <sys/uio_internal.h>
e5568f75
A
83
84#include <bsm/audit_kernel.h>
1c79356b 85
1c79356b 86#if KTRACE
91447636
A
87static struct ktr_header *ktrgetheader(int type);
88static void ktrwrite(struct vnode *, struct ktr_header *, struct uio *);
89static int ktrcanset(struct proc *,struct proc *);
90static int ktrsetchildren(struct proc *,struct proc *,
91 int, int, struct vnode *);
92static int ktrops(struct proc *,struct proc *,int,int,struct vnode *);
1c79356b 93
9bccf70c
A
94
95static struct ktr_header *
1c79356b
A
96ktrgetheader(type)
97 int type;
98{
99 register struct ktr_header *kth;
100 struct proc *p = current_proc(); /* XXX */
101
9bccf70c
A
102 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header),
103 M_KTRACE, M_WAITOK);
91447636
A
104 if (kth != NULL) {
105 kth->ktr_type = type;
106 microtime(&kth->ktr_time);
107 kth->ktr_pid = p->p_pid;
108 bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN);
109 }
1c79356b
A
110 return (kth);
111}
9bccf70c 112#endif
1c79356b
A
113
114void
91447636 115ktrsyscall(p, code, narg, args)
9bccf70c
A
116 struct proc *p;
117 int code, narg;
8ad349bb 118 u_int64_t args[];
1c79356b 119{
9bccf70c
A
120#if KTRACE
121 struct vnode *vp;
1c79356b
A
122 struct ktr_header *kth;
123 struct ktr_syscall *ktp;
9bccf70c 124 register int len;
91447636 125 u_int64_t *argp;
1c79356b
A
126 int i;
127
9bccf70c
A
128 if (!KTRPOINT(p, KTR_SYSCALL))
129 return;
130
131 vp = p->p_tracep;
132 len = __offsetof(struct ktr_syscall, ktr_args) +
91447636 133 (narg * sizeof(u_int64_t));
1c79356b
A
134 p->p_traceflag |= KTRFAC_ACTIVE;
135 kth = ktrgetheader(KTR_SYSCALL);
91447636
A
136 if (kth == NULL) {
137 p->p_traceflag &= ~KTRFAC_ACTIVE;
138 return;
139 }
9bccf70c 140 MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK);
91447636
A
141 if (ktp == NULL) {
142 FREE(kth, M_KTRACE);
143 return;
144 }
1c79356b 145 ktp->ktr_code = code;
9bccf70c
A
146 ktp->ktr_narg = narg;
147 argp = &ktp->ktr_args[0];
148 for (i = 0; i < narg; i++)
1c79356b
A
149 *argp++ = args[i];
150 kth->ktr_buf = (caddr_t)ktp;
151 kth->ktr_len = len;
91447636 152 ktrwrite(vp, kth, NULL);
9bccf70c
A
153 FREE(ktp, M_KTRACE);
154 FREE(kth, M_KTRACE);
1c79356b 155 p->p_traceflag &= ~KTRFAC_ACTIVE;
9bccf70c
A
156#else
157 return;
158#endif
1c79356b 159}
9bccf70c 160
1c79356b 161void
91447636 162ktrsysret(p, code, error, retval)
9bccf70c
A
163 struct proc *p;
164 int code, error;
1c79356b
A
165 register_t retval;
166{
9bccf70c
A
167#if KTRACE
168 struct vnode *vp;
1c79356b
A
169 struct ktr_header *kth;
170 struct ktr_sysret ktp;
1c79356b 171
9bccf70c
A
172 if (!KTRPOINT(p, KTR_SYSRET))
173 return;
174
175 vp = p->p_tracep;
1c79356b
A
176 p->p_traceflag |= KTRFAC_ACTIVE;
177 kth = ktrgetheader(KTR_SYSRET);
91447636
A
178 if (kth == NULL) {
179 p->p_traceflag &= ~KTRFAC_ACTIVE;
180 return;
181 }
1c79356b
A
182 ktp.ktr_code = code;
183 ktp.ktr_error = error;
184 ktp.ktr_retval = retval; /* what about val2 ? */
185
186 kth->ktr_buf = (caddr_t)&ktp;
187 kth->ktr_len = sizeof(struct ktr_sysret);
188
91447636 189 ktrwrite(vp, kth, NULL);
9bccf70c 190 FREE(kth, M_KTRACE);
1c79356b 191 p->p_traceflag &= ~KTRFAC_ACTIVE;
9bccf70c
A
192#else
193 return;
194#endif
1c79356b
A
195}
196
9bccf70c 197#if KTRACE
1c79356b
A
198void
199ktrnamei(vp, path)
200 struct vnode *vp;
201 char *path;
202{
203 struct ktr_header *kth;
204 struct proc *p = current_proc(); /* XXX */
205
206 p->p_traceflag |= KTRFAC_ACTIVE;
207 kth = ktrgetheader(KTR_NAMEI);
91447636
A
208 if (kth == NULL) {
209 p->p_traceflag &= ~KTRFAC_ACTIVE;
210 return;
211 }
1c79356b
A
212 kth->ktr_len = strlen(path);
213 kth->ktr_buf = path;
214
91447636 215 ktrwrite(vp, kth, NULL);
9bccf70c 216 FREE(kth, M_KTRACE);
1c79356b
A
217 p->p_traceflag &= ~KTRFAC_ACTIVE;
218}
219
220void
91447636 221ktrgenio(vp, fd, rw, uio, error)
1c79356b
A
222 struct vnode *vp;
223 int fd;
224 enum uio_rw rw;
9bccf70c
A
225 struct uio *uio;
226 int error;
1c79356b
A
227{
228 struct ktr_header *kth;
9bccf70c 229 struct ktr_genio ktg;
1c79356b 230 struct proc *p = current_proc(); /* XXX */
9bccf70c 231
1c79356b
A
232 if (error)
233 return;
9bccf70c 234
1c79356b
A
235 p->p_traceflag |= KTRFAC_ACTIVE;
236 kth = ktrgetheader(KTR_GENIO);
91447636
A
237 if (kth == NULL) {
238 p->p_traceflag &= ~KTRFAC_ACTIVE;
239 return;
240 }
9bccf70c
A
241 ktg.ktr_fd = fd;
242 ktg.ktr_rw = rw;
243 kth->ktr_buf = (caddr_t)&ktg;
244 kth->ktr_len = sizeof(struct ktr_genio);
245 uio->uio_offset = 0;
246 uio->uio_rw = UIO_WRITE;
247
91447636 248 ktrwrite(vp, kth, uio);
9bccf70c 249 FREE(kth, M_KTRACE);
1c79356b
A
250 p->p_traceflag &= ~KTRFAC_ACTIVE;
251}
252
253void
91447636 254ktrpsig(vp, sig, action, mask, code)
1c79356b
A
255 struct vnode *vp;
256 int sig;
257 sig_t action;
9bccf70c
A
258 sigset_t *mask;
259 int code;
1c79356b
A
260{
261 struct ktr_header *kth;
262 struct ktr_psig kp;
263 struct proc *p = current_proc(); /* XXX */
264
265 p->p_traceflag |= KTRFAC_ACTIVE;
266 kth = ktrgetheader(KTR_PSIG);
91447636
A
267 if (kth == NULL) {
268 p->p_traceflag &= ~KTRFAC_ACTIVE;
269 return;
270 }
1c79356b
A
271 kp.signo = (char)sig;
272 kp.action = action;
9bccf70c 273 kp.mask = *mask;
1c79356b
A
274 kp.code = code;
275 kth->ktr_buf = (caddr_t)&kp;
276 kth->ktr_len = sizeof (struct ktr_psig);
277
91447636 278 ktrwrite(vp, kth, NULL);
9bccf70c 279 FREE(kth, M_KTRACE);
1c79356b
A
280 p->p_traceflag &= ~KTRFAC_ACTIVE;
281}
282
283void
91447636 284ktrcsw(vp, out, user)
1c79356b
A
285 struct vnode *vp;
286 int out, user;
287{
288 struct ktr_header *kth;
289 struct ktr_csw kc;
290 struct proc *p = current_proc(); /* XXX */
291
292 p->p_traceflag |= KTRFAC_ACTIVE;
293 kth = ktrgetheader(KTR_CSW);
91447636
A
294 if (kth == NULL) {
295 p->p_traceflag &= ~KTRFAC_ACTIVE;
296 return;
297 }
1c79356b
A
298 kc.out = out;
299 kc.user = user;
300 kth->ktr_buf = (caddr_t)&kc;
301 kth->ktr_len = sizeof (struct ktr_csw);
302
91447636 303 ktrwrite(vp, kth, NULL);
9bccf70c 304 FREE(kth, M_KTRACE);
1c79356b
A
305 p->p_traceflag &= ~KTRFAC_ACTIVE;
306}
9bccf70c 307#endif /* KTRACE */
1c79356b
A
308
309/* Interface and common routines */
310
311/*
312 * ktrace system call
313 */
1c79356b
A
314/* ARGSUSED */
315int
91447636 316ktrace(struct proc *curp, register struct ktrace_args *uap, __unused register_t *retval)
1c79356b 317{
9bccf70c 318#if KTRACE
1c79356b
A
319 register struct vnode *vp = NULL;
320 register struct proc *p;
321 struct pgrp *pg;
9bccf70c
A
322 int facs = uap->facs & ~KTRFAC_ROOT;
323 int ops = KTROP(uap->ops);
324 int descend = uap->ops & KTRFLAG_DESCEND;
1c79356b
A
325 int ret = 0;
326 int error = 0;
327 struct nameidata nd;
91447636 328 struct vfs_context context;
1c79356b 329
e5568f75
A
330 AUDIT_ARG(cmd, uap->ops);
331 AUDIT_ARG(pid, uap->pid);
332 AUDIT_ARG(value, uap->facs);
91447636
A
333
334 context.vc_proc = curp;
335 context.vc_ucred = kauth_cred_get();
336
1c79356b
A
337 curp->p_traceflag |= KTRFAC_ACTIVE;
338 if (ops != KTROP_CLEAR) {
339 /*
340 * an operation which requires a file argument.
341 */
91447636
A
342 NDINIT(&nd, LOOKUP, (NOFOLLOW|LOCKLEAF), UIO_USERSPACE,
343 uap->fname, &context);
9bccf70c
A
344 error = vn_open(&nd, FREAD|FWRITE|O_NOFOLLOW, 0);
345 if (error) {
1c79356b
A
346 curp->p_traceflag &= ~KTRFAC_ACTIVE;
347 return (error);
348 }
349 vp = nd.ni_vp;
91447636 350
1c79356b 351 if (vp->v_type != VREG) {
91447636
A
352 (void) vn_close(vp, FREAD|FWRITE, kauth_cred_get(), curp);
353 (void) vnode_put(vp);
354
1c79356b
A
355 curp->p_traceflag &= ~KTRFAC_ACTIVE;
356 return (EACCES);
357 }
358 }
359 /*
360 * Clear all uses of the tracefile
361 */
362 if (ops == KTROP_CLEARFILE) {
9bccf70c 363 LIST_FOREACH(p, &allproc, p_list) {
1c79356b
A
364 if (p->p_tracep == vp) {
365 if (ktrcanset(curp, p)) {
9bccf70c
A
366 struct vnode *tvp = p->p_tracep;
367 /* no more tracing */
1c79356b 368 p->p_traceflag = 0;
9bccf70c
A
369 if (tvp != NULL) {
370 p->p_tracep = NULL;
91447636 371 vnode_rele(tvp);
9bccf70c 372 }
1c79356b
A
373 } else
374 error = EPERM;
375 }
376 }
377 goto done;
378 }
9bccf70c 379
1c79356b
A
380 /*
381 * need something to (un)trace (XXX - why is this here?)
382 */
383 if (!facs) {
384 error = EINVAL;
385 goto done;
386 }
9bccf70c 387 /*
1c79356b
A
388 * do it
389 */
9bccf70c 390 if (uap->pid < 0) {
1c79356b
A
391 /*
392 * by process group
393 */
9bccf70c 394 pg = pgfind(-uap->pid);
1c79356b
A
395 if (pg == NULL) {
396 error = ESRCH;
397 goto done;
398 }
9bccf70c 399 LIST_FOREACH(p, &pg->pg_members, p_pglist)
1c79356b
A
400 if (descend)
401 ret |= ktrsetchildren(curp, p, ops, facs, vp);
9bccf70c 402 else
1c79356b 403 ret |= ktrops(curp, p, ops, facs, vp);
9bccf70c 404
1c79356b
A
405 } else {
406 /*
407 * by pid
408 */
9bccf70c 409 p = pfind(uap->pid);
1c79356b
A
410 if (p == NULL) {
411 error = ESRCH;
412 goto done;
413 }
e5568f75 414 AUDIT_ARG(process, p);
1c79356b
A
415 if (descend)
416 ret |= ktrsetchildren(curp, p, ops, facs, vp);
417 else
418 ret |= ktrops(curp, p, ops, facs, vp);
419 }
420 if (!ret)
421 error = EPERM;
422done:
91447636
A
423 if (vp != NULL) {
424 (void) vn_close(vp, FWRITE, kauth_cred_get(), curp);
425 (void) vnode_put(vp);
426 }
1c79356b
A
427 curp->p_traceflag &= ~KTRFAC_ACTIVE;
428 return (error);
9bccf70c
A
429#else
430 return ENOSYS;
431#endif
1c79356b
A
432}
433
9bccf70c
A
434/*
435 * utrace system call
436 */
9bccf70c
A
437
438/* ARGSUSED */
1c79356b 439int
91447636 440utrace(__unused struct proc *curp, register struct utrace_args *uap, __unused register_t *retval)
9bccf70c
A
441{
442#if KTRACE
443 struct ktr_header *kth;
444 struct proc *p = current_proc(); /* XXX */
445 register caddr_t cp;
446
447 if (!KTRPOINT(p, KTR_USER))
448 return (0);
449 if (uap->len > KTR_USER_MAXLEN)
450 return (EINVAL);
451 p->p_traceflag |= KTRFAC_ACTIVE;
452 kth = ktrgetheader(KTR_USER);
91447636
A
453 if (kth == NULL) {
454 p->p_traceflag &= ~KTRFAC_ACTIVE;
455 return(ENOMEM);
456 }
9bccf70c 457 MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK);
91447636
A
458 if (cp == NULL) {
459 FREE(kth, M_KTRACE);
460 return(ENOMEM);
461 }
462 if (copyin(uap->addr, cp, uap->len) == 0) {
9bccf70c
A
463 kth->ktr_buf = cp;
464 kth->ktr_len = uap->len;
91447636 465 ktrwrite(p->p_tracep, kth, NULL);
9bccf70c
A
466 }
467 FREE(kth, M_KTRACE);
468 FREE(cp, M_KTRACE);
469 p->p_traceflag &= ~KTRFAC_ACTIVE;
470
471 return (0);
472#else
473 return (ENOSYS);
474#endif
475}
476
477#if KTRACE
478static int
1c79356b
A
479ktrops(curp, p, ops, facs, vp)
480 struct proc *p, *curp;
481 int ops, facs;
482 struct vnode *vp;
483{
9bccf70c 484 struct vnode *tvp;
1c79356b
A
485
486 if (!ktrcanset(curp, p))
487 return (0);
488 if (ops == KTROP_SET) {
9bccf70c 489 if (p->p_tracep != vp) {
9bccf70c 490 tvp = p->p_tracep;
91447636 491 vnode_ref(vp);
1c79356b 492 p->p_tracep = vp;
91447636 493
e5568f75 494 if (tvp != NULL) {
91447636
A
495 /*
496 * if trace file already in use, relinquish
497 */
498 vnode_rele(tvp);
e5568f75 499 }
1c79356b
A
500 }
501 p->p_traceflag |= facs;
91447636 502 if (!suser(kauth_cred_get(), NULL))
1c79356b 503 p->p_traceflag |= KTRFAC_ROOT;
9bccf70c 504 } else {
1c79356b
A
505 /* KTROP_CLEAR */
506 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
507 /* no more tracing */
9bccf70c 508 tvp = p->p_tracep;
1c79356b 509 p->p_traceflag = 0;
9bccf70c 510 if (tvp != NULL) {
1c79356b 511 p->p_tracep = NULL;
91447636 512 vnode_rele(tvp);
1c79356b
A
513 }
514 }
515 }
516
517 return (1);
518}
519
9bccf70c 520static int
1c79356b
A
521ktrsetchildren(curp, top, ops, facs, vp)
522 struct proc *curp, *top;
523 int ops, facs;
524 struct vnode *vp;
525{
526 register struct proc *p;
527 register int ret = 0;
528
529 p = top;
530 for (;;) {
531 ret |= ktrops(curp, p, ops, facs, vp);
532 /*
533 * If this process has children, descend to them next,
534 * otherwise do any siblings, and if done with this level,
535 * follow back up the tree (but not past top).
536 */
9bccf70c
A
537 if (!LIST_EMPTY(&p->p_children))
538 p = LIST_FIRST(&p->p_children);
1c79356b
A
539 else for (;;) {
540 if (p == top)
541 return (ret);
9bccf70c
A
542 if (LIST_NEXT(p, p_sibling)) {
543 p = LIST_NEXT(p, p_sibling);
1c79356b
A
544 break;
545 }
546 p = p->p_pptr;
547 }
548 }
549 /*NOTREACHED*/
550}
551
9bccf70c 552static void
91447636 553ktrwrite(struct vnode *vp, struct ktr_header *kth, struct uio *uio)
1c79356b 554{
91447636 555 uio_t auio;
1c79356b 556 register struct proc *p = current_proc(); /* XXX */
91447636 557 struct vfs_context context;
1c79356b 558 int error;
91447636 559 char uio_buf[ UIO_SIZEOF(2) ];
1c79356b
A
560
561 if (vp == NULL)
562 return;
9bccf70c 563
91447636
A
564 auio = uio_createwithbuffer(2, 0, UIO_SYSSPACE, UIO_WRITE,
565 &uio_buf[0], sizeof(uio_buf));
566 uio_addiov(auio, CAST_USER_ADDR_T(kth), sizeof(struct ktr_header));
567 context.vc_proc = p;
568 context.vc_ucred = kauth_cred_get();
569
1c79356b 570 if (kth->ktr_len > 0) {
91447636 571 uio_addiov(auio, CAST_USER_ADDR_T(kth->ktr_buf), kth->ktr_len);
9bccf70c 572 if (uio != NULL)
91447636 573 kth->ktr_len += uio_resid(uio);
9bccf70c 574 }
91447636
A
575 if ((error = vnode_getwithref(vp)) == 0) {
576 error = VNOP_WRITE(vp, auio, IO_UNIT | IO_APPEND, &context);
577 if (error == 0 && uio != NULL) {
578 error = VNOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, &context);
9bccf70c 579 }
91447636 580 vnode_put(vp);
9bccf70c 581 }
91447636
A
582 if (error) {
583 /*
584 * If error encountered, give up tracing on this vnode.
585 */
586 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
587 error);
588 LIST_FOREACH(p, &allproc, p_list) {
589 if (p->p_tracep == vp) {
590 p->p_tracep = NULL;
591 p->p_traceflag = 0;
592 vnode_rele(vp);
593 }
1c79356b
A
594 }
595 }
596}
597
598/*
599 * Return true if caller has permission to set the ktracing state
600 * of target. Essentially, the target can't possess any
601 * more permissions than the caller. KTRFAC_ROOT signifies that
9bccf70c 602 * root previously set the tracing status on the target process, and
1c79356b
A
603 * so, only root may further change it.
604 *
605 * TODO: check groups. use caller effective gid.
606 */
9bccf70c 607static int
91447636 608ktrcanset(__unused struct proc *callp, struct proc *targetp)
1c79356b 609{
91447636
A
610 kauth_cred_t caller = kauth_cred_get();
611 kauth_cred_t target = targetp->p_ucred; /* XXX */
1c79356b 612
91447636
A
613#if 0
614 /* PRISON_CHECK was defined to 1 always .... */
9bccf70c
A
615 if (!PRISON_CHECK(callp, targetp))
616 return (0);
91447636
A
617#endif
618 if ((kauth_cred_getuid(caller) == target->cr_ruid &&
619 target->cr_ruid == target->cr_svuid &&
620 caller->cr_rgid == target->cr_rgid && /* XXX */
621 target->cr_rgid == target->cr_svgid &&
55e303ae
A
622 (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
623 (targetp->p_flag & P_SUGID) == 0) ||
91447636 624 !suser(caller, NULL))
1c79356b
A
625 return (1);
626
627 return (0);
628}
629
9bccf70c 630#endif /* KTRACE */