|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)kern_ktrace.c 7.15 (Berkeley) 6/21/91
34: */
35:
36: #ifdef KTRACE
37:
38: #include "param.h"
39: #include "proc.h"
40: #include "file.h"
41: #include "namei.h"
42: #include "vnode.h"
43: #include "ktrace.h"
44: #include "malloc.h"
45: #include "syslog.h"
46:
47: struct ktr_header *
48: ktrgetheader(type)
49: {
50: register struct ktr_header *kth;
51: struct proc *p = curproc; /* XXX */
52:
53: MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header),
54: M_TEMP, M_WAITOK);
55: kth->ktr_type = type;
56: microtime(&kth->ktr_time);
57: kth->ktr_pid = p->p_pid;
58: bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN);
59: return (kth);
60: }
61:
62: ktrsyscall(vp, code, narg, args)
63: struct vnode *vp;
64: int code, narg, args[];
65: {
66: struct ktr_header *kth = ktrgetheader(KTR_SYSCALL);
67: struct ktr_syscall *ktp;
68: register len = sizeof(struct ktr_syscall) + (narg * sizeof(int));
69: int *argp, i;
70:
71: MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
72: ktp->ktr_code = code;
73: ktp->ktr_narg = narg;
74: argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
75: for (i = 0; i < narg; i++)
76: *argp++ = args[i];
77: kth->ktr_buf = (caddr_t)ktp;
78: kth->ktr_len = len;
79: ktrwrite(vp, kth);
80: FREE(ktp, M_TEMP);
81: FREE(kth, M_TEMP);
82: }
83:
84: ktrsysret(vp, code, error, retval)
85: struct vnode *vp;
86: int code, error, retval;
87: {
88: struct ktr_header *kth = ktrgetheader(KTR_SYSRET);
89: struct ktr_sysret ktp;
90:
91: ktp.ktr_code = code;
92: ktp.ktr_error = error;
93: ktp.ktr_retval = retval; /* what about val2 ? */
94:
95: kth->ktr_buf = (caddr_t)&ktp;
96: kth->ktr_len = sizeof(struct ktr_sysret);
97:
98: ktrwrite(vp, kth);
99: FREE(kth, M_TEMP);
100: }
101:
102: ktrnamei(vp, path)
103: struct vnode *vp;
104: char *path;
105: {
106: struct ktr_header *kth = ktrgetheader(KTR_NAMEI);
107:
108: kth->ktr_len = strlen(path);
109: kth->ktr_buf = path;
110:
111: ktrwrite(vp, kth);
112: FREE(kth, M_TEMP);
113: }
114:
115: ktrgenio(vp, fd, rw, iov, len, error)
116: struct vnode *vp;
117: int fd;
118: enum uio_rw rw;
119: register struct iovec *iov;
120: {
121: struct ktr_header *kth = ktrgetheader(KTR_GENIO);
122: register struct ktr_genio *ktp;
123: register caddr_t cp;
124: register int resid = len, cnt;
125:
126: if (error)
127: return;
128: MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
129: M_TEMP, M_WAITOK);
130: ktp->ktr_fd = fd;
131: ktp->ktr_rw = rw;
132: cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
133: while (resid > 0) {
134: if ((cnt = iov->iov_len) > resid)
135: cnt = resid;
136: if (copyin(iov->iov_base, cp, (unsigned)cnt))
137: goto done;
138: cp += cnt;
139: resid -= cnt;
140: iov++;
141: }
142: kth->ktr_buf = (caddr_t)ktp;
143: kth->ktr_len = sizeof (struct ktr_genio) + len;
144:
145: ktrwrite(vp, kth);
146: done:
147: FREE(kth, M_TEMP);
148: FREE(ktp, M_TEMP);
149: }
150:
151: ktrpsig(vp, sig, action, mask, code)
152: struct vnode *vp;
153: sig_t action;
154: {
155: struct ktr_header *kth = ktrgetheader(KTR_PSIG);
156: struct ktr_psig kp;
157:
158: kp.signo = (char)sig;
159: kp.action = action;
160: kp.mask = mask;
161: kp.code = code;
162: kth->ktr_buf = (caddr_t)&kp;
163: kth->ktr_len = sizeof (struct ktr_psig);
164:
165: ktrwrite(vp, kth);
166: FREE(kth, M_TEMP);
167: }
168:
169: /* Interface and common routines */
170:
171: /*
172: * ktrace system call
173: */
174: /* ARGSUSED */
175: ktrace(curp, uap, retval)
176: struct proc *curp;
177: register struct args {
178: char *fname;
179: int ops;
180: int facs;
181: int pid;
182: } *uap;
183: int *retval;
184: {
185: register struct vnode *vp = NULL;
186: register struct proc *p;
187: struct pgrp *pg;
188: int facs = uap->facs & ~KTRFAC_ROOT;
189: int ops = KTROP(uap->ops);
190: int descend = uap->ops & KTRFLAG_DESCEND;
191: int ret = 0;
192: int error = 0;
193: struct nameidata nd;
194:
195: if (ops != KTROP_CLEAR) {
196: /*
197: * an operation which requires a file argument.
198: */
199: nd.ni_segflg = UIO_USERSPACE;
200: nd.ni_dirp = uap->fname;
201: if (error = vn_open(&nd, curp, FREAD|FWRITE, 0))
202: return (error);
203: vp = nd.ni_vp;
204: VOP_UNLOCK(vp);
205: if (vp->v_type != VREG) {
206: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
207: return (EACCES);
208: }
209: }
210: /*
211: * Clear all uses of the tracefile
212: */
213: if (ops == KTROP_CLEARFILE) {
214: for (p = allproc; p != NULL; p = p->p_nxt) {
215: if (p->p_tracep == vp) {
216: if (ktrcanset(curp, p)) {
217: p->p_tracep = NULL;
218: p->p_traceflag = 0;
219: (void) vn_close(vp, FREAD|FWRITE,
220: p->p_ucred, p);
221: } else
222: error = EPERM;
223: }
224: }
225: goto done;
226: }
227: /*
228: * need something to (un)trace (XXX - why is this here?)
229: */
230: if (!facs) {
231: error = EINVAL;
232: goto done;
233: }
234: /*
235: * do it
236: */
237: if (uap->pid < 0) {
238: /*
239: * by process group
240: */
241: pg = pgfind(-uap->pid);
242: if (pg == NULL) {
243: error = ESRCH;
244: goto done;
245: }
246: for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt)
247: if (descend)
248: ret |= ktrsetchildren(curp, p, ops, facs, vp);
249: else
250: ret |= ktrops(curp, p, ops, facs, vp);
251:
252: } else {
253: /*
254: * by pid
255: */
256: p = pfind(uap->pid);
257: if (p == NULL) {
258: error = ESRCH;
259: goto done;
260: }
261: if (descend)
262: ret |= ktrsetchildren(curp, p, ops, facs, vp);
263: else
264: ret |= ktrops(curp, p, ops, facs, vp);
265: }
266: if (!ret)
267: error = EPERM;
268: done:
269: if (vp != NULL)
270: (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
271: return (error);
272: }
273:
274: ktrops(curp, p, ops, facs, vp)
275: struct proc *curp, *p;
276: struct vnode *vp;
277: {
278:
279: if (!ktrcanset(curp, p))
280: return (0);
281: if (ops == KTROP_SET) {
282: if (p->p_tracep != vp) {
283: /*
284: * if trace file already in use, relinquish
285: */
286: if (p->p_tracep != NULL)
287: vrele(p->p_tracep);
288: VREF(vp);
289: p->p_tracep = vp;
290: }
291: p->p_traceflag |= facs;
292: if (curp->p_ucred->cr_uid == 0)
293: p->p_traceflag |= KTRFAC_ROOT;
294: } else {
295: /* KTROP_CLEAR */
296: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
297: /* no more tracing */
298: p->p_traceflag = 0;
299: if (p->p_tracep != NULL) {
300: vrele(p->p_tracep);
301: p->p_tracep = NULL;
302: }
303: }
304: }
305:
306: return (1);
307: }
308:
309: ktrsetchildren(curp, top, ops, facs, vp)
310: struct proc *curp, *top;
311: struct vnode *vp;
312: {
313: register struct proc *p;
314: register int ret = 0;
315:
316: p = top;
317: for (;;) {
318: ret |= ktrops(curp, p, ops, facs, vp);
319: /*
320: * If this process has children, descend to them next,
321: * otherwise do any siblings, and if done with this level,
322: * follow back up the tree (but not past top).
323: */
324: if (p->p_cptr)
325: p = p->p_cptr;
326: else if (p == top)
327: return (ret);
328: else if (p->p_osptr)
329: p = p->p_osptr;
330: else for (;;) {
331: p = p->p_pptr;
332: if (p == top)
333: return (ret);
334: if (p->p_osptr) {
335: p = p->p_osptr;
336: break;
337: }
338: }
339: }
340: /*NOTREACHED*/
341: }
342:
343: ktrwrite(vp, kth)
344: struct vnode *vp;
345: register struct ktr_header *kth;
346: {
347: struct uio auio;
348: struct iovec aiov[2];
349: register struct proc *p = curproc; /* XXX */
350: int error;
351:
352: if (vp == NULL)
353: return;
354: auio.uio_iov = &aiov[0];
355: auio.uio_offset = 0;
356: auio.uio_segflg = UIO_SYSSPACE;
357: auio.uio_rw = UIO_WRITE;
358: aiov[0].iov_base = (caddr_t)kth;
359: aiov[0].iov_len = sizeof(struct ktr_header);
360: auio.uio_resid = sizeof(struct ktr_header);
361: auio.uio_iovcnt = 1;
362: auio.uio_procp = (struct proc *)0;
363: if (kth->ktr_len > 0) {
364: auio.uio_iovcnt++;
365: aiov[1].iov_base = kth->ktr_buf;
366: aiov[1].iov_len = kth->ktr_len;
367: auio.uio_resid += kth->ktr_len;
368: }
369: VOP_LOCK(vp);
370: error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
371: VOP_UNLOCK(vp);
372: if (!error)
373: return;
374: /*
375: * If error encountered, give up tracing on this vnode.
376: */
377: log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
378: error);
379: for (p = allproc; p != NULL; p = p->p_nxt) {
380: if (p->p_tracep == vp) {
381: p->p_tracep = NULL;
382: p->p_traceflag = 0;
383: vrele(vp);
384: }
385: }
386: }
387:
388: /*
389: * Return true if caller has permission to set the ktracing state
390: * of target. Essentially, the target can't possess any
391: * more permissions than the caller. KTRFAC_ROOT signifies that
392: * root previously set the tracing status on the target process, and
393: * so, only root may further change it.
394: *
395: * TODO: check groups. use caller effective gid.
396: */
397: ktrcanset(callp, targetp)
398: struct proc *callp, *targetp;
399: {
400: register struct pcred *caller = callp->p_cred;
401: register struct pcred *target = targetp->p_cred;
402:
403: if ((caller->pc_ucred->cr_uid == target->p_ruid &&
404: target->p_ruid == target->p_svuid &&
405: caller->p_rgid == target->p_rgid && /* XXX */
406: target->p_rgid == target->p_svgid &&
407: (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
408: caller->pc_ucred->cr_uid == 0)
409: return (1);
410:
411: return (0);
412: }
413:
414: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.