Use `so_lock' to protect key management (PF_KEY) sockets. This can be
authormvs <mvs@openbsd.org>
Wed, 26 May 2021 08:28:34 +0000 (08:28 +0000)
committermvs <mvs@openbsd.org>
Wed, 26 May 2021 08:28:34 +0000 (08:28 +0000)
done because we have no cases where one thread should lock two sockets
simultaneously.

tested by yasuoka@

ok bluhm@ markus@

sys/kern/uipc_socket2.c
sys/net/pfkeyv2.c

index 851a0df..07ecd09 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket2.c,v 1.109 2021/05/01 16:13:13 mvs Exp $  */
+/*     $OpenBSD: uipc_socket2.c,v 1.110 2021/05/26 08:28:34 mvs Exp $  */
 /*     $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $       */
 
 /*
@@ -287,12 +287,8 @@ solock(struct socket *so)
        case PF_UNIX:
                rw_enter_write(&unp_lock);
                break;
-       case PF_ROUTE:
-               rw_enter_write(&so->so_lock);
-               break;
-       case PF_KEY:
        default:
-               KERNEL_LOCK();
+               rw_enter_write(&so->so_lock);
                break;
        }
 
@@ -315,12 +311,8 @@ sounlock(struct socket *so, int s)
        case PF_UNIX:
                rw_exit_write(&unp_lock);
                break;
-       case PF_ROUTE:
-               rw_exit_write(&so->so_lock);
-               break;
-       case PF_KEY:
        default:
-               KERNEL_UNLOCK();
+               rw_exit_write(&so->so_lock);
                break;
        }
 }
@@ -336,12 +328,8 @@ soassertlocked(struct socket *so)
        case PF_UNIX:
                rw_assert_wrlock(&unp_lock);
                break;
-       case PF_ROUTE:
-               rw_assert_wrlock(&so->so_lock);
-               break;
-       case PF_KEY:
        default:
-               KERNEL_ASSERT_LOCKED();
+               rw_assert_wrlock(&so->so_lock);
                break;
        }
 }
@@ -360,12 +348,8 @@ sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg,
        case PF_UNIX:
                ret = rwsleep_nsec(ident, &unp_lock, prio, wmesg, nsecs);
                break;
-       case PF_ROUTE:
-               ret = rwsleep_nsec(ident, &so->so_lock, prio, wmesg, nsecs);
-               break;
-       case PF_KEY:
        default:
-               ret = tsleep_nsec(ident, prio, wmesg, nsecs);
+               ret = rwsleep_nsec(ident, &so->so_lock, prio, wmesg, nsecs);
                break;
        }
 
index fa69173..0152df9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.213 2021/05/25 22:45:09 bluhm Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.214 2021/05/26 08:28:34 mvs Exp $ */
 
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
@@ -246,7 +246,7 @@ pfkey_init(void)
        rw_init(&pkptable.pkp_lk, "pfkey");
        SRPL_INIT(&pkptable.pkp_list);
        pool_init(&pkpcb_pool, sizeof(struct pkpcb), 0,
-           IPL_NONE, PR_WAITOK, "pkpcb", NULL);
+           IPL_SOFTNET, PR_WAITOK, "pkpcb", NULL);
        pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy), 0,
            IPL_SOFTNET, 0, "ipsec policy", NULL);
 }
@@ -315,8 +315,10 @@ pfkeyv2_detach(struct socket *so)
            kcb_list);
        rw_exit(&pkptable.pkp_lk);
 
+       sounlock(so, SL_LOCKED);
        /* wait for all references to drop */
        refcnt_finalize(&kp->kcb_refcnt, "pfkeyrefs");
+       solock(so);
 
        so->so_pcb = NULL;
        KASSERT((so->so_state & SS_NOFDREF) == 0);
@@ -430,7 +432,14 @@ pfkeyv2_output(struct mbuf *mbuf, struct socket *so,
 
        m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message);
 
+       /*
+        * The socket can't be closed concurrently because the file
+        * descriptor reference is still held.
+        */
+
+       sounlock(so, SL_LOCKED);
        error = pfkeyv2_send(so, message, mbuf->m_pkthdr.len);
+       solock(so);
 
 ret:
        m_freem(mbuf);