aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-04-28 14:42:59 +0000
committerMark Johnston <markj@FreeBSD.org>2021-04-28 14:43:29 +0000
commitd1e9441583fd85c7de5f48197d80c287f1a9494b (patch)
tree88befc88c100cc51b72d0781da5c8189a080fa57
parente444a4c677ee3e86038ba2179c4838f5f4b778cd (diff)
downloadsrc-d1e9441583fd85c7de5f48197d80c287f1a9494b.tar.gz
src-d1e9441583fd85c7de5f48197d80c287f1a9494b.zip
pipe: Avoid calling selrecord() on a closing pipe
pipe_poll() may add the calling thread to the selinfo lists of both ends of a pipe. It is ok to do this for the local end, since we know we hold a reference on the file and so the local end is not closed. It is not ok to do this for the remote end, which may already be closed and have called seldrain(). In this scenario, when the polling thread wakes up, it may end up referencing a freed selinfo. Guard the selrecord() call appropriately. Reviewed by: kib Reported by: syzkaller+KASAN MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D30016
-rw-r--r--sys/kern/sys_pipe.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index fee9d95e179c..d226543c0118 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1494,7 +1494,8 @@ pipe_poll(struct file *fp, int events, struct ucred *active_cred,
rpipe->pipe_state |= PIPE_SEL;
}
- if ((fp->f_flag & FWRITE) != 0) {
+ if ((fp->f_flag & FWRITE) != 0 &&
+ wpipe->pipe_present == PIPE_ACTIVE) {
selrecord(td, &wpipe->pipe_sel);
if (SEL_WAITING(&wpipe->pipe_sel))
wpipe->pipe_state |= PIPE_SEL;