The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=12c542cd0e9efc1ad9f20f1035402c0acf6d403f

commit 12c542cd0e9efc1ad9f20f1035402c0acf6d403f
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2022-05-19 13:12:54 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2022-05-20 12:49:30 +0000

    dummynet: do not store struct ifnet pointers
    
    The dn_pkt_tag tag contained a struct ifnet pointer. If we persist that
    across NET_EPOCH boundaries (as we did in dummynet) we risk panics if
    the interface is removed between the packet being enqueued and it being
    dequeued.
    
    Convert the pointer into an index/generation pair and restore it when
    the packet is taken out of the queue.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D35256
---
 sys/netpfil/ipfw/ip_dn_io.c      | 10 +++++++---
 sys/netpfil/ipfw/ip_dn_private.h |  3 ++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c
index 824e7450fb8f..98f9d08495df 100644
--- a/sys/netpfil/ipfw/ip_dn_io.c
+++ b/sys/netpfil/ipfw/ip_dn_io.c
@@ -766,12 +766,12 @@ dummynet_send(struct mbuf *m)
                        /* extract the dummynet info, rename the tag
                         * to carry reinject info.
                         */
+                       ifp = ifnet_byindexgen(pkt->if_index, pkt->if_idxgen);
                        if (pkt->dn_dir == (DIR_OUT | PROTO_LAYER2) &&
-                               pkt->ifp == NULL) {
+                               ifp == NULL) {
                                dst = DIR_DROP;
                        } else {
                                dst = pkt->dn_dir;
-                               ifp = pkt->ifp;
                                tag->m_tag_cookie = MTAG_IPFW_RULE;
                                tag->m_tag_id = 0;
                        }
@@ -852,7 +852,11 @@ tag_mbuf(struct mbuf *m, int dir, struct ip_fw_args *fwa)
        /* only keep this info */
        dt->rule.info &= (IPFW_ONEPASS | IPFW_IS_DUMMYNET);
        dt->dn_dir = dir;
-       dt->ifp = fwa->flags & IPFW_ARGS_OUT ? fwa->ifp : NULL;
+       if (fwa->flags & IPFW_ARGS_OUT && fwa->ifp != NULL) {
+               NET_EPOCH_ASSERT();
+               dt->if_index = fwa->ifp->if_index;
+               dt->if_idxgen = fwa->ifp->if_idxgen;
+       }
        /* dt->output tame is updated as we move through */
        dt->output_time = V_dn_cfg.curr_time;
        dt->iphdr_off = (dir & PROTO_LAYER2) ? ETHER_HDR_LEN : 0;
diff --git a/sys/netpfil/ipfw/ip_dn_private.h b/sys/netpfil/ipfw/ip_dn_private.h
index d7df31b85345..1cd38a2c94d8 100644
--- a/sys/netpfil/ipfw/ip_dn_private.h
+++ b/sys/netpfil/ipfw/ip_dn_private.h
@@ -374,7 +374,8 @@ struct dn_pkt_tag {
        int dn_dir;             /* action when packet comes out.*/
                                /* see ip_fw_private.h          */
        uint64_t output_time;   /* when the pkt is due for delivery*/
-       struct ifnet *ifp;      /* interface, for ip_output     */
+       uint16_t if_index;
+       uint16_t if_idxgen;
        struct _ip6dn_args ip6opt;      /* XXX ipv6 options     */
        uint16_t iphdr_off;     /* IP header offset for mtodo() */
 };

Reply via email to