svn commit: r344278 - head/sys/kern

Mark Johnston markj at
Tue Feb 19 15:46:44 UTC 2019

Author: markj
Date: Tue Feb 19 15:46:43 2019
New Revision: 344278

  Move a racy assertion in filt_pipewrite().
  EVFILT_WRITE knotes for pipes live on the knlist for the other end of the
  pipe.  Since they do not hold a reference on the corresponding file
  structure, they may be removed from the knlist by pipeclose() while still
  remaining active.  In this case, there is no knlist lock acquired before
  filt_pipewrite() is called, so the assertion fails.
  Fix the problem by first checking whether that end of the pipe has been
  closed.  These checks are memory safe since the knote holds a reference
  on one end of the pipe, and the pipe structure is not freed until both
  ends are closed.  The checks are not racy since PIPE_EOF is never cleared
  after being set, and pipe_present is never set back to PIPE_ACTIVE after
  pipeclose() has been called.
  PR:		235640
  Reported and tested by:	pho
  Reviewed by:	kib
  MFC after:	2 weeks
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:


Modified: head/sys/kern/sys_pipe.c
--- head/sys/kern/sys_pipe.c	Tue Feb 19 12:45:37 2019	(r344277)
+++ head/sys/kern/sys_pipe.c	Tue Feb 19 15:46:43 2019	(r344278)
@@ -1741,15 +1741,19 @@ static int
 filt_pipewrite(struct knote *kn, long hint)
 	struct pipe *wpipe;
+	/*
+	 * If this end of the pipe is closed, the knote was removed from the
+	 * knlist and the list lock (i.e., the pipe lock) is therefore not held.
+	 */
 	wpipe = kn->kn_hook;
 	if (wpipe->pipe_present != PIPE_ACTIVE ||
 	    (wpipe->pipe_state & PIPE_EOF)) {
 		kn->kn_data = 0;
 		kn->kn_flags |= EV_EOF;
 		return (1);
 	kn->kn_data = (wpipe->pipe_buffer.size > 0) ?
 	    (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) : PIPE_BUF;
 	if (wpipe->pipe_state & PIPE_DIRECTW)

More information about the svn-src-all mailing list