Author: hselasky
Date: Fri Oct 13 14:14:46 2017
New Revision: 324597
URL: https://svnweb.freebsd.org/changeset/base/324597

Log:
  Don't call selrecord() outside the select system call in the LinuxKPI, because
  then td->td_sel is NULL and this will result in a segfault inside selrecord().
  This happens when only using kqueue() to poll for read and write events.
  If select() and kqueue() is mixed there won't be a segfault.
  
  Reported by:  Johannes Lundberg
  MFC after:    1 week
  Sponsored by: Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c  Fri Oct 13 13:56:44 
2017        (r324596)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c  Fri Oct 13 14:14:46 
2017        (r324597)
@@ -1021,6 +1021,8 @@ linux_dev_write(struct cdev *dev, struct uio *uio, int
        return (error);
 }
 
+#define        LINUX_POLL_TABLE_NORMAL ((poll_table *)1)
+
 static int
 linux_dev_poll(struct cdev *dev, int events, struct thread *td)
 {
@@ -1037,7 +1039,7 @@ linux_dev_poll(struct cdev *dev, int events, struct th
        filp->f_flags = file->f_flag;
        linux_set_current(td);
        if (filp->f_op->poll != NULL)
-               revents = filp->f_op->poll(filp, NULL) & events;
+               revents = filp->f_op->poll(filp, LINUX_POLL_TABLE_NORMAL) & 
events;
        else
                revents = 0;
 
@@ -1094,7 +1096,9 @@ linux_poll_wait(struct linux_file *filp, wait_queue_he
                [LINUX_FWQ_STATE_READY] = LINUX_FWQ_STATE_QUEUED,
        };
 
-       selrecord(curthread, &filp->f_selinfo);
+       /* check if we are called inside the select system call */
+       if (p == LINUX_POLL_TABLE_NORMAL)
+               selrecord(curthread, &filp->f_selinfo);
 
        switch (linux_poll_wakeup_state(&filp->f_wait_queue.state, state)) {
        case LINUX_FWQ_STATE_INIT:
@@ -1438,10 +1442,9 @@ linux_file_poll(struct file *file, int events, struct 
        filp = (struct linux_file *)file->f_data;
        filp->f_flags = file->f_flag;
        linux_set_current(td);
-       if (filp->f_op->poll != NULL) {
-               selrecord(td, &filp->f_selinfo);
-               revents = filp->f_op->poll(filp, NULL) & events;
-       } else
+       if (filp->f_op->poll != NULL)
+               revents = filp->f_op->poll(filp, LINUX_POLL_TABLE_NORMAL) & 
events;
+       else
                revents = 0;
 
        return (revents);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to