don't use database for getpwent; checked in by Keith Bostic
[unix-history] / usr / src / sys / kern / kern_ktrace.c
CommitLineData
2d68027d
MT
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 are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
d0efa41a 17 * @(#)kern_ktrace.c 7.4 (Berkeley) %G%
2d68027d
MT
18 */
19
20#ifdef KTRACE
21
22#include "param.h"
2d68027d 23#include "user.h"
2d68027d 24#include "proc.h"
c4ec2128
KM
25#include "file.h"
26#include "vnode.h"
2d68027d
MT
27#include "ktrace.h"
28#include "malloc.h"
29
f73d8bd6 30#include "syscalls.c"
2d68027d
MT
31
32extern int nsysent;
33extern char *syscallnames[];
34
f73d8bd6
MT
35int ktrace_nocheck = 1;
36
2d68027d
MT
37struct ktr_header *
38ktrgetheader(type)
39{
40 register struct ktr_header *kth;
41
42 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header),
43 M_TEMP, M_WAITOK);
2d68027d 44 kth->ktr_type = type;
f73d8bd6 45 microtime(&kth->ktr_time);
2d68027d 46 kth->ktr_pid = u.u_procp->p_pid;
a97cc92e 47 bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN);
2d68027d
MT
48 return (kth);
49}
50
c4ec2128
KM
51ktrsyscall(vp, code, narg)
52 struct vnode *vp;
2d68027d
MT
53{
54 struct ktr_header *kth = ktrgetheader(KTR_SYSCALL);
55 struct ktr_syscall *ktp;
56 register len = sizeof(struct ktr_syscall) + (narg * sizeof(int));
57 int *argp, i;
58
f73d8bd6 59 if (kth == NULL)
2d68027d 60 return;
2d68027d 61 MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK);
2d68027d
MT
62 ktp->ktr_code = code;
63 ktp->ktr_narg = narg;
64 argp = (int *)((char *)ktp + sizeof(struct ktr_syscall));
65 for (i = 0; i < narg; i++)
66 *argp++ = u.u_arg[i];
67 kth->ktr_buf = (caddr_t)ktp;
68 kth->ktr_len = len;
c4ec2128 69 ktrwrite(vp, kth);
2d68027d
MT
70 FREE(ktp, M_TEMP);
71 FREE(kth, M_TEMP);
72}
73
c4ec2128
KM
74ktrsysret(vp, code)
75 struct vnode *vp;
2d68027d
MT
76{
77 struct ktr_header *kth = ktrgetheader(KTR_SYSRET);
a97cc92e 78 struct ktr_sysret ktp;
2d68027d 79
f73d8bd6 80 if (kth == NULL)
2d68027d 81 return;
a97cc92e 82 ktp.ktr_code = code;
a97cc92e
MT
83 ktp.ktr_error = u.u_error;
84 ktp.ktr_retval = u.u_r.r_val1; /* what about val2 ? */
2d68027d 85
a97cc92e 86 kth->ktr_buf = (caddr_t)&ktp;
2d68027d
MT
87 kth->ktr_len = sizeof(struct ktr_sysret);
88
c4ec2128 89 ktrwrite(vp, kth);
2d68027d
MT
90 FREE(kth, M_TEMP);
91}
92
c4ec2128
KM
93ktrnamei(vp, path)
94 struct vnode *vp;
2d68027d
MT
95 char *path;
96{
97 struct ktr_header *kth = ktrgetheader(KTR_NAMEI);
98
f73d8bd6 99 if (kth == NULL)
2d68027d 100 return;
2d68027d
MT
101 kth->ktr_len = strlen(path);
102 kth->ktr_buf = path;
103
c4ec2128 104 ktrwrite(vp, kth);
2d68027d
MT
105 FREE(kth, M_TEMP);
106}
107
c4ec2128
KM
108ktrgenio(vp, fd, rw, iov, len)
109 struct vnode *vp;
f73d8bd6
MT
110 enum uio_rw rw;
111 register struct iovec *iov;
112{
113 struct ktr_header *kth = ktrgetheader(KTR_GENIO);
114 register struct ktr_genio *ktp;
115 register caddr_t cp;
116 register int resid = len, cnt;
117
118 if (kth == NULL || u.u_error)
119 return;
120 MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
121 M_TEMP, M_WAITOK);
f73d8bd6
MT
122 ktp->ktr_fd = fd;
123 ktp->ktr_rw = rw;
124 cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
125 while (resid > 0) {
126 if ((cnt = iov->iov_len) > resid)
127 cnt = resid;
128 if (copyin(iov->iov_base, cp, cnt))
129 goto done;
130 cp += cnt;
131 resid -= cnt;
132 iov++;
133 }
134 kth->ktr_buf = (caddr_t)ktp;
135 kth->ktr_len = sizeof (struct ktr_genio) + len;
136
c4ec2128 137 ktrwrite(vp, kth);
f73d8bd6
MT
138done:
139 FREE(kth, M_TEMP);
140 FREE(ktp, M_TEMP);
141}
142
a97cc92e
MT
143ktrpsig(vp, sig, action, mask, code)
144 struct vnode *vp;
145 sig_t action;
146{
147 struct ktr_header *kth = ktrgetheader(KTR_PSIG);
148 struct ktr_psig kp;
149
150 if (kth == NULL)
151 return;
152 kp.signo = (char)sig;
153 kp.action = action;
154 kp.mask = mask;
155 kp.code = code;
156 kth->ktr_buf = (caddr_t)&kp;
157 kth->ktr_len = sizeof (struct ktr_psig);
158
159 ktrwrite(vp, kth);
160 FREE(kth, M_TEMP);
161}
162
163/* Interface and common routines */
164
2d68027d
MT
165/*
166 * ktrace system call
167 */
168ktrace()
169{
2d68027d
MT
170 register struct a {
171 char *fname;
172 int ops;
173 int facs;
f73d8bd6 174 int pid;
2d68027d 175 } *uap = (struct a *)u.u_ap;
c4ec2128 176 register struct vnode *vp = NULL;
2d68027d
MT
177 register struct nameidata *ndp = &u.u_nd;
178 register struct proc *p;
a97cc92e 179 register ops = KTROP(uap->ops);
2d68027d 180 struct pgrp *pg;
2d68027d 181 register int facs = uap->facs;
f73d8bd6 182 register int ret = 0;
2d68027d
MT
183
184 /*
185 * Until security implications are thought through,
f73d8bd6 186 * limit tracing to root (unless ktrace_nocheck is set).
2d68027d 187 */
849cbd39 188 if (!ktrace_nocheck && (u.u_error = suser(u.u_cred, &u.u_acflag)))
2d68027d 189 return;
2d68027d
MT
190 if (ops != KTROP_CLEAR) {
191 /*
192 * an operation which requires a file argument.
193 */
2d68027d
MT
194 ndp->ni_segflg = UIO_USERSPACE;
195 ndp->ni_dirp = uap->fname;
c4ec2128 196 if (u.u_error = vn_open(ndp, FREAD|FWRITE, 0))
2d68027d 197 return;
c4ec2128
KM
198 vp = ndp->ni_vp;
199 if (vp->v_type != VREG) {
2d68027d 200 u.u_error = EACCES;
c4ec2128 201 vrele(vp);
2d68027d
MT
202 return;
203 }
2d68027d
MT
204 }
205 /*
206 * Clear all uses of the tracefile
207 */
208 if (ops == KTROP_CLEARFILE) {
209 for (p = allproc; p != NULL; p = p->p_nxt) {
c4ec2128 210 if (p->p_tracep == vp) {
2d68027d
MT
211 p->p_tracep = NULL;
212 p->p_traceflag = 0;
c4ec2128 213 vrele(vp);
2d68027d
MT
214 }
215 }
216 goto done;
217 }
2d68027d
MT
218 /*
219 * need something to (un)trace
220 */
221 if (!facs) {
222 u.u_error = EINVAL;
223 goto done;
224 }
a97cc92e
MT
225 /*
226 * doit
227 */
2d68027d
MT
228 if (uap->pid < 0) {
229 pg = pgfind(-uap->pid);
230 if (pg == NULL) {
231 u.u_error = ESRCH;
232 goto done;
233 }
234 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt)
a97cc92e 235 if (uap->ops&KTRFLAG_DESCEND)
c4ec2128 236 ret |= ktrsetchildren(p, ops, facs, vp);
2d68027d 237 else
c4ec2128 238 ret |= ktrops(p, ops, facs, vp);
2d68027d
MT
239
240 } else {
241 p = pfind(uap->pid);
242 if (p == NULL) {
243 u.u_error = ESRCH;
244 goto done;
245 }
a97cc92e 246 if (ops&KTRFLAG_DESCEND)
c4ec2128 247 ret |= ktrsetchildren(p, ops, facs, vp);
2d68027d 248 else
c4ec2128 249 ret |= ktrops(p, ops, facs, vp);
2d68027d 250 }
f73d8bd6
MT
251 if (!ret)
252 u.u_error = EPERM;
2d68027d 253done:
c4ec2128
KM
254 if (vp != NULL)
255 vrele(vp);
2d68027d
MT
256}
257
c4ec2128 258ktrops(p, ops, facs, vp)
2d68027d 259 struct proc *p;
c4ec2128 260 struct vnode *vp;
2d68027d 261{
f73d8bd6
MT
262
263 if (u.u_uid && u.u_uid != p->p_uid)
264 return 0;
2d68027d 265 if (ops == KTROP_SET) {
a97cc92e 266 if (p->p_tracep != vp) {
2d68027d
MT
267 /*
268 * if trace file already in use, relinquish
269 */
270 if (p->p_tracep != NULL)
c4ec2128 271 vrele(p->p_tracep);
2c0d2f20 272 VREF(vp);
c4ec2128 273 p->p_tracep = vp;
2d68027d
MT
274 }
275 p->p_traceflag |= facs;
276 } else {
277 /* KTROP_CLEAR */
a97cc92e
MT
278 if (((p->p_traceflag &= ~facs) & ~KTRFAC_INHERIT) == 0) {
279 /* no more tracing */
280 p->p_traceflag = 0;
2d68027d 281 if (p->p_tracep != NULL) {
c4ec2128 282 vrele(p->p_tracep);
2d68027d
MT
283 p->p_tracep = NULL;
284 }
2d68027d
MT
285 }
286 }
f73d8bd6
MT
287
288 return 1;
2d68027d 289}
f73d8bd6 290
c4ec2128 291ktrsetchildren(top, ops, facs, vp)
2d68027d 292 struct proc *top;
c4ec2128 293 struct vnode *vp;
2d68027d
MT
294{
295 register struct proc *p;
296 register int ndx;
f73d8bd6 297 register int ret = 0;
2d68027d
MT
298
299 p = top;
300 for (;;) {
a97cc92e 301 ret |= ktrops(p, ops, facs, vp);
2d68027d
MT
302 /*
303 * If this process has children, descend to them next,
304 * otherwise do any siblings, and if done with this level,
305 * follow back up the tree (but not past top).
306 */
307 if (p->p_cptr)
308 p = p->p_cptr;
309 else if (p == top)
f73d8bd6 310 return ret;
2d68027d
MT
311 else if (p->p_osptr)
312 p = p->p_osptr;
313 else for (;;) {
314 p = p->p_pptr;
315 if (p == top)
f73d8bd6 316 return ret;
2d68027d
MT
317 if (p->p_osptr) {
318 p = p->p_osptr;
319 break;
320 }
321 }
322 }
f73d8bd6 323 /*NOTREACHED*/
2d68027d
MT
324}
325
c4ec2128
KM
326ktrwrite(vp, kth)
327 struct vnode *vp;
328 register struct ktr_header *kth;
2d68027d 329{
c4ec2128
KM
330 struct uio auio;
331 struct iovec aiov[2];
aeb44310 332 int error;
c4ec2128
KM
333
334 if (vp == NULL)
f73d8bd6 335 return;
c4ec2128
KM
336 auio.uio_iov = &aiov[0];
337 auio.uio_offset = 0;
338 auio.uio_segflg = UIO_SYSSPACE;
339 auio.uio_rw = UIO_WRITE;
340 aiov[0].iov_base = (caddr_t)kth;
341 aiov[0].iov_len = sizeof(struct ktr_header);
342 auio.uio_resid = sizeof(struct ktr_header);
343 auio.uio_iovcnt = 1;
2d68027d 344 if (kth->ktr_len > 0) {
c4ec2128
KM
345 auio.uio_iovcnt++;
346 aiov[1].iov_base = kth->ktr_buf;
347 aiov[1].iov_len = kth->ktr_len;
348 auio.uio_resid += kth->ktr_len;
2d68027d 349 }
aeb44310
KM
350 VOP_LOCK(vp);
351 error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred);
352 VOP_UNLOCK(vp);
2d68027d 353}
2d68027d 354#endif