|
|
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: #include "param.h"
37: #include "proc.h"
38: #include "file.h"
39: #include "namei.h"
40: #include "vnode.h"
41: #include "ktrace.h"
42: #include "malloc.h"
43: #include "syslog.h"
44:
45: struct ktr_header *
46: ktrgetheader(type)
47: {
48: register struct ktr_header *kth;
49: struct proc *p = curproc; /* XXX */
50:
51: MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header),
52: M_TEMP, M_WAITOK);
53: kth->ktr_type = type;
54: microtime(&kth->ktr_time);
55: kth->ktr_pid = p->p_pid;
56: bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN);
57: return (kth);
58: }
59:
60: ktrsyscall(vp, code, narg, args)
61: struct vnode *vp;
62: int code, narg, args[];
63: {
64: struct ktr_header *kth = ktrgetheader(KTR_SYSCALL);
65: struct ktr_syscall *ktp;
66: register len = sizeof(struct ktr_syscall) + (narg * sizeof(int));
67: int *argp, i;
68:
69: MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
70: ktp->ktr_code = code;
71: ktp->ktr_narg = narg;
72: argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
73: for (i = 0; i < narg; i++)
74: *argp++ = args[i];
75: kth->ktr_buf = (caddr_t)ktp;
76: kth->ktr_len = len;
77: ktrwrite(vp, kth);
78: FREE(ktp, M_TEMP);
79: FREE(kth, M_TEMP);
80: }
81:
82: ktrsysret(vp, code, error, retval)
83: struct vnode *vp;
84: int code, error, retval;
85: {
86: struct ktr_header *kth = ktrgetheader(KTR_SYSRET);
87: struct ktr_sysret ktp;
88:
89: ktp.ktr_code = code;
90: ktp.ktr_error = error;
91: ktp.ktr_retval = retval; /* what about val2 ? */
92:
93: kth->ktr_buf = (caddr_t)&ktp;
94: kth->ktr_len = sizeof(struct ktr_sysret);
95:
96: ktrwrite(vp, kth);
97: FREE(kth, M_TEMP);
98: }
99:
100: ktrnamei(vp, path)
101: struct vnode *vp;
102: char *path;
103: {
104: struct ktr_header *kth = ktrgetheader(KTR_NAMEI);
105:
106: kth->ktr_len = strlen(path);
107: kth->ktr_buf = path;
108:
109: ktrwrite(vp, kth);
110: FREE(kth, M_TEMP);
111: }
112:
113: ktrgenio(vp, fd, rw, iov, len, error)
114: struct vnode *vp;
115: int fd;
116: enum uio_rw rw;
117: register struct iovec *iov;
118: {
119: struct ktr_header *kth = ktrgetheader(KTR_GENIO);
120: register struct ktr_genio *ktp;
121: register caddr_t cp;
122: register int resid = len, cnt;
123:
124: if (error)
125: return;
126: MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
127: M_TEMP, M_WAITOK);
128: ktp->ktr_fd = fd;
129: ktp->ktr_rw = rw;
130: cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
131: while (resid > 0) {
132: if ((cnt = iov->iov_len) > resid)
133: cnt = resid;
134: if (copyin(iov->iov_base, cp, (unsigned)cnt))
135: goto done;
136: cp += cnt;
137: resid -= cnt;
138: iov++;
139: }
140: kth->ktr_buf = (caddr_t)ktp;
141: kth->ktr_len = sizeof (struct ktr_genio) + len;
142:
143: ktrwrite(vp, kth);
144: done:
145: FREE(kth, M_TEMP);
146: FREE(ktp, M_TEMP);
147: }
148:
149: ktrpsig(vp, sig, action, mask, code)
150: struct vnode *vp;
151: sig_t action;
152: {
153: struct ktr_header *kth = ktrgetheader(KTR_PSIG);
154: struct ktr_psig kp;
155:
156: kp.signo = (char)sig;
157: kp.action = action;
158: kp.mask = mask;
159: kp.code = code;
160: kth->ktr_buf = (caddr_t)&kp;
161: kth->ktr_len = sizeof (struct ktr_psig);
162:
163: ktrwrite(vp, kth);
164: FREE(kth, M_TEMP);
165: }
166:
167: /* Interface and common routines */
168:
169: /*
170: * ktrace system call
171: */
172: /* ARGSUSED */
173: ktrace(curp, uap, retval)
174: struct proc *curp;
175: register struct args {
176: char *fname;
177: int ops;
178: int facs;
179: int pid;
180: } *uap;
181: int *retval;
182: {
183: register struct vnode *vp = NULL;
184: register struct proc *p;
185: struct pgrp *pg;
186: int facs = uap->facs & ~KTRFAC_ROOT;
187: int ops = KTROP(uap->ops);
188: int descend = uap->ops & KTRFLAG_DESCEND;
189: int ret = 0;
190: int error = 0;
191: struct nameidata nd;
192:
193: if (ops != KTROP_CLEAR) {
194: /*
195: * an operation which requires a file argument.
196: */
197: nd.ni_segflg = UIO_USERSPACE;
198: nd.ni_dirp = uap->fname;
199: if (error = vn_open(&nd, curp, FREAD|FWRITE, 0))
200: return (error);
201: vp = nd.ni_vp;
202: VOP_UNLOCK(vp);
203: if (vp->v_type != VREG) {
204: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
205: return (EACCES);
206: }
207: }
208: /*
209: * Clear all uses of the tracefile
210: */
211: if (ops == KTROP_CLEARFILE) {
212: for (p = allproc; p != NULL; p = p->p_nxt) {
213: if (p->p_tracep == vp) {
214: if (ktrcanset(curp, p)) {
215: p->p_tracep = NULL;
216: p->p_traceflag = 0;
217: (void) vn_close(vp, FREAD|FWRITE,
218: p->p_ucred, p);
219: } else
220: error = EPERM;
221: }
222: }
223: goto done;
224: }
225: /*
226: * need something to (un)trace (XXX - why is this here?)
227: */
228: if (!facs) {
229: error = EINVAL;
230: goto done;
231: }
232: /*
233: * do it
234: */
235: if (uap->pid < 0) {
236: /*
237: * by process group
238: */
239: pg = pgfind(-uap->pid);
240: if (pg == NULL) {
241: error = ESRCH;
242: goto done;
243: }
244: for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt)
245: if (descend)
246: ret |= ktrsetchildren(curp, p, ops, facs, vp);
247: else
248: ret |= ktrops(curp, p, ops, facs, vp);
249:
250: } else {
251: /*
252: * by pid
253: */
254: p = pfind(uap->pid);
255: if (p == NULL) {
256: error = ESRCH;
257: goto done;
258: }
259: if (descend)
260: ret |= ktrsetchildren(curp, p, ops, facs, vp);
261: else
262: ret |= ktrops(curp, p, ops, facs, vp);
263: }
264: if (!ret)
265: error = EPERM;
266: done:
267: if (vp != NULL)
268: (void) vn_close(vp, FWRITE, curp->p_ucred, curp);
269: return (error);
270: }
271:
272: ktrops(curp, p, ops, facs, vp)
273: struct proc *curp, *p;
274: struct vnode *vp;
275: {
276:
277: if (!ktrcanset(curp, p))
278: return (0);
279: if (ops == KTROP_SET) {
280: if (p->p_tracep != vp) {
281: /*
282: * if trace file already in use, relinquish
283: */
284: if (p->p_tracep != NULL)
285: vrele(p->p_tracep);
286: VREF(vp);
287: p->p_tracep = vp;
288: }
289: p->p_traceflag |= facs;
290: if (curp->p_ucred->cr_uid == 0)
291: p->p_traceflag |= KTRFAC_ROOT;
292: } else {
293: /* KTROP_CLEAR */
294: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
295: /* no more tracing */
296: p->p_traceflag = 0;
297: if (p->p_tracep != NULL) {
298: vrele(p->p_tracep);
299: p->p_tracep = NULL;
300: }
301: }
302: }
303:
304: return (1);
305: }
306:
307: ktrsetchildren(curp, top, ops, facs, vp)
308: struct proc *curp, *top;
309: struct vnode *vp;
310: {
311: register struct proc *p;
312: register int ret = 0;
313:
314: p = top;
315: for (;;) {
316: ret |= ktrops(curp, p, ops, facs, vp);
317: /*
318: * If this process has children, descend to them next,
319: * otherwise do any siblings, and if done with this level,
320: * follow back up the tree (but not past top).
321: */
322: if (p->p_cptr)
323: p = p->p_cptr;
324: else if (p == top)
325: return (ret);
326: else if (p->p_osptr)
327: p = p->p_osptr;
328: else for (;;) {
329: p = p->p_pptr;
330: if (p == top)
331: return (ret);
332: if (p->p_osptr) {
333: p = p->p_osptr;
334: break;
335: }
336: }
337: }
338: /*NOTREACHED*/
339: }
340:
341: ktrwrite(vp, kth)
342: struct vnode *vp;
343: register struct ktr_header *kth;
344: {
345: struct uio auio;
346: struct iovec aiov[2];
347: register struct proc *p = curproc; /* XXX */
348: int error;
349:
350: if (vp == NULL)
351: return;
352: auio.uio_iov = &aiov[0];
353: auio.uio_offset = 0;
354: auio.uio_segflg = UIO_SYSSPACE;
355: auio.uio_rw = UIO_WRITE;
356: aiov[0].iov_base = (caddr_t)kth;
357: aiov[0].iov_len = sizeof(struct ktr_header);
358: auio.uio_resid = sizeof(struct ktr_header);
359: auio.uio_iovcnt = 1;
360: auio.uio_procp = (struct proc *)0;
361: if (kth->ktr_len > 0) {
362: auio.uio_iovcnt++;
363: aiov[1].iov_base = kth->ktr_buf;
364: aiov[1].iov_len = kth->ktr_len;
365: auio.uio_resid += kth->ktr_len;
366: }
367: VOP_LOCK(vp);
368: error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
369: VOP_UNLOCK(vp);
370: if (!error)
371: return;
372: /*
373: * If error encountered, give up tracing on this vnode.
374: */
375: log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
376: error);
377: for (p = allproc; p != NULL; p = p->p_nxt) {
378: if (p->p_tracep == vp) {
379: p->p_tracep = NULL;
380: p->p_traceflag = 0;
381: vrele(vp);
382: }
383: }
384: }
385:
386: /*
387: * Return true if caller has permission to set the ktracing state
388: * of target. Essentially, the target can't possess any
389: * more permissions than the caller. KTRFAC_ROOT signifies that
390: * root previously set the tracing status on the target process, and
391: * so, only root may further change it.
392: *
393: * TODO: check groups. use caller effective gid.
394: */
395: ktrcanset(callp, targetp)
396: struct proc *callp, *targetp;
397: {
398: register struct pcred *caller = callp->p_cred;
399: register struct pcred *target = targetp->p_cred;
400:
401: if ((caller->pc_ucred->cr_uid == target->p_ruid &&
402: target->p_ruid == target->p_svuid &&
403: caller->p_rgid == target->p_rgid && /* XXX */
404: target->p_rgid == target->p_svgid &&
405: (targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
406: caller->pc_ucred->cr_uid == 0)
407: return (1);
408:
409: return (0);
410: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.