* Copyright (c) 1989 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)kern_ktrace.c 7.2 (Berkeley) %G%
extern char *syscallnames
[];
register struct ktr_header
*kth
;
MALLOC(kth
, struct ktr_header
*, sizeof (struct ktr_header
),
microtime(&kth
->ktr_time
);
kth
->ktr_pid
= u
.u_procp
->p_pid
;
bcopy(u
.u_comm
, kth
->ktr_comm
, MAXCOMLEN
);
ktrsyscall(vp
, code
, narg
)
struct ktr_header
*kth
= ktrgetheader(KTR_SYSCALL
);
register len
= sizeof(struct ktr_syscall
) + (narg
* sizeof(int));
MALLOC(ktp
, struct ktr_syscall
*, len
, M_TEMP
, M_WAITOK
);
argp
= (int *)((char *)ktp
+ sizeof(struct ktr_syscall
));
for (i
= 0; i
< narg
; i
++)
kth
->ktr_buf
= (caddr_t
)ktp
;
struct ktr_header
*kth
= ktrgetheader(KTR_SYSRET
);
MALLOC(ktp
, struct ktr_sysret
*, sizeof(struct ktr_sysret
),
ktp
->ktr_eosys
= u
.u_eosys
;
ktp
->ktr_error
= u
.u_error
;
ktp
->ktr_retval
= u
.u_r
.r_val1
; /* what about val2 ? */
kth
->ktr_buf
= (caddr_t
)ktp
;
kth
->ktr_len
= sizeof(struct ktr_sysret
);
struct ktr_header
*kth
= ktrgetheader(KTR_NAMEI
);
kth
->ktr_len
= strlen(path
);
ktrgenio(vp
, fd
, rw
, iov
, len
)
register struct iovec
*iov
;
struct ktr_header
*kth
= ktrgetheader(KTR_GENIO
);
register struct ktr_genio
*ktp
;
register int resid
= len
, cnt
;
if (kth
== NULL
|| u
.u_error
)
MALLOC(ktp
, struct ktr_genio
*, sizeof(struct ktr_genio
) + len
,
cp
= (caddr_t
)((char *)ktp
+ sizeof (struct ktr_genio
));
if ((cnt
= iov
->iov_len
) > resid
)
if (copyin(iov
->iov_base
, cp
, cnt
))
kth
->ktr_buf
= (caddr_t
)ktp
;
kth
->ktr_len
= sizeof (struct ktr_genio
) + len
;
} *uap
= (struct a
*)u
.u_ap
;
register struct vnode
*vp
= NULL
;
register struct nameidata
*ndp
= &u
.u_nd
;
register int ops
= uap
->ops
&0x3;
register int facs
= uap
->facs
;
* Until security implications are thought through,
* limit tracing to root (unless ktrace_nocheck is set).
if (!ktrace_nocheck
&& (u
.u_error
= suser(u
.u_cred
, &u
.u_acflag
)))
if (ops
!= KTROP_CLEAR
) {
* an operation which requires a file argument.
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (u
.u_error
= vn_open(ndp
, FREAD
|FWRITE
, 0))
if (vp
->v_type
!= VREG
) {
* Clear all uses of the tracefile
if (ops
== KTROP_CLEARFILE
) {
for (p
= allproc
; p
!= NULL
; p
= p
->p_nxt
) {
* need something to (un)trace
for (p
= pg
->pg_mem
; p
!= NULL
; p
= p
->p_pgrpnxt
)
if (uap
->ops
&KTROP_INHERITFLAG
)
ret
|= ktrsetchildren(p
, ops
, facs
, vp
);
ret
|= ktrops(p
, ops
, facs
, vp
);
if (uap
->ops
&KTROP_INHERITFLAG
)
ret
|= ktrsetchildren(p
, ops
, facs
, vp
);
ret
|= ktrops(p
, ops
, facs
, vp
);
if (u
.u_uid
&& u
.u_uid
!= p
->p_uid
)
* if trace file already in use, relinquish
if ((p
->p_traceflag
&= ~facs
) == 0) {
if (p
->p_tracep
!= NULL
) {
ktrsetchildren(top
, ops
, facs
, vp
)
if ((ret
|= ktrops(p
, ops
, facs
, vp
)) && ops
== KTROP_SET
)
* If this process has children, descend to them next,
* otherwise do any siblings, and if done with this level,
* follow back up the tree (but not past top).
register struct ktr_header
*kth
;
auio
.uio_segflg
= UIO_SYSSPACE
;
aiov
[0].iov_base
= (caddr_t
)kth
;
aiov
[0].iov_len
= sizeof(struct ktr_header
);
auio
.uio_resid
= sizeof(struct ktr_header
);
aiov
[1].iov_base
= kth
->ktr_buf
;
aiov
[1].iov_len
= kth
->ktr_len
;
auio
.uio_resid
+= kth
->ktr_len
;
error
= VOP_WRITE(vp
, &auio
, IO_UNIT
|IO_APPEND
, u
.u_cred
);