ktrace: Avoid recursion in namei()
sys_ktrace() calls namei(), which may call ktrnamei(). But sys_ktrace() also calls ktrace_enter() first, so if the caller is itself being traced, the assertion in ktrace_enter() is triggered. And, ktrnamei() does not check for recursion like most other ktrace ops do. Fix the bug by simply deferring the ktrace_enter() call. Also make the parameter to ktrnamei() const and convert to ANSI. Reported by: syzbot+d0a4de45e58d3c08af4b@syzkaller.appspotmail.com Reviewed by: kib MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D30340
This commit is contained in:
parent
e67ef6ce66
commit
e4b16f2fb1
@ -698,8 +698,7 @@ ktruserret(struct thread *td)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ktrnamei(path)
|
ktrnamei(const char *path)
|
||||||
char *path;
|
|
||||||
{
|
{
|
||||||
struct ktr_request *req;
|
struct ktr_request *req;
|
||||||
int namelen;
|
int namelen;
|
||||||
@ -1017,7 +1016,6 @@ sys_ktrace(struct thread *td, struct ktrace_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
kiop = NULL;
|
kiop = NULL;
|
||||||
ktrace_enter(td);
|
|
||||||
if (ops != KTROP_CLEAR) {
|
if (ops != KTROP_CLEAR) {
|
||||||
/*
|
/*
|
||||||
* an operation which requires a file argument.
|
* an operation which requires a file argument.
|
||||||
@ -1025,23 +1023,22 @@ sys_ktrace(struct thread *td, struct ktrace_args *uap)
|
|||||||
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td);
|
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td);
|
||||||
flags = FREAD | FWRITE | O_NOFOLLOW;
|
flags = FREAD | FWRITE | O_NOFOLLOW;
|
||||||
error = vn_open(&nd, &flags, 0, NULL);
|
error = vn_open(&nd, &flags, 0, NULL);
|
||||||
if (error) {
|
if (error)
|
||||||
ktrace_exit(td);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
|
||||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||||
vp = nd.ni_vp;
|
vp = nd.ni_vp;
|
||||||
VOP_UNLOCK(vp);
|
VOP_UNLOCK(vp);
|
||||||
if (vp->v_type != VREG) {
|
if (vp->v_type != VREG) {
|
||||||
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
|
(void)vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
|
||||||
ktrace_exit(td);
|
|
||||||
return (EACCES);
|
return (EACCES);
|
||||||
}
|
}
|
||||||
kiop = ktr_io_params_alloc(td, vp);
|
kiop = ktr_io_params_alloc(td, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear all uses of the tracefile.
|
* Clear all uses of the tracefile.
|
||||||
*/
|
*/
|
||||||
|
ktrace_enter(td);
|
||||||
if (ops == KTROP_CLEARFILE) {
|
if (ops == KTROP_CLEARFILE) {
|
||||||
restart:
|
restart:
|
||||||
sx_slock(&allproc_lock);
|
sx_slock(&allproc_lock);
|
||||||
|
@ -269,7 +269,7 @@ struct ktr_io_params;
|
|||||||
|
|
||||||
struct vnode *ktr_get_tracevp(struct proc *, bool);
|
struct vnode *ktr_get_tracevp(struct proc *, bool);
|
||||||
void ktr_io_params_free(struct ktr_io_params *);
|
void ktr_io_params_free(struct ktr_io_params *);
|
||||||
void ktrnamei(char *);
|
void ktrnamei(const char *);
|
||||||
void ktrcsw(int, int, const char *);
|
void ktrcsw(int, int, const char *);
|
||||||
void ktrpsig(int, sig_t, sigset_t *, int);
|
void ktrpsig(int, sig_t, sigset_t *, int);
|
||||||
void ktrfault(vm_offset_t, int);
|
void ktrfault(vm_offset_t, int);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user