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