1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

Destruction of the pipe calls knlist_cleardel() to remove the knotes

monitoring the pipe. The code sets pipe_present = 0 and enters
knlist_cleardel(), where the PIPE_MTX might be dropped when knl->kl_list
cannot be cleared due to influx knotes.

If the following often encountered code fragment
                if (!(kn->kn_status & KN_DETACHED))
                        kn->kn_fop->f_detach(kn);
                knote_drop(kn, td); [1]
is executed while the knlist lock is dropped, then the knote memory is freed
by the knote_drop() without knote being removed from the knlist, since
the filt_pipedetach() contains the following:
        if (kn->kn_filter == EVFILT_WRITE) {
                if (!cpipe->pipe_peer->pipe_present) {
                        PIPE_UNLOCK(cpipe);
                        return;

Now, the memory may be reused in the zone, causing the access to the
freed memory. I got the panics caused by the marker knote appearing on
the knlist, that, I believe, manifestation of the issue. In the Peter
Holm test scenarious, we got unkillable processes too.

The pipe_peer that has the knote for write shall be present. Ignore the
pipe_present value for EVFILT_WRITE in filt_pipedetach().

Debugging help and tested by:	pho
Discussed with:	jmg
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2008-05-23 11:09:50 +00:00
parent 9445f413ee
commit e2e1693f15
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179242

View File

@ -1566,13 +1566,8 @@ filt_pipedetach(struct knote *kn)
struct pipe *cpipe = (struct pipe *)kn->kn_fp->f_data;
PIPE_LOCK(cpipe);
if (kn->kn_filter == EVFILT_WRITE) {
if (!cpipe->pipe_peer->pipe_present) {
PIPE_UNLOCK(cpipe);
return;
}
if (kn->kn_filter == EVFILT_WRITE)
cpipe = cpipe->pipe_peer;
}
knlist_remove(&cpipe->pipe_sel.si_note, kn, 1);
PIPE_UNLOCK(cpipe);
}