kernel - Fix SMP races in raw socket code
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 13 Aug 2019 17:55:50 +0000 (10:55 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 13 Aug 2019 17:55:50 +0000 (10:55 -0700)
* The raw socket code was not properly dealing with SMP races
  in attach/detach verses receive processing.  Replace the token
  with a lockmgr lock.

  These issues never really caused an issue because raw sockets just
  aren't used very often, but they still need to be dealt with.

* SMP performance is not super-critical in this case so I just use a
  normal lock and keep it simple.

sys/net/raw_cb.c
sys/net/raw_cb.h
sys/net/raw_usrreq.c

index 63e1ca1..e31f2d2 100644 (file)
@@ -79,7 +79,11 @@ raw_attach(struct socket *so, int proto, struct rlimit *rl)
        rp->rcb_socket = so;
        rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
        rp->rcb_proto.sp_protocol = proto;
+
+       lockmgr(&raw_lock, LK_EXCLUSIVE);
        LIST_INSERT_HEAD(&rawcb_list, rp, list);
+       lockmgr(&raw_lock, LK_RELEASE);
+
        return (0);
 }
 
@@ -92,9 +96,12 @@ raw_detach(struct rawcb *rp)
 {
        struct socket *so = rp->rcb_socket;
 
+       lockmgr(&raw_lock, LK_EXCLUSIVE);
+       LIST_REMOVE(rp, list);
+       lockmgr(&raw_lock, LK_RELEASE);
+
        so->so_pcb = NULL;
        sofree(so);             /* remove pcb ref */
-       LIST_REMOVE(rp, list);
        kfree(rp, M_PCB);
 }
 
index c575a38..9def816 100644 (file)
@@ -69,6 +69,7 @@ struct rawcb {
 
 #ifdef _KERNEL
 extern LIST_HEAD(rawcb_list_head, rawcb) rawcb_list;
+extern struct lock raw_lock;
 
 union netmsg;
 
index 9d3186b..5acb9c7 100644 (file)
@@ -44,8 +44,7 @@
 
 #include <net/raw_cb.h>
 
-
-static struct lwkt_token raw_token = LWKT_TOKEN_INITIALIZER(raw_token);
+struct lock raw_lock = LOCK_INITIALIZER("rawlk", 0, 0);
 
 /*
  * Initialize raw connection block q.
@@ -77,9 +76,9 @@ raw_input(struct mbuf *m0, const struct sockproto *proto,
        struct mbuf *m = m0;
        struct socket *last;
 
-       lwkt_gettoken(&raw_token);
-
+       lockmgr(&raw_lock, LK_SHARED);
        last = NULL;
+
        LIST_FOREACH(rp, &rawcb_list, list) {
                if (rp == skip)
                        continue;
@@ -129,7 +128,7 @@ raw_input(struct mbuf *m0, const struct sockproto *proto,
        } else {
                m_freem(m);
        }
-       lwkt_reltoken(&raw_token);
+       lockmgr(&raw_lock, LK_RELEASE);
 }
 
 /*