On 20.6.2022. 16:46, Vitaliy Makkoveev wrote:
> And use this mutex(9) to make the `session' dereference safe.
> 
> Hrvoje Popovski pointed me, he triggered netlock assertion with pipex(4)
> pppoe sessions:
> 

Hi,

I can trigger this splassert with plain snapshot and with only pppoe
clients. npppd setup is without pf.

r420-1# ifconfig ix0
ix0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 90:e2:ba:19:29:a8
        index 1 priority 0 llprio 3
        media: Ethernet autoselect (10GSFP+Cu full-duplex,rxpause,txpause)
        status: active
        inet 192.168.100.205 netmask 0xffffff00 broadcast 192.168.100.255



r420-1# cat /etc/npppd/npppd.conf
authentication LOCAL type local {
        users-file "/etc/npppd/npppd-users"
}
tunnel PPTP protocol pptp {
}
tunnel L2TP protocol l2tp {
        authentication-method pap chap mschapv2
}
tunnel PPPOE protocol pppoe {
        listen on interface ix0
        authentication-method pap chap
}

ipcp IPCP-L2TP {
        pool-address 10.53.251.10-10.53.251.100
        dns-servers 161.53.2.69
}
ipcp IPCP-PPTP {
        pool-address 10.53.252.10-10.53.252.100
        dns-servers 161.53.2.69
}
ipcp IPCP-PPPOE {
        pool-address 10.53.253.10-10.53.253.100
}

interface pppac0 address 10.53.251.1 ipcp IPCP-L2TP
interface pppac1 address 10.53.252.1 ipcp IPCP-PPTP
interface pppac2 address 10.53.253.1 ipcp IPCP-PPPOE

bind tunnel from L2TP authenticated by LOCAL to pppac0
bind tunnel from PPTP authenticated by LOCAL to pppac1
bind tunnel from PPPOE authenticated by LOCAL to pppac2


r420-1# npppctl ses bri
Ppp Id     Assigned IPv4   Username             Proto Tunnel From
---------- --------------- -------------------- -----
-------------------------
         0 10.53.253.11    hrvojepppoe11        PPPoE 90:e2:ba:33:af:ec
         1 10.53.253.12    hrvojepppoe12        PPPoE ec:f4:bb:c8:e9:88


I'm generating traffic with iperf3 from pppoe hosts to hosts in
192.168.100.0/24 network and at same time generating traffic between
pppoe hosts.
This triggers splassert after half a hour or so ...

r420-1# splassert: pipex_ppp_output: want 2 have 0
Starting stack trace...
pipex_ppp_output(fffffd80a45eaa00,ffff800022782400,21) at
pipex_ppp_output+0x5e
pppac_qstart(ffff800000ec0ab0) at pppac_qstart+0x96
ifq_serialize(ffff800000ec0ab0,ffff800000ec0b90) at ifq_serialize+0xfd
taskq_thread(ffff800000030080) at taskq_thread+0x100
end trace frame: 0x0, count: 253
End of stack trace.



>>
>> r420-1# splassert: pipex_ppp_output: want 2 have 0
>> Starting stack trace...
>> pipex_ppp_output(fffffd80cb7c9500,ffff800022761200,21) at
>> pipex_ppp_output+0x5e
>> pppac_qstart(ffff800000e80ab0) at pppac_qstart+0x96
>> ifq_serialize(ffff800000e80ab0,ffff800000e80b90) at ifq_serialize+0xfd
>> taskq_thread(ffff800000030080) at taskq_thread+0x100
>> end trace frame: 0x0, count: 253
>> End of stack trace.
>> splassert: pipex_ppp_output: want 2 have 0
>> Starting stack trace...
>> pipex_ppp_output(fffffd80c53b2300,ffff800022761200,21) at
>> pipex_ppp_output+0x5e
>> pppac_qstart(ffff800000e80ab0) at pppac_qstart+0x96
>> ifq_serialize(ffff800000e80ab0,ffff800000e80b90) at ifq_serialize+0xfd
>> taskq_thread(ffff800000030080) at taskq_thread+0x100
>> end trace frame: 0x0, count: 253
>> End of stack trace.
>>
>>
>> r420-1# npppctl ses bri
>> Ppp Id     Assigned IPv4   Username             Proto Tunnel From
>> ---------- --------------- -------------------- -----
>> -------------------------
>>          7 10.53.251.22    r6202                L2TP  192.168.100.12:1701
>>          1 10.53.253.11    hrvojepppoe11        PPPoE 90:e2:ba:33:af:ec
>>          0 10.53.253.12    hrvojepppoe12        PPPoE ec:f4:bb:da:f7:f8
> 
> This means the hack we use to enforce pppac_qstart() and
> pppx_if_qstart() be called with netlock held doesn't work anymore for
> pppoe sessions:
> 
>       /* XXXSMP: be sure pppac_qstart() called with NET_LOCK held */
>       ifq_set_maxlen(&ifp->if_snd, 1);
> 
> pptp and l2tp sessions are not affected, because the pcb layer is still
> accessed with exclusive netlock held, but the code is common for all
> session types. This mean we can't rely on netlock and should rework
> pipex(4) locking.
> 
> The diff below introduces `pipex_list_mtx' mutex(9) to protect global
> pipex(4) lists and made `session' dereference safe. It doesn't fix the
> assertion, but only makes us sure the pppoe session can't be killed
> concurrently while stack processes it.
> 
> I'll protect pipex(4) session data and rework pipex(4) output with next
> diffs.
> 
> ok?
> 
> Index: sys/net/if_ethersubr.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_ethersubr.c,v
> retrieving revision 1.279
> diff -u -p -r1.279 if_ethersubr.c
> --- sys/net/if_ethersubr.c    22 Apr 2022 12:10:57 -0000      1.279
> +++ sys/net/if_ethersubr.c    20 Jun 2022 14:44:03 -0000
> @@ -545,11 +545,14 @@ ether_input(struct ifnet *ifp, struct mb
>               if (pipex_enable) {
>                       struct pipex_session *session;
>  
> +                     mtx_enter(&pipex_list_mtx);
>                       if ((session = pipex_pppoe_lookup_session(m)) != NULL) {
>                               pipex_pppoe_input(m, session);
> +                             mtx_leave(&pipex_list_mtx);
>                               KERNEL_UNLOCK();
>                               return;
>                       }
> +                     mtx_leave(&pipex_list_mtx);
>               }
>  #endif
>               if (etype == ETHERTYPE_PPPOEDISC)
> Index: sys/net/if_gre.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_gre.c,v
> retrieving revision 1.171
> diff -u -p -r1.171 if_gre.c
> --- sys/net/if_gre.c  10 Mar 2021 10:21:47 -0000      1.171
> +++ sys/net/if_gre.c  20 Jun 2022 14:44:03 -0000
> @@ -973,10 +973,18 @@ gre_input_1(struct gre_tunnel *key, stru
>               if (pipex_enable) {
>                       struct pipex_session *session;
>  
> +                     mtx_enter(&pipex_list_mtx);
>                       session = pipex_pptp_lookup_session(m);
> -                     if (session != NULL &&
> -                         pipex_pptp_input(m, session) == NULL)
> -                             return (NULL);
> +                     if (session != NULL) {
> +                             struct mbuf *m0;
> +
> +                             m0 = pipex_pptp_input(m, session);
> +                             mtx_leave(&pipex_list_mtx);
> +
> +                             if (m0 == NULL)
> +                                     return (NULL);
> +                     }
> +                     mtx_leave(&pipex_list_mtx);
>               }
>  #endif
>               break;
> Index: sys/net/if_pppx.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_pppx.c,v
> retrieving revision 1.114
> diff -u -p -r1.114 if_pppx.c
> --- sys/net/if_pppx.c 22 Feb 2022 01:15:02 -0000      1.114
> +++ sys/net/if_pppx.c 20 Jun 2022 14:44:03 -0000
> @@ -1322,9 +1322,7 @@ pppacclose(dev_t dev, int flags, int mod
>       splx(s);
>  
>       pool_put(&pipex_session_pool, sc->sc_multicast_session);
> -     NET_LOCK();
>       pipex_destroy_all_sessions(sc);
> -     NET_UNLOCK();
>  
>       LIST_REMOVE(sc, sc_entry);
>       free(sc, M_DEVBUF, sizeof(*sc));
> @@ -1384,11 +1382,15 @@ pppac_del_session(struct pppac_softc *sc
>  {
>       struct pipex_session *session;
>  
> +     mtx_enter(&pipex_list_mtx);
>       session = pipex_lookup_by_session_id(req->pcr_protocol,
>           req->pcr_session_id);
> -     if (session == NULL || session->ownersc != sc)
> +     if (session == NULL || session->ownersc != sc) {
> +             mtx_leave(&pipex_list_mtx);
>               return (EINVAL);
> -     pipex_unlink_session(session);
> +     }
> +     pipex_unlink_session_locked(session);
> +     mtx_leave(&pipex_list_mtx);
>       pipex_rele_session(session);
>  
>       return (0);
> @@ -1458,11 +1460,13 @@ pppac_qstart(struct ifqueue *ifq)
>                               else
>                                       goto bad;
>                       } else {
> +                             mtx_enter(&pipex_list_mtx);
>                               session = pipex_lookup_by_ip_address(ip.ip_dst);
>                               if (session != NULL) {
>                                       pipex_ip_output(m, session);
>                                       m = NULL;
>                               }
> +                             mtx_leave(&pipex_list_mtx);
>                       }
>                       break;
>               }
> Index: sys/net/pipex.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex.c,v
> retrieving revision 1.136
> diff -u -p -r1.136 pipex.c
> --- sys/net/pipex.c   2 Jan 2022 22:36:04 -0000       1.136
> +++ sys/net/pipex.c   20 Jun 2022 14:44:03 -0000
> @@ -40,6 +40,7 @@
>  #include <sys/kernel.h>
>  #include <sys/pool.h>
>  #include <sys/percpu.h>
> +#include <sys/mutex.h>
>  
>  #include <net/if.h>
>  #include <net/if_types.h>
> @@ -79,6 +80,8 @@
>  #include <net/pipex.h>
>  #include "pipex_local.h"
>  
> +struct mutex pipex_list_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
> +
>  struct pool pipex_session_pool;
>  struct pool mppe_key_pool;
>  
> @@ -88,17 +91,18 @@ struct pool mppe_key_pool;
>   *       A       atomic operation
>   *       I       immutable after creation
>   *       N       net lock
> + *       L       pipex_list_mtx
>   */
>  
>  int  pipex_enable = 0;                       /* [N] */
>  struct pipex_hash_head
> -    pipex_session_list,                              /* [N] master session 
> list */
> -    pipex_close_wait_list,                   /* [N] expired session list */
> -    pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],      /* [N] peer's address 
> hash */
> -    pipex_id_hashtable[PIPEX_HASH_SIZE];     /* [N] peer id hash */
> +    pipex_session_list,                              /* [L] master session 
> list */
> +    pipex_close_wait_list,                   /* [L] expired session list */
> +    pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],      /* [L] peer's address 
> hash */
> +    pipex_id_hashtable[PIPEX_HASH_SIZE];     /* [L] peer id hash */
>  
> -struct radix_node_head       *pipex_rd_head4 = NULL; /* [N] */
> -struct radix_node_head       *pipex_rd_head6 = NULL; /* [N] */
> +struct radix_node_head       *pipex_rd_head4 = NULL; /* [L] */
> +struct radix_node_head       *pipex_rd_head6 = NULL; /* [L] */
>  struct timeout pipex_timer_ch;               /* callout timer context */
>  int pipex_prune = 1;                 /* [I] walk list every seconds */
>  
> @@ -145,16 +149,18 @@ pipex_destroy_all_sessions(void *ownersc
>  {
>       struct pipex_session *session, *session_tmp;
>  
> -     NET_ASSERT_LOCKED();
> +     mtx_enter(&pipex_list_mtx);
>  
>       LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
>           session_tmp) {
>               if (session->ownersc == ownersc) {
>                       KASSERT(session->is_pppx == 0);
> -                     pipex_unlink_session(session);
> +                     pipex_unlink_session_locked(session);
>                       pipex_rele_session(session);
>               }
>       }
> +
> +     mtx_leave(&pipex_list_mtx);
>  }
>  
>  int
> @@ -375,8 +381,9 @@ pipex_link_session(struct pipex_session 
>  {
>       struct pipex_hash_head *chain;
>       struct radix_node *rn;
> +     int error = 0;
>  
> -     NET_ASSERT_LOCKED();
> +     mtx_enter(&pipex_list_mtx);
>  
>       if (pipex_rd_head4 == NULL) {
>               if (!rn_inithead((void **)&pipex_rd_head4,
> @@ -389,8 +396,10 @@ pipex_link_session(struct pipex_session 
>                       panic("rn_inithead() failed on pipex_link_session()");
>       }
>       if (pipex_lookup_by_session_id(session->protocol,
> -         session->session_id))
> -             return (EEXIST);
> +         session->session_id)) {
> +             error = EEXIST;
> +             goto out;
> +     }
>  
>       session->ownersc = ownersc;
>       session->ifindex = ifp->if_index;
> @@ -400,12 +409,16 @@ pipex_link_session(struct pipex_session 
>       if (session->is_pppx == 0 &&
>           !in_nullhost(session->ip_address.sin_addr)) {
>               if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
> -                 != NULL)
> -                     return (EADDRINUSE);
> +                 != NULL) {
> +                     error = EADDRINUSE;
> +                     goto out;
> +             }
>               rn = rn_addroute(&session->ip_address, &session->ip_netmask,
>                   pipex_rd_head4, session->ps4_rn, RTP_STATIC);
> -             if (rn == NULL)
> -                     return (ENOMEM);
> +             if (rn == NULL) {
> +                     error = ENOMEM;
> +                     goto out;
> +             }
>       }
>  
>       LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
> @@ -426,17 +439,21 @@ pipex_link_session(struct pipex_session 
>               pipex_timer_start();
>       session->state = PIPEX_STATE_OPENED;
>  
> -     return (0);
> +out:
> +     mtx_leave(&pipex_list_mtx);
> +
> +     return error;
>  }
>  
>  void
> -pipex_unlink_session(struct pipex_session *session)
> +pipex_unlink_session_locked(struct pipex_session *session)
>  {
>       struct radix_node *rn;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       session->ifindex = 0;
>  
> -     NET_ASSERT_LOCKED();
>       if (session->state == PIPEX_STATE_CLOSED)
>               return;
>       if (session->is_pppx == 0 &&
> @@ -466,10 +483,19 @@ pipex_unlink_session(struct pipex_sessio
>               pipex_timer_stop();
>  }
>  
> +void
> +pipex_unlink_session(struct pipex_session *session)
> +{
> +     mtx_enter(&pipex_list_mtx);
> +     pipex_unlink_session_locked(session);
> +     mtx_leave(&pipex_list_mtx);
> +}
> +
>  int
>  pipex_notify_close_session(struct pipex_session *session)
>  {
> -     NET_ASSERT_LOCKED();
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       session->state = PIPEX_STATE_CLOSE_WAIT;
>       session->idle_time = 0;
>       LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list);
> @@ -499,34 +525,54 @@ Static int
>  pipex_config_session(struct pipex_session_config_req *req, void *ownersc)
>  {
>       struct pipex_session *session;
> +     int error = 0;
>  
>       NET_ASSERT_LOCKED();
> +     mtx_enter(&pipex_list_mtx);
> +
>       session = pipex_lookup_by_session_id(req->pcr_protocol,
>           req->pcr_session_id);
> -     if (session == NULL)
> -             return (EINVAL);
> -     if (session->ownersc != ownersc)
> -             return (EINVAL);
> +     if (session == NULL) {
> +             error = EINVAL;
> +             goto out;
> +     }
> +     if (session->ownersc != ownersc) {
> +             error = EINVAL;
> +             goto out;
> +     }
>       session->ip_forward = req->pcr_ip_forward;
>  
> -     return (0);
> +out:
> +     mtx_leave(&pipex_list_mtx);
> +
> +     return error;
>  }
>  
>  Static int
>  pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc)
>  {
>       struct pipex_session *session;
> +     int error = 0;
>  
>       NET_ASSERT_LOCKED();
> +     mtx_enter(&pipex_list_mtx);
> +
>       session = pipex_lookup_by_session_id(req->psr_protocol,
>           req->psr_session_id);
> -     if (session == NULL)
> -             return (EINVAL);
> -     if (session->ownersc != ownersc)
> -             return (EINVAL);
> +     if (session == NULL) {
> +             error = EINVAL;
> +             goto out;
> +     }
> +     if (session->ownersc != ownersc) {
> +             error = EINVAL;
> +             goto out;
> +     }
>       pipex_export_session_stats(session, &req->psr_stat);
>  
> -     return (0);
> +out:
> +     mtx_leave(&pipex_list_mtx);
> +
> +     return error;
>  }
>  
>  Static int
> @@ -534,8 +580,10 @@ pipex_get_closed(struct pipex_session_li
>  {
>       struct pipex_session *session, *session_tmp;
>  
> -     NET_ASSERT_LOCKED();
>       bzero(req, sizeof(*req));
> +
> +     mtx_enter(&pipex_list_mtx);
> +
>       LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list,
>           session_tmp) {
>               if (session->ownersc != ownersc)
> @@ -550,6 +598,8 @@ pipex_get_closed(struct pipex_session_li
>               }
>       }
>  
> +     mtx_leave(&pipex_list_mtx);
> +
>       return (0);
>  }
>  
> @@ -559,6 +609,8 @@ pipex_lookup_by_ip_address(struct in_add
>       struct pipex_session *session;
>       struct sockaddr_in pipex_in4, pipex_in4mask;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       if (pipex_rd_head4 == NULL)
>               return (NULL);
>       bzero(&pipex_in4, sizeof(pipex_in4));
> @@ -592,7 +644,8 @@ pipex_lookup_by_session_id(int protocol,
>       struct pipex_hash_head *list;
>       struct pipex_session *session;
>  
> -     NET_ASSERT_LOCKED();
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       list = PIPEX_ID_HASHTABLE(session_id);
>       LIST_FOREACH(session, list, id_chain) {
>               if (session->protocol == protocol &&
> @@ -633,7 +686,7 @@ pipex_timer(void *ignored_arg)
>  
>       timeout_add_sec(&pipex_timer_ch, pipex_prune);
>  
> -     NET_LOCK();
> +     mtx_enter(&pipex_list_mtx);
>       /* walk through */
>       LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
>           session_tmp) {
> @@ -656,7 +709,7 @@ pipex_timer(void *ignored_arg)
>                       if (session->idle_time < PIPEX_CLOSE_TIMEOUT)
>                               continue;
>                       /* Release the sessions when timeout */
> -                     pipex_unlink_session(session);
> +                     pipex_unlink_session_locked(session);
>                       KASSERTMSG(session->is_pppx == 0,
>                           "FIXME session must not be released when pppx");
>                       pipex_rele_session(session);
> @@ -667,7 +720,7 @@ pipex_timer(void *ignored_arg)
>               }
>       }
>  
> -     NET_UNLOCK();
> +     mtx_leave(&pipex_list_mtx);
>  }
>  
>  /***********************************************************************
> @@ -1113,6 +1166,8 @@ pipex_pppoe_lookup_session(struct mbuf *
>       struct pipex_session *session;
>       struct pipex_pppoe_header pppoe;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       /* short packet */
>       if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe)))
>               return (NULL);
> @@ -1139,7 +1194,8 @@ pipex_pppoe_input(struct mbuf *m0, struc
>       int hlen;
>       struct pipex_pppoe_header pppoe;
>  
> -     NET_ASSERT_LOCKED();
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       /* already checked at pipex_pppoe_lookup_session */
>       KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) +
>           sizeof(pppoe)));
> @@ -1302,6 +1358,8 @@ pipex_pptp_lookup_session(struct mbuf *m
>       uint16_t id;
>       int hlen;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) {
>               PIPEX_DBG((NULL, LOG_DEBUG,
>                   "<%s> packet length is too short", __func__));
> @@ -1372,6 +1430,8 @@ pipex_pptp_input(struct mbuf *m0, struct
>       int rewind = 0;
>  
>       NET_ASSERT_LOCKED();
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
>       pptp_session = &session->proto.pptp;
>  
> @@ -1535,6 +1595,8 @@ pipex_pptp_userland_lookup_session(struc
>       struct pipex_session *session;
>       uint16_t id, flags;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       /* pullup */
>       if (m0->m_pkthdr.len < sizeof(gre)) {
>               PIPEX_DBG((NULL, LOG_DEBUG,
> @@ -1592,6 +1654,8 @@ pipex_pptp_userland_output(struct mbuf *
>       u_char *cp, *cp0;
>       uint32_t val32;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       len = sizeof(struct pipex_gre_header);
>       m_copydata(m0, 0, len, &gre0);
>       gre = &gre0;
> @@ -1776,6 +1840,8 @@ pipex_l2tp_lookup_session(struct mbuf *m
>       uint16_t flags, session_id, ver;
>       u_char *cp, buf[PIPEX_L2TP_MINLEN];
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
>               PIPEX_DBG((NULL, LOG_DEBUG,
>                   "<%s> packet length is too short", __func__));
> @@ -1829,6 +1895,8 @@ pipex_l2tp_input(struct mbuf *m0, int of
>       int rewind = 0;
>  
>       NET_ASSERT_LOCKED();
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       length = offset = ns = nr = 0;
>       l2tp_session = &session->proto.l2tp;
>       l2tp_session->ipsecflowinfo = ipsecflowinfo;
> @@ -1975,6 +2043,8 @@ pipex_l2tp_userland_lookup_session(struc
>       struct pipex_session *session;
>       uint16_t session_id, tunnel_id, flags;
>  
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
> +
>       if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
>               return (NULL);
>  
> @@ -2031,6 +2101,8 @@ pipex_l2tp_userland_output(struct mbuf *
>       struct pipex_l2tp_header *l2tp;
>       struct pipex_l2tp_seq_header *seq;
>       uint16_t ns, nr;
> +
> +     MUTEX_ASSERT_LOCKED(&pipex_list_mtx);
>  
>       /* check length */
>       PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
> Index: sys/net/pipex.h
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex.h,v
> retrieving revision 1.31
> diff -u -p -r1.31 pipex.h
> --- sys/net/pipex.h   2 Jan 2022 22:36:04 -0000       1.31
> +++ sys/net/pipex.h   20 Jun 2022 14:44:03 -0000
> @@ -29,6 +29,8 @@
>  #ifndef NET_PIPEX_H
>  #define NET_PIPEX_H 1
>  
> +#include <sys/mutex.h>
> +
>  /*
>   * Names for pipex sysctl objects
>   */
> @@ -174,6 +176,7 @@ struct pipex_session_descr_req {
>  
>  #ifdef _KERNEL
>  extern int   pipex_enable;
> +extern struct mutex pipex_list_mtx;
>  
>  struct pipex_session;
>  
> Index: sys/net/pipex_local.h
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex_local.h,v
> retrieving revision 1.45
> diff -u -p -r1.45 pipex_local.h
> --- sys/net/pipex_local.h     15 Feb 2022 03:31:17 -0000      1.45
> +++ sys/net/pipex_local.h     20 Jun 2022 14:44:03 -0000
> @@ -26,6 +26,8 @@
>   * SUCH DAMAGE.
>   */
>  
> +#include <sys/mutex.h>
> +
>  #define      PIPEX_PPTP      1
>  #define      PIPEX_L2TP      1
>  #define      PIPEX_PPPOE     1
> @@ -53,10 +55,13 @@
>   * Locks used to protect struct members:
>   *      I       immutable after creation
>   *      N       net lock
> + *      L       pipex_list_mtx
>   *      s       this pipex_session' `pxs_mtx'
>   *      m       this pipex_mppe' `pxm_mtx'
>   */
>  
> +extern struct mutex pipex_list_mtx;
> +
>  #ifdef PIPEX_MPPE
>  /* mppe rc4 key */
>  struct pipex_mppe {
> @@ -152,24 +157,24 @@ struct cpumem;
>  /* pppac ip-extension session table */
>  struct pipex_session {
>       struct radix_node       ps4_rn[2];
> -                                     /* [N] tree glue, and other values */
> +                                     /* [L] tree glue, and other values */
>       struct radix_node       ps6_rn[2];
> -                                     /* [N] tree glue, and other values */
> +                                     /* [L] tree glue, and other values */
>       struct mutex pxs_mtx;
>  
> -     LIST_ENTRY(pipex_session) session_list; /* [N] all session chain */
> -     LIST_ENTRY(pipex_session) state_list;   /* [N] state list chain */
> -     LIST_ENTRY(pipex_session) id_chain;     /* [N] id hash chain */
> +     LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */
> +     LIST_ENTRY(pipex_session) state_list;   /* [L] state list chain */
> +     LIST_ENTRY(pipex_session) id_chain;     /* [L] id hash chain */
>       LIST_ENTRY(pipex_session) peer_addr_chain;
> -                                     /* [N] peer's address hash chain */
> -     uint16_t        state;          /* [N] pipex session state */
> +                                     /* [L] peer's address hash chain */
> +     uint16_t        state;          /* [L] pipex session state */
>  #define PIPEX_STATE_INITIAL          0x0000
>  #define PIPEX_STATE_OPENED           0x0001
>  #define PIPEX_STATE_CLOSE_WAIT               0x0002
>  #define PIPEX_STATE_CLOSE_WAIT2              0x0003
>  #define PIPEX_STATE_CLOSED           0x0004
>  
> -     uint32_t        idle_time;      /* [N] idle time in seconds */
> +     uint32_t        idle_time;      /* [L] idle time in seconds */
>       uint16_t        ip_forward:1,   /* [N] {en|dis}ableIP forwarding */
>                       ip6_forward:1,  /* [I] {en|dis}able IPv6 forwarding */
>                       is_multicast:1, /* [I] virtual entry for multicast */
> @@ -400,6 +405,7 @@ void                  pipex_rele_session
>  int                   pipex_link_session(struct pipex_session *,
>                            struct ifnet *, void *);
>  void                  pipex_unlink_session(struct pipex_session *);
> +void                  pipex_unlink_session_locked(struct pipex_session *);
>  void                  pipex_export_session_stats(struct pipex_session *,
>                            struct pipex_statistics *);
>  int                   pipex_config_session (struct pipex_session_config_req 
> *,
> Index: sys/netinet/ip_gre.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_gre.c,v
> retrieving revision 1.73
> diff -u -p -r1.73 ip_gre.c
> --- sys/netinet/ip_gre.c      25 Feb 2022 23:51:03 -0000      1.73
> +++ sys/netinet/ip_gre.c      20 Jun 2022 14:44:03 -0000
> @@ -70,7 +70,6 @@ gre_usrreq(struct socket *so, int req, s
>       if (inp != NULL && inp->inp_pipex && req == PRU_SEND) {
>               struct sockaddr_in *sin4;
>               struct in_addr *ina_dst;
> -             struct pipex_session *session;
>  
>               ina_dst = NULL;
>               if ((so->so_state & SS_ISCONNECTED) != 0) {
> @@ -81,10 +80,18 @@ gre_usrreq(struct socket *so, int req, s
>                       if (in_nam2sin(nam, &sin4) == 0)
>                               ina_dst = &sin4->sin_addr;
>               }
> -             if (ina_dst != NULL &&
> -                 (session = pipex_pptp_userland_lookup_session_ipv4(m,
> -                         *ina_dst)))
> -                     m = pipex_pptp_userland_output(m, session);
> +             if (ina_dst != NULL) {
> +                     struct pipex_session *session;
> +
> +                     mtx_enter(&pipex_list_mtx);
> +                     session = pipex_pptp_userland_lookup_session_ipv4(m,
> +                         *ina_dst);
> +
> +                     if(session != NULL)
> +                             m = pipex_pptp_userland_output(m, session);
> +
> +                     mtx_leave(&pipex_list_mtx);
> +             }
>  
>               if (m == NULL)
>                       return (ENOMEM);
> Index: sys/netinet/udp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
> retrieving revision 1.278
> diff -u -p -r1.278 udp_usrreq.c
> --- sys/netinet/udp_usrreq.c  15 May 2022 09:12:20 -0000      1.278
> +++ sys/netinet/udp_usrreq.c  20 Jun 2022 14:44:03 -0000
> @@ -565,13 +565,17 @@ udp_input(struct mbuf **mp, int *offp, i
>       if (pipex_enable && inp->inp_pipex) {
>               struct pipex_session *session;
>               int off = iphlen + sizeof(struct udphdr);
> +
> +             mtx_enter(&pipex_list_mtx);
>               if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) {
>                       if ((m = *mp = pipex_l2tp_input(m, off, session,
>                           ipsecflowinfo)) == NULL) {
>                               /* the packet is handled by PIPEX */
> +                             mtx_leave(&pipex_list_mtx);
>                               return IPPROTO_DONE;
>                       }
>               }
> +             mtx_leave(&pipex_list_mtx);
>       }
>  #endif
>  
> @@ -1135,6 +1139,8 @@ udp_usrreq(struct socket *so, int req, s
>               if (inp->inp_pipex) {
>                       struct pipex_session *session;
>  
> +                     mtx_enter(&pipex_list_mtx);
> +
>                       if (addr != NULL)
>                               session =
>                                   pipex_l2tp_userland_lookup_session(m,
> @@ -1153,9 +1159,12 @@ udp_usrreq(struct socket *so, int req, s
>                       if (session != NULL)
>                               if ((m = pipex_l2tp_userland_output(
>                                   m, session)) == NULL) {
> +                                     mtx_leave(&pipex_list_mtx);
>                                       error = ENOMEM;
>                                       goto release;
>                               }
> +
> +                     mtx_leave(&pipex_list_mtx);
>               }
>  #endif
>  
> 

Reply via email to