In the Linux kernel, the following vulnerability has been resolved:
netfilter: bridge: replace physindev with physinif in nf_bridge_info
An skb can be added to a neigh->arp_queue while waiting for an arp
reply. Where original skb’s skb->dev can be different to neigh’s
neigh->dev. For instance in case of bridging dnated skb from one veth to
another, the skb would be added to a neigh->arp_queue of the bridge.
As skb->dev can be reset back to nf_bridge->physindev and used, and as
there is no explicit mechanism that prevents this physindev from been
freed under us (for instance neigh_flush_dev doesn’t cleanup skbs from
different device’s neigh queue) we can crash on e.g. this stack:
arp_process
neigh_update
skb = __skb_dequeue(&neigh->arp_queue)
neigh_resolve_output(…, skb)
…
br_nf_dev_xmit
br_nf_pre_routing_finish_bridge_slow
skb->dev = nf_bridge->physindev
br_handle_frame_finish
Let’s use plain ifindex instead of net_device link. To peek into the
original net_device we will use dev_get_by_index_rcu(). Thus either we
get device and are safe to use it or we don’t get it and drop skb.
[
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "c4e70a87d975",
"lessThan": "7ae19ee81ca5",
"versionType": "git"
},
{
"status": "affected",
"version": "c4e70a87d975",
"lessThan": "9325e3188a9c",
"versionType": "git"
},
{
"status": "affected",
"version": "c4e70a87d975",
"lessThan": "544add1f1cfb",
"versionType": "git"
},
{
"status": "affected",
"version": "c4e70a87d975",
"lessThan": "9874808878d9",
"versionType": "git"
}
],
"programFiles": [
"include/linux/netfilter_bridge.h",
"include/linux/skbuff.h",
"net/bridge/br_netfilter_hooks.c",
"net/bridge/br_netfilter_ipv6.c",
"net/ipv4/netfilter/nf_reject_ipv4.c",
"net/ipv6/netfilter/nf_reject_ipv6.c"
],
"defaultStatus": "unaffected"
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "4.2"
},
{
"status": "unaffected",
"version": "0",
"lessThan": "4.2",
"versionType": "custom"
},
{
"status": "unaffected",
"version": "6.1.75",
"versionType": "custom",
"lessThanOrEqual": "6.1.*"
},
{
"status": "unaffected",
"version": "6.6.14",
"versionType": "custom",
"lessThanOrEqual": "6.6.*"
},
{
"status": "unaffected",
"version": "6.7.2",
"versionType": "custom",
"lessThanOrEqual": "6.7.*"
},
{
"status": "unaffected",
"version": "6.8",
"versionType": "original_commit_for_fix",
"lessThanOrEqual": "*"
}
],
"programFiles": [
"include/linux/netfilter_bridge.h",
"include/linux/skbuff.h",
"net/bridge/br_netfilter_hooks.c",
"net/bridge/br_netfilter_ipv6.c",
"net/ipv4/netfilter/nf_reject_ipv4.c",
"net/ipv6/netfilter/nf_reject_ipv6.c"
],
"defaultStatus": "affected"
}
]