Fix a crash on access to TAP's owning thread. The owning thread can go away
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 5 Sep 2008 17:03:15 +0000 (17:03 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 5 Sep 2008 17:03:15 +0000 (17:03 +0000)
with the descriptor still open, for example if the opening process forks
into a background daemon and the foreground process exits.

Use the SIGIO mechanic to record the owning thread so we can detect if
the process goes away.

sys/net/tap/if_tap.c
sys/net/tap/if_tapvar.h

index 0fa9828..c085fda 100644 (file)
@@ -32,7 +32,7 @@
 
 /*
  * $FreeBSD: src/sys/net/if_tap.c,v 1.3.2.3 2002/04/14 21:41:48 luigi Exp $
- * $DragonFly: src/sys/net/tap/if_tap.c,v 1.40 2008/05/18 05:12:08 sephe Exp $
+ * $DragonFly: src/sys/net/tap/if_tap.c,v 1.41 2008/09/05 17:03:15 dillon Exp $
  * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
  */
 
@@ -291,7 +291,8 @@ tapopen(struct dev_open_args *ap)
 
        bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
 
-       tp->tap_td = curthread;
+       if (curthread->td_proc)
+               fsetown(curthread->td_proc->p_pid, &tp->tap_sigtd);
        tp->tap_flags |= TAP_OPEN;
        taprefcnt ++;
 
@@ -343,10 +344,12 @@ tapclose(struct dev_close_args *ap)
        rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
 
        funsetown(tp->tap_sigio);
+       tp->tap_sigio = NULL;
        selwakeup(&tp->tap_rsel);
 
        tp->tap_flags &= ~TAP_OPEN;
-       tp->tap_td = NULL;
+       funsetown(tp->tap_sigtd);
+       tp->tap_sigtd = NULL;
 
        taprefcnt --;
        if (taprefcnt < 0) {
@@ -434,16 +437,17 @@ tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                case SIOCGIFSTATUS:
                        ifs = (struct ifstat *)data;
                        dummy = strlen(ifs->ascii);
-                       if (tp->tap_td != NULL && dummy < sizeof(ifs->ascii)) {
-                               if (tp->tap_td->td_proc) {
+                       if ((tp->tap_flags & TAP_OPEN) &&
+                           dummy < sizeof(ifs->ascii)) {
+                               if (tp->tap_sigtd && tp->tap_sigtd->sio_proc) {
                                    ksnprintf(ifs->ascii + dummy,
                                        sizeof(ifs->ascii) - dummy,
                                        "\tOpened by pid %d\n",
-                                       (int)tp->tap_td->td_proc->p_pid);
+                                       (int)tp->tap_sigtd->sio_proc->p_pid);
                                } else {
                                    ksnprintf(ifs->ascii + dummy,
                                        sizeof(ifs->ascii) - dummy,
-                                       "\tOpened by td %p\n", tp->tap_td);
+                                       "\tOpened by <unknown>\n");
                                }
                        }
                        break;
index dcaecfe..2cd173e 100644 (file)
@@ -35,7 +35,7 @@
 
 /*
  * $FreeBSD: src/sys/net/if_tapvar.h,v 1.3.2.1 2000/07/27 13:57:05 nsayer Exp $
- * $DragonFly: src/sys/net/tap/if_tapvar.h,v 1.5 2008/05/18 05:12:08 sephe Exp $
+ * $DragonFly: src/sys/net/tap/if_tapvar.h,v 1.6 2008/09/05 17:03:15 dillon Exp $
  * $Id: if_tapvar.h,v 0.6 2000/07/11 02:16:08 max Exp $
  */
 
@@ -57,7 +57,7 @@ struct tap_softc {
 
        u_int8_t        ether_addr[ETHER_ADDR_LEN]; /* ether addr of the remote side */
 
-       struct thread   *tap_td;                /* thread of process to open  */
+       struct sigio    *tap_sigtd;             /* track process owning tap */
        struct sigio    *tap_sigio;             /* information for async I/O */
        struct selinfo   tap_rsel;              /* read select               */
        struct ifqueue   tap_devq;