On 2014/03/26 07:30, Mateusz Guzik wrote:
Author: mjg
Date: Tue Mar 25 23:30:35 2014
New Revision: 263755
URL: http://svnweb.freebsd.org/changeset/base/263755

Log:
   Document a known problem with handling the process intended to receive
   SIGIO in /dev/devctl.

   Suggested by:        adrian
   MFC after:   6 days

Modified:
   head/sys/kern/subr_bus.c

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c    Tue Mar 25 23:19:45 2014        (r263754)
+++ head/sys/kern/subr_bus.c    Tue Mar 25 23:30:35 2014        (r263755)
@@ -490,6 +490,21 @@ devioctl(struct cdev *dev, u_long cmd, c
                        devsoftc.nonblock = 0;
                return (0);
        case FIOASYNC:
+               /*
+                * FIXME:
+                * Since this is a simple assignment there is no guarantee that
+                * devsoftc.async_proc consumers will get a valid pointer.
+                *
+                * Example scenario where things break (processes A and B):
+                * 1. A opens devctl
+                * 2. A sends fd to B
+                * 3. B sets itself as async_proc
+                * 4. B exits
+                *
+                * However, normally this requires root privileges and the only
+                * in-tree consumer does not behave in a dangerous way so the
+                * issue is not critical.
+                */
                if (*(int*)data)
                        devsoftc.async_proc = td->td_proc;
                else
@@ -575,6 +590,7 @@ devctl_queue_data_f(char *data, int flag
        cv_broadcast(&devsoftc.cv);
        mtx_unlock(&devsoftc.mtx);
        selwakeup(&devsoftc.sel);
+       /* XXX see a comment in devioctl */
        p = devsoftc.async_proc;
        if (p != NULL) {
                PROC_LOCK(p);



I think the async process pointer can be cleared when a process exits
by registering an event handler. please see attached patch.


# HG changeset patch
# Parent 53b614ff2cae108f27e4475989d3a86997017268

diff -r 53b614ff2cae sys/kern/subr_bus.c
--- a/sys/kern/subr_bus.c	Thu Mar 27 10:03:50 2014 +0800
+++ b/sys/kern/subr_bus.c	Thu Mar 27 15:38:40 2014 +0800
@@ -54,6 +54,7 @@
 #include <sys/uio.h>
 #include <sys/bus.h>
 #include <sys/interrupt.h>
+#include <sys/eventhandler.h>
 
 #include <net/vnet.h>
 
@@ -399,6 +400,18 @@
 } devsoftc;
 
 static struct cdev *devctl_dev;
+static eventhandler_tag devctl_eh;
+
+static void
+devctl_proc_clear(void *arg, struct proc *p, struct image_params *imgp __unused)
+{
+	if (devsoftc.async_proc == p) {
+		mtx_lock(&devsoftc.mtx);
+		if (devsoftc.async_proc == p)
+			devsoftc.async_proc = NULL;
+		mtx_unlock(&devsoftc.mtx);
+	}
+}
 
 static void
 devinit(void)
@@ -408,6 +421,8 @@
 	mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
 	cv_init(&devsoftc.cv, "dev cv");
 	TAILQ_INIT(&devsoftc.devq);
+	devctl_eh = EVENTHANDLER_REGISTER(process_exit, devctl_proc_clear, NULL,
+		EVENTHANDLER_PRI_ANY);
 }
 
 static int
@@ -490,25 +505,12 @@
 			devsoftc.nonblock = 0;
 		return (0);
 	case FIOASYNC:
-		/*
-		 * FIXME:
-		 * Since this is a simple assignment there is no guarantee that
-		 * devsoftc.async_proc consumers will get a valid pointer.
-		 *
-		 * Example scenario where things break (processes A and B):
-		 * 1. A opens devctl
-		 * 2. A sends fd to B
-		 * 3. B sets itself as async_proc
-		 * 4. B exits
-		 *
-		 * However, normally this requires root privileges and the only
-		 * in-tree consumer does not behave in a dangerous way so the
-		 * issue is not critical.
-		 */
+		mtx_lock(&devsoftc.mtx);
 		if (*(int*)data)
 			devsoftc.async_proc = td->td_proc;
 		else
 			devsoftc.async_proc = NULL;
+		mtx_unlock(&devsoftc.mtx);
 		return (0);
 
 		/* (un)Support for other fcntl() calls. */
@@ -588,15 +590,14 @@
 	TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
 	devsoftc.queued++;
 	cv_broadcast(&devsoftc.cv);
-	mtx_unlock(&devsoftc.mtx);
 	selwakeup(&devsoftc.sel);
-	/* XXX see a comment in devioctl */
 	p = devsoftc.async_proc;
 	if (p != NULL) {
 		PROC_LOCK(p);
 		kern_psignal(p, SIGIO);
 		PROC_UNLOCK(p);
 	}
+	mtx_unlock(&devsoftc.mtx);
 	return;
 out:
 	/*
@@ -4503,7 +4504,7 @@
 		return (0);
 
 	case MOD_SHUTDOWN:
-		device_shutdown(root_bus);
+		EVENTHANDLER_DEREGISTER(process_exit, devctl_eh);
 		return (0);
 	default:
 		return (EOPNOTSUPP);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to