History

netfilter: nf_queue: hold bridge skb->dev while queued

br_pass_frame_up() rewrites skb->dev from the ingress port to the bridge master before queueing bridge LOCAL_IN packets. NFQUEUE only holds references on state.in/out and bridge physdevs, so a queued bridge packet can retain a freed bridge master in skb->dev until reinjection. When the verdict is reinjected later, br_netif_receive_skb() re-enters the receive path with skb->dev still pointing at the freed bridge master, triggering a use-after-free. Store skb->dev in the queue entry, hold a reference on it for the queue lifetime, and use the saved device when dropping queued packets during NETDEV_DOWN handling.

Haoze Xie committed 6 months ago

Commit e1961151 parent b2870fc3 files · +6 −1Browse files

Showing the changes to include/net (1 of 3 files). Show all

Unified · Split

include/net/netfilter/nf_queue.h+1−0
@@ -14,6 +14,7 @@ struct nf_queue_entry { · 13 unmodified lines
14 struct list_head list;14 struct list_head list;
15 struct rhash_head hash_node;15 struct rhash_head hash_node;
16 struct sk_buff *skb;16 struct sk_buff *skb;
17 struct net_device *skb_dev;
17 unsigned int id;18 unsigned int id;
18 unsigned int hook_index; /* index in hook_entries->hook[] */19 unsigned int hook_index; /* index in hook_entries->hook[] */
19#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)20#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)