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
This commit is contained in:
Kristof Provost 2022-05-19 15:12:54 +02:00
parent eca368ecb6
commit 12c542cd0e
2 changed files with 9 additions and 4 deletions

View File

@ -766,12 +766,12 @@ dummynet_send(struct mbuf *m)
/* extract the dummynet info, rename the tag /* extract the dummynet info, rename the tag
* to carry reinject info. * to carry reinject info.
*/ */
ifp = ifnet_byindexgen(pkt->if_index, pkt->if_idxgen);
if (pkt->dn_dir == (DIR_OUT | PROTO_LAYER2) && if (pkt->dn_dir == (DIR_OUT | PROTO_LAYER2) &&
pkt->ifp == NULL) { ifp == NULL) {
dst = DIR_DROP; dst = DIR_DROP;
} else { } else {
dst = pkt->dn_dir; dst = pkt->dn_dir;
ifp = pkt->ifp;
tag->m_tag_cookie = MTAG_IPFW_RULE; tag->m_tag_cookie = MTAG_IPFW_RULE;
tag->m_tag_id = 0; 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 */ /* only keep this info */
dt->rule.info &= (IPFW_ONEPASS | IPFW_IS_DUMMYNET); dt->rule.info &= (IPFW_ONEPASS | IPFW_IS_DUMMYNET);
dt->dn_dir = dir; 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 tame is updated as we move through */
dt->output_time = V_dn_cfg.curr_time; dt->output_time = V_dn_cfg.curr_time;
dt->iphdr_off = (dir & PROTO_LAYER2) ? ETHER_HDR_LEN : 0; dt->iphdr_off = (dir & PROTO_LAYER2) ? ETHER_HDR_LEN : 0;

View File

@ -374,7 +374,8 @@ struct dn_pkt_tag {
int dn_dir; /* action when packet comes out.*/ int dn_dir; /* action when packet comes out.*/
/* see ip_fw_private.h */ /* see ip_fw_private.h */
uint64_t output_time; /* when the pkt is due for delivery*/ 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 */ struct _ip6dn_args ip6opt; /* XXX ipv6 options */
uint16_t iphdr_off; /* IP header offset for mtodo() */ uint16_t iphdr_off; /* IP header offset for mtodo() */
}; };