This source file includes following definitions.
- ktrsettracevnode
- ktrinitheader
- ktrsyscall
- ktrsysret
- ktrnamei
- ktremul
- ktrgenio
- ktrpsig
- ktrcsw
- sys_ktrace
- ktrops
- ktrsetchildren
- ktrwrite
- ktrcanset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #ifdef KTRACE
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/sched.h>
41 #include <sys/file.h>
42 #include <sys/namei.h>
43 #include <sys/vnode.h>
44 #include <sys/ktrace.h>
45 #include <sys/malloc.h>
46 #include <sys/syslog.h>
47 #include <sys/sysctl.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 ktrinitheader(struct ktr_header *, struct proc *, int);
56 int ktrops(struct proc *, struct proc *, int, int, struct vnode *);
57 int ktrsetchildren(struct proc *, struct proc *, int, int,
58 struct vnode *);
59 int ktrwrite(struct proc *, struct ktr_header *);
60 int ktrcanset(struct proc *, struct proc *);
61
62
63
64
65 void
66 ktrsettracevnode(struct proc *p, struct vnode *newvp)
67 {
68 struct vnode *vp;
69
70 if (p->p_tracep == newvp)
71 return;
72
73 if (newvp != NULL)
74 VREF(newvp);
75
76 vp = p->p_tracep;
77 p->p_tracep = newvp;
78
79 if (vp != NULL)
80 vrele(vp);
81 }
82
83 void
84 ktrinitheader(struct ktr_header *kth, struct proc *p, int type)
85 {
86 bzero(kth, sizeof (struct ktr_header));
87 kth->ktr_type = type;
88 microtime(&kth->ktr_time);
89 kth->ktr_pid = p->p_pid;
90 bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN);
91 }
92
93 void
94 ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[])
95 {
96 struct ktr_header kth;
97 struct ktr_syscall *ktp;
98 size_t len = sizeof(struct ktr_syscall) + argsize;
99 register_t *argp;
100 u_int nargs = 0;
101 int i;
102
103 if (code == SYS___sysctl && (p->p_emul->e_flags & EMUL_NATIVE)) {
104
105
106
107
108 if (args[1] > 0)
109 nargs = min(args[1], CTL_MAXNAME);
110 len += nargs * sizeof(int);
111 }
112 p->p_traceflag |= KTRFAC_ACTIVE;
113 ktrinitheader(&kth, p, KTR_SYSCALL);
114 ktp = malloc(len, M_TEMP, M_WAITOK);
115 ktp->ktr_code = code;
116 ktp->ktr_argsize = argsize;
117 argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
118 for (i = 0; i < (argsize / sizeof *argp); i++)
119 *argp++ = args[i];
120 if (code == SYS___sysctl && (p->p_emul->e_flags & EMUL_NATIVE) &&
121 nargs &&
122 copyin((void *)args[0], argp, nargs * sizeof(int)))
123 bzero(argp, nargs * sizeof(int));
124 kth.ktr_buf = (caddr_t)ktp;
125 kth.ktr_len = len;
126 ktrwrite(p, &kth);
127 free(ktp, M_TEMP);
128 p->p_traceflag &= ~KTRFAC_ACTIVE;
129 }
130
131 void
132 ktrsysret(struct proc *p, register_t code, int error, register_t retval)
133 {
134 struct ktr_header kth;
135 struct ktr_sysret ktp;
136
137 p->p_traceflag |= KTRFAC_ACTIVE;
138 ktrinitheader(&kth, p, KTR_SYSRET);
139 ktp.ktr_code = code;
140 ktp.ktr_error = error;
141 ktp.ktr_retval = retval;
142
143 kth.ktr_buf = (caddr_t)&ktp;
144 kth.ktr_len = sizeof(struct ktr_sysret);
145
146 ktrwrite(p, &kth);
147 p->p_traceflag &= ~KTRFAC_ACTIVE;
148 }
149
150 void
151 ktrnamei(struct proc *p, char *path)
152 {
153 struct ktr_header kth;
154
155 p->p_traceflag |= KTRFAC_ACTIVE;
156 ktrinitheader(&kth, p, KTR_NAMEI);
157 kth.ktr_len = strlen(path);
158 kth.ktr_buf = path;
159
160 ktrwrite(p, &kth);
161 p->p_traceflag &= ~KTRFAC_ACTIVE;
162 }
163
164 void
165 ktremul(struct proc *p, char *emul)
166 {
167 struct ktr_header kth;
168
169 p->p_traceflag |= KTRFAC_ACTIVE;
170 ktrinitheader(&kth, p, KTR_EMUL);
171 kth.ktr_len = strlen(emul);
172 kth.ktr_buf = emul;
173
174 ktrwrite(p, &kth);
175 p->p_traceflag &= ~KTRFAC_ACTIVE;
176 }
177
178 void
179 ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov, int len,
180 int error)
181 {
182 struct ktr_header kth;
183 struct ktr_genio *ktp;
184 caddr_t cp;
185 int resid = len, count;
186 int buflen;
187
188 if (error)
189 return;
190
191 p->p_traceflag |= KTRFAC_ACTIVE;
192
193 buflen = min(PAGE_SIZE, len + sizeof(struct ktr_genio));
194
195 ktrinitheader(&kth, p, KTR_GENIO);
196 ktp = malloc(buflen, M_TEMP, M_WAITOK);
197 ktp->ktr_fd = fd;
198 ktp->ktr_rw = rw;
199
200 kth.ktr_buf = (caddr_t)ktp;
201
202 cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
203 buflen -= sizeof(struct ktr_genio);
204
205 while (resid > 0) {
206
207
208
209
210 if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD)
211 preempt(NULL);
212
213 count = min(iov->iov_len, buflen);
214 if (count > resid)
215 count = resid;
216 if (copyin(iov->iov_base, cp, count))
217 break;
218
219 kth.ktr_len = count + sizeof(struct ktr_genio);
220
221 if (ktrwrite(p, &kth) != 0)
222 break;
223
224 iov->iov_len -= count;
225 iov->iov_base = (caddr_t)iov->iov_base + count;
226
227 if (iov->iov_len == 0)
228 iov++;
229
230 resid -= count;
231 }
232
233 free(ktp, M_TEMP);
234 p->p_traceflag &= ~KTRFAC_ACTIVE;
235
236 }
237
238 void
239 ktrpsig(struct proc *p, int sig, sig_t action, int mask, int code,
240 siginfo_t *si)
241 {
242 struct ktr_header kth;
243 struct ktr_psig kp;
244
245 p->p_traceflag |= KTRFAC_ACTIVE;
246 ktrinitheader(&kth, p, KTR_PSIG);
247 kp.signo = (char)sig;
248 kp.action = action;
249 kp.mask = mask;
250 kp.code = code;
251 kp.si = *si;
252 kth.ktr_buf = (caddr_t)&kp;
253 kth.ktr_len = sizeof(struct ktr_psig);
254
255 ktrwrite(p, &kth);
256 p->p_traceflag &= ~KTRFAC_ACTIVE;
257 }
258
259 void
260 ktrcsw(struct proc *p, int out, int user)
261 {
262 struct ktr_header kth;
263 struct ktr_csw kc;
264
265 p->p_traceflag |= KTRFAC_ACTIVE;
266 ktrinitheader(&kth, p, KTR_CSW);
267 kc.out = out;
268 kc.user = user;
269 kth.ktr_buf = (caddr_t)&kc;
270 kth.ktr_len = sizeof(struct ktr_csw);
271
272 ktrwrite(p, &kth);
273 p->p_traceflag &= ~KTRFAC_ACTIVE;
274 }
275
276
277
278
279
280
281
282 int
283 sys_ktrace(struct proc *curp, void *v, register_t *retval)
284 {
285 struct sys_ktrace_args
286
287
288
289
290 *uap = v;
291 struct vnode *vp = NULL;
292 struct proc *p = NULL;
293 struct pgrp *pg;
294 int facs = SCARG(uap, facs) & ~((unsigned) KTRFAC_ROOT);
295 int ops = KTROP(SCARG(uap, ops));
296 int descend = SCARG(uap, ops) & KTRFLAG_DESCEND;
297 int ret = 0;
298 int error = 0;
299 struct nameidata nd;
300
301 curp->p_traceflag |= KTRFAC_ACTIVE;
302 if (ops != KTROP_CLEAR) {
303
304
305
306 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
307 curp);
308 if ((error = vn_open(&nd, FREAD|FWRITE|O_NOFOLLOW, 0)) != 0) {
309 curp->p_traceflag &= ~KTRFAC_ACTIVE;
310 return (error);
311 }
312 vp = nd.ni_vp;
313
314 VOP_UNLOCK(vp, 0, curp);
315 if (vp->v_type != VREG) {
316 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
317 curp->p_traceflag &= ~KTRFAC_ACTIVE;
318 return (EACCES);
319 }
320 }
321
322
323
324 if (ops == KTROP_CLEARFILE) {
325 for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list)) {
326 if (p->p_tracep == vp) {
327 if (ktrcanset(curp, p)) {
328 p->p_traceflag = 0;
329 ktrsettracevnode(p, NULL);
330 } else
331 error = EPERM;
332 }
333 }
334 goto done;
335 }
336
337
338
339 if (!facs) {
340 error = EINVAL;
341 goto done;
342 }
343
344
345
346 if (SCARG(uap, pid) < 0) {
347
348
349
350 pg = pgfind(-SCARG(uap, pid));
351 if (pg == NULL) {
352 error = ESRCH;
353 goto done;
354 }
355 LIST_FOREACH(p, &pg->pg_members, p_pglist)
356 if (descend)
357 ret |= ktrsetchildren(curp, p, ops, facs, vp);
358 else
359 ret |= ktrops(curp, p, ops, facs, vp);
360
361 } else {
362
363
364
365 p = pfind(SCARG(uap, pid));
366 if (p == NULL) {
367 error = ESRCH;
368 goto done;
369 }
370 if (descend)
371 ret |= ktrsetchildren(curp, p, ops, facs, vp);
372 else
373 ret |= ktrops(curp, p, ops, facs, vp);
374 }
375 if (!ret)
376 error = EPERM;
377 done:
378 if (vp != NULL)
379 (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
380 curp->p_traceflag &= ~KTRFAC_ACTIVE;
381 return (error);
382 }
383
384 int
385 ktrops(struct proc *curp, struct proc *p, int ops, int facs, struct vnode *vp)
386 {
387
388 if (!ktrcanset(curp, p))
389 return (0);
390 if (ops == KTROP_SET) {
391 ktrsettracevnode(p, vp);
392 p->p_traceflag |= facs;
393 if (curp->p_ucred->cr_uid == 0)
394 p->p_traceflag |= KTRFAC_ROOT;
395 } else {
396
397 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
398
399 p->p_traceflag = 0;
400 ktrsettracevnode(p, NULL);
401 }
402 }
403
404
405
406
407
408 if (KTRPOINT(p, KTR_EMUL))
409 ktremul(p, p->p_emul->e_name);
410
411 return (1);
412 }
413
414 int
415 ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs,
416 struct vnode *vp)
417 {
418 struct proc *p;
419 int ret = 0;
420
421 p = top;
422 for (;;) {
423 ret |= ktrops(curp, p, ops, facs, vp);
424
425
426
427
428
429 if (!LIST_EMPTY(&p->p_children))
430 p = LIST_FIRST(&p->p_children);
431 else for (;;) {
432 if (p == top)
433 return (ret);
434 if (LIST_NEXT(p, p_sibling) != NULL) {
435 p = LIST_NEXT(p, p_sibling);
436 break;
437 }
438 p = p->p_pptr;
439 }
440 }
441
442 }
443
444 int
445 ktrwrite(struct proc *p, struct ktr_header *kth)
446 {
447 struct uio auio;
448 struct iovec aiov[2];
449 int error;
450 struct vnode *vp = p->p_tracep;
451
452 if (vp == NULL)
453 return 0;
454 auio.uio_iov = &aiov[0];
455 auio.uio_offset = 0;
456 auio.uio_segflg = UIO_SYSSPACE;
457 auio.uio_rw = UIO_WRITE;
458 aiov[0].iov_base = (caddr_t)kth;
459 aiov[0].iov_len = sizeof(struct ktr_header);
460 auio.uio_resid = sizeof(struct ktr_header);
461 auio.uio_iovcnt = 1;
462 auio.uio_procp = p;
463 if (kth->ktr_len > 0) {
464 auio.uio_iovcnt++;
465 aiov[1].iov_base = kth->ktr_buf;
466 aiov[1].iov_len = kth->ktr_len;
467 auio.uio_resid += kth->ktr_len;
468 }
469 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
470 error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
471 VOP_UNLOCK(vp, 0, p);
472 if (!error)
473 return 0;
474
475
476
477 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
478 error);
479 for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
480 if (p->p_tracep == vp) {
481 p->p_traceflag = 0;
482 ktrsettracevnode(p, NULL);
483 }
484 }
485
486 return error;
487 }
488
489
490
491
492
493
494
495
496
497
498 int
499 ktrcanset(struct proc *callp, struct proc *targetp)
500 {
501 struct pcred *caller = callp->p_cred;
502 struct pcred *target = targetp->p_cred;
503
504 if ((caller->pc_ucred->cr_uid == target->p_ruid &&
505 target->p_ruid == target->p_svuid &&
506 caller->p_rgid == target->p_rgid &&
507 target->p_rgid == target->p_svgid &&
508 (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
509 !ISSET(targetp->p_flag, P_SUGID)) ||
510 caller->pc_ucred->cr_uid == 0)
511 return (1);
512
513 return (0);
514 }
515
516 #endif