svn commit: r324597 - head/sys/compat/linuxkpi/common/src

Hans Petter Selasky hselasky at FreeBSD.org
Fri Oct 13 14:14:47 UTC 2017


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);


More information about the svn-src-head mailing list