From 8600ba1aa9cc990afb6b3c231b1aa4a76bfb9e16 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 1 Jun 2017 16:49:48 +0000 Subject: [PATCH] Make sure the selrecord() function is only called from within system polling contexts in the LinuxKPI. After the kqueue() support was added to the LinuxKPI in r319409 the Linux poll file operation will be used outside the system file polling callback function, which can cause a NULL-pointer panic inside selrecord() because curthread->td_sel is set to NULL. This patch moves the selrecord() call away from poll_wait() and to the system file poll callback function in the LinuxKPI, which essentially wraps the Linux one. This is similar to what the cuse(3) module is currently doing. Refer to sys/fs/cuse/*.[ch] for more details. MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/compat/linuxkpi/common/include/linux/poll.h | 2 +- sys/compat/linuxkpi/common/src/linux_compat.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/poll.h b/sys/compat/linuxkpi/common/include/linux/poll.h index 254a5adfb26..16c75ec65bc 100644 --- a/sys/compat/linuxkpi/common/include/linux/poll.h +++ b/sys/compat/linuxkpi/common/include/linux/poll.h @@ -43,7 +43,7 @@ typedef struct poll_table_struct { static inline void poll_wait(struct linux_file *filp, wait_queue_head_t *wait_address, poll_table *p) { - selrecord(curthread, &filp->f_selinfo); + /* NOP */ } extern void linux_poll_wakeup(struct linux_file *); diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index 8d3c27cc3c9..7bf098bf490 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -956,9 +956,10 @@ linux_dev_poll(struct cdev *dev, int events, struct thread *td) file = td->td_fpop; filp->f_flags = file->f_flag; linux_set_current(td); - if (filp->f_op->poll) + if (filp->f_op->poll != NULL) { + selrecord(td, &filp->f_selinfo); revents = filp->f_op->poll(filp, NULL) & events; - else + } else revents = 0; return (revents); @@ -1263,9 +1264,10 @@ linux_file_poll(struct file *file, int events, struct ucred *active_cred, filp = (struct linux_file *)file->f_data; filp->f_flags = file->f_flag; linux_set_current(td); - if (filp->f_op->poll) + if (filp->f_op->poll != NULL) { + selrecord(td, &filp->f_selinfo); revents = filp->f_op->poll(filp, NULL) & events; - else + } else revents = 0; return (revents);