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
This commit is contained in:
parent
eee74fe05d
commit
a8afa221cc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175642
@ -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);
|
||||
}
|
||||
|
@ -181,6 +181,8 @@ struct knote {
|
||||
union {
|
||||
struct file *p_fp; /* file data pointer */
|
||||
struct proc *p_proc; /* proc pointer */
|
||||
struct aiocblist *p_aio; /* AIO job pointer */
|
||||
struct aioliojob *p_lio; /* LIO job pointer */
|
||||
} kn_ptr;
|
||||
struct filterops *kn_fop;
|
||||
void *kn_hook;
|
||||
|
Loading…
Reference in New Issue
Block a user