summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_ktrace.c
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2000-07-02 08:08:09 +0000
committergreen <green@FreeBSD.org>2000-07-02 08:08:09 +0000
commit9707bc34b009d1e09d192ec84d1ddc8e8693006f (patch)
tree176c788b7d732a310aa42a0b4652b645bc735a99 /sys/kern/kern_ktrace.c
parentc350a86095dd249ad9e0371c7caaf6a5c52a0260 (diff)
downloadFreeBSD-src-9707bc34b009d1e09d192ec84d1ddc8e8693006f.zip
FreeBSD-src-9707bc34b009d1e09d192ec84d1ddc8e8693006f.tar.gz
Modify ktrace's general I/O tracing, ktrgenio(), to use a struct uio *
instead of a struct iovec * array and int len. Get rid of stupidly trying to allocate all of the memory and copyin()ing the entire iovec[], and instead just do the proper VOP_WRITE() in ktrwrite() using a copy of the struct uio that the syscall originally used. This solves the DoS which could easily be performed; to work around the DoS, one could also remove "options KTRACE" from the kernel. This is a very strong MFC candidate for 4.1. Found by: art@OpenBSD.org
Diffstat (limited to 'sys/kern/kern_ktrace.c')
-rw-r--r--sys/kern/kern_ktrace.c64
1 files changed, 29 insertions, 35 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index 1ca4e34..22f04e0 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -56,7 +56,7 @@ static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE");
#ifdef KTRACE
static struct ktr_header *ktrgetheader __P((int type));
-static void ktrwrite __P((struct vnode *, struct ktr_header *));
+static void ktrwrite __P((struct vnode *, struct ktr_header *, struct uio *));
static int ktrcanset __P((struct proc *,struct proc *));
static int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *));
static int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *));
@@ -102,7 +102,7 @@ ktrsyscall(vp, code, narg, args)
*argp++ = args[i];
kth->ktr_buf = (caddr_t)ktp;
kth->ktr_len = len;
- ktrwrite(vp, kth);
+ ktrwrite(vp, kth, NULL);
FREE(ktp, M_KTRACE);
FREE(kth, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
@@ -127,7 +127,7 @@ ktrsysret(vp, code, error, retval)
kth->ktr_buf = (caddr_t)&ktp;
kth->ktr_len = sizeof(struct ktr_sysret);
- ktrwrite(vp, kth);
+ ktrwrite(vp, kth, NULL);
FREE(kth, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
}
@@ -145,50 +145,36 @@ ktrnamei(vp, path)
kth->ktr_len = strlen(path);
kth->ktr_buf = path;
- ktrwrite(vp, kth);
+ ktrwrite(vp, kth, NULL);
FREE(kth, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
}
void
-ktrgenio(vp, fd, rw, iov, len, error)
+ktrgenio(vp, fd, rw, uio, error)
struct vnode *vp;
int fd;
enum uio_rw rw;
- register struct iovec *iov;
- int len, error;
+ struct uio *uio;
+ int error;
{
struct ktr_header *kth;
- register struct ktr_genio *ktp;
- register caddr_t cp;
- register int resid = len, cnt;
+ struct ktr_genio ktg;
struct proc *p = curproc; /* XXX */
if (error)
return;
p->p_traceflag |= KTRFAC_ACTIVE;
kth = ktrgetheader(KTR_GENIO);
- MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len,
- M_KTRACE, M_WAITOK);
- ktp->ktr_fd = fd;
- ktp->ktr_rw = rw;
- cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio));
- while (resid > 0) {
- if ((cnt = iov->iov_len) > resid)
- cnt = resid;
- if (copyin(iov->iov_base, cp, (unsigned)cnt))
- goto done;
- cp += cnt;
- resid -= cnt;
- iov++;
- }
- kth->ktr_buf = (caddr_t)ktp;
- kth->ktr_len = sizeof (struct ktr_genio) + len;
-
- ktrwrite(vp, kth);
-done:
+ ktg.ktr_fd = fd;
+ ktg.ktr_rw = rw;
+ kth->ktr_buf = (caddr_t)&ktg;
+ kth->ktr_len = sizeof(struct ktr_genio);
+ uio->uio_offset = 0;
+ uio->uio_rw = UIO_READ;
+
+ ktrwrite(vp, kth, uio);
FREE(kth, M_KTRACE);
- FREE(ktp, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
}
@@ -213,7 +199,7 @@ ktrpsig(vp, sig, action, mask, code)
kth->ktr_buf = (caddr_t)&kp;
kth->ktr_len = sizeof (struct ktr_psig);
- ktrwrite(vp, kth);
+ ktrwrite(vp, kth, NULL);
FREE(kth, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
}
@@ -234,7 +220,7 @@ ktrcsw(vp, out, user)
kth->ktr_buf = (caddr_t)&kc;
kth->ktr_len = sizeof (struct ktr_csw);
- ktrwrite(vp, kth);
+ ktrwrite(vp, kth, NULL);
FREE(kth, M_KTRACE);
p->p_traceflag &= ~KTRFAC_ACTIVE;
}
@@ -380,7 +366,7 @@ utrace(curp, uap)
if (!copyin(uap->addr, cp, uap->len)) {
kth->ktr_buf = cp;
kth->ktr_len = uap->len;
- ktrwrite(p->p_tracep, kth);
+ ktrwrite(p->p_tracep, kth, NULL);
}
FREE(kth, M_KTRACE);
FREE(cp, M_KTRACE);
@@ -463,9 +449,10 @@ ktrsetchildren(curp, top, ops, facs, vp)
}
static void
-ktrwrite(vp, kth)
+ktrwrite(vp, kth, uio)
struct vnode *vp;
register struct ktr_header *kth;
+ struct uio *uio;
{
struct uio auio;
struct iovec aiov[2];
@@ -488,9 +475,16 @@ ktrwrite(vp, kth)
aiov[1].iov_base = kth->ktr_buf;
aiov[1].iov_len = kth->ktr_len;
auio.uio_resid += kth->ktr_len;
+ if (uio != NULL)
+ kth->ktr_len += uio->uio_resid;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
+ (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred);
+ if (error == 0 && uio != NULL) {
+ (void)VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred);
+ }
VOP_UNLOCK(vp, 0, p);
if (!error)
return;
OpenPOWER on IntegriCloud