]>
Commit | Line | Data |
---|---|---|
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 |
87 | static struct ktr_header *ktrgetheader(int type); |
88 | static void ktrwrite(struct vnode *, struct ktr_header *, struct uio *); | |
89 | static int ktrcanset(struct proc *,struct proc *); | |
90 | static int ktrsetchildren(struct proc *,struct proc *, | |
91 | int, int, struct vnode *); | |
92 | static int ktrops(struct proc *,struct proc *,int,int,struct vnode *); | |
1c79356b | 93 | |
9bccf70c A |
94 | |
95 | static struct ktr_header * | |
1c79356b A |
96 | ktrgetheader(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 | |
114 | void | |
91447636 | 115 | ktrsyscall(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 | 161 | void |
91447636 | 162 | ktrsysret(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 |
198 | void |
199 | ktrnamei(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 | ||
220 | void | |
91447636 | 221 | ktrgenio(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 | ||
253 | void | |
91447636 | 254 | ktrpsig(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 | ||
283 | void | |
91447636 | 284 | ktrcsw(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 */ |
315 | int | |
91447636 | 316 | ktrace(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; | |
422 | done: | |
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 | 439 | int |
91447636 | 440 | utrace(__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 | |
478 | static int | |
1c79356b A |
479 | ktrops(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 | 520 | static int |
1c79356b A |
521 | ktrsetchildren(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 | 552 | static void |
91447636 | 553 | ktrwrite(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 | 607 | static int |
91447636 | 608 | ktrcanset(__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 */ |