diff options
author | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2008-01-24 17:10:19 +0000 |
---|---|---|
committer | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2008-01-24 17:10:19 +0000 |
commit | a8afa221cca994c1c967598ea9154e852a246917 (patch) | |
tree | 7068fef549babbf1bf671437caf732a4825b963a /sys/kern/vfs_aio.c | |
parent | eee74fe05d86b6be3ee663ef31aaa0a087f8e2c0 (diff) | |
download | src-a8afa221cca994c1c967598ea9154e852a246917.tar.gz src-a8afa221cca994c1c967598ea9154e852a246917.zip |
When asked to use kqueue, AIO stores its internal state in the
`kn_sdata' member of the newly registered knote. The problem is that
this member is overwritten by a call to kevent(2) with the EV_ADD flag,
targetted at the same kevent/knote. For instance, a userland application
may set the pointer to NULL, leading to a panic.
A testcase was provided by the submitter.
PR: kern/118911
Submitted by: MOROHOSHI Akihiko <moro@remus.dti.ne.jp>
MFC after: 1 day
Notes
Notes:
svn path=/head/; revision=175642
Diffstat (limited to 'sys/kern/vfs_aio.c')
-rw-r--r-- | sys/kern/vfs_aio.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index e958d5476f32..877ddf139a51 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -2251,6 +2251,7 @@ filt_aioattach(struct knote *kn) */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); + kn->kn_ptr.p_aio = aiocbe; kn->kn_flags &= ~EV_FLAG1; knlist_add(&aiocbe->klist, kn, 0); @@ -2262,7 +2263,7 @@ filt_aioattach(struct knote *kn) static void filt_aiodetach(struct knote *kn) { - struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; + struct aiocblist *aiocbe = kn->kn_ptr.p_aio; if (!knlist_empty(&aiocbe->klist)) knlist_remove(&aiocbe->klist, kn, 0); @@ -2273,7 +2274,7 @@ filt_aiodetach(struct knote *kn) static int filt_aio(struct knote *kn, long hint) { - struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; + struct aiocblist *aiocbe = kn->kn_ptr.p_aio; kn->kn_data = aiocbe->uaiocb._aiocb_private.error; if (aiocbe->jobstate != JOBST_JOBFINISHED) @@ -2295,6 +2296,7 @@ filt_lioattach(struct knote *kn) */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); + kn->kn_ptr.p_lio = lj; kn->kn_flags &= ~EV_FLAG1; knlist_add(&lj->klist, kn, 0); @@ -2306,7 +2308,7 @@ filt_lioattach(struct knote *kn) static void filt_liodetach(struct knote *kn) { - struct aioliojob * lj = (struct aioliojob *)kn->kn_sdata; + struct aioliojob * lj = kn->kn_ptr.p_lio; if (!knlist_empty(&lj->klist)) knlist_remove(&lj->klist, kn, 0); @@ -2317,7 +2319,7 @@ filt_liodetach(struct knote *kn) static int filt_lio(struct knote *kn, long hint) { - struct aioliojob * lj = (struct aioliojob *)kn->kn_sdata; + struct aioliojob * lj = kn->kn_ptr.p_lio; return (lj->lioj_flags & LIOJ_KEVENT_POSTED); } |