mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Star Chang <starchang@google.com>
To: netdev@vger.kernel.org
Cc: ja@ssi.bg, dsahern@kernel.org, idosch@nvidia.com,
	davem@davemloft.net,  edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org,  johannes@sipsolutions.net,
	johannes.berg@intel.com,  linux-kernel@vger.kernel.org,
	wangroger@google.com, starchang@google.com
Subject: [PATCH net v5] arp: Fix Hole-196 vulnerability by dropping unicast ARP replies in L2 BMC
Date: Fri, 30 Oct 2026 03:11:36 +0000	[thread overview]
Message-ID: <20261030031136.607720-1-starchang@google.com> (raw)

Wi-Fi 802.11 to 802.3 frame translation allows attackers to inject
frames inside GTK-encrypted L2 broadcast/multicast (BMC) frames (the
"Hole-196" vulnerability).

While the `drop_unicast_in_l2_multicast` sysctl drops unicast
IPv4/IPv6 packets received over L2 BMC, it did not check ARP replies in
`net/ipv4/arp.c`. In laboratory testing on shared-key Wi-Fi networks,
an attacker can inject an unsolicited unicast ARP reply (e.g. sip =
gateway IP, sha = attacker MAC, tip = victim IP) over L2 broadcast. If
the victim already has a neighbor entry for the gateway (such as after
normal network traffic), `neigh_update()` is invoked after the
1-second locktime window, overwriting the gateway's cached MAC address
with the attacker's MAC.

Under standard networking behavior, a non-GARP ARP reply is strictly
meant to be delivered as an L2 unicast frame (PACKET_HOST) to the
requester. The only legitimate reason an ARP reply is sent over L2
broadcast is for Gratuitous ARP (sip == tip) or address announcement.

Enhance `drop_unicast_in_l2_multicast` sysctl enforcement:
- Drop ARP replies received over L2 BMC frames unless they are
  Gratuitous ARP (sip == tip), recording
  SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST.
- Preserve legitimate GARP announcements (sip == tip) so they continue
  to defer to the `drop_gratuitous_arp` sysctl, preserving VRRP/HSRP
  router failover.
- Leave ARP requests untouched per RFC 826.
- Update Documentation/networking/ip-sysctl.rst to describe the ARP
  behavior.

Fixes: 12b74dfadb5a ("ipv4: add option to drop unicast encapsulated in L2 multicast")
Signed-off-by: Star Chang <starchang@google.com>
---
v4 -> v5:
  - Drop all IP and IPv6 changes to avoid UAF risks and adhere to RFC 1122.
  - Simplify ARP logic to strictly drop non-GARP ARP replies (ar_op == ARPOP_REPLY && sip != tip) over L2 BMC.
  - Do not inspect or gate on target hardware address (tha), leaving ARP requests untouched per RFC 826.
  - Update Documentation/networking/ip-sysctl.rst to accurately reflect ARP behavior.
  - Record SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST on drop.
  - Retain only Fixes: 12b74dfadb5a.

v3 -> v4:
  - Addressed review feedback on ratelimit logging and drop counters.

v2 -> v3:
  - Added THA validation and gratuitous ARP handling.

v1 -> v2:
  - Initial expansion to ARP.

 Documentation/networking/ip-sysctl.rst |  4 ++--
 net/ipv4/arp.c                         | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 208f46967ee5..0e4f151fac48 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -2297,8 +2297,8 @@ promote_secondaries - BOOLEAN
 	Default: 0 (disabled)
 
 drop_unicast_in_l2_multicast - BOOLEAN
-	Drop any unicast IP packets that are received in link-layer
-	multicast (or broadcast) frames.
+	Drop any unicast IP packets and non-GARP ARP replies that are
+	received in link-layer multicast (or broadcast) frames.
 
 	This behavior (for multicast) is actually a SHOULD in RFC
 	1122, but is disabled by default for compatibility reasons.
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index d409f606aec0..d6a01d05aa75 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -791,6 +791,26 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
 	    (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip)))
 		goto out_free_skb;
 
+/*
+ * Hole-196 defense for ARP:
+ * If drop_unicast_in_l2_multicast is enabled, drop ARP Replies received
+ * in L2 BMC frames unless they are Gratuitous ARP (sip == tip).
+ *
+ * Standard ARP Replies are strictly unicast (PACKET_HOST). An ARP Reply
+ * in an L2 broadcast frame with (sip != tip) is an injected unicast packet.
+ * Legitimate GARP (sip == tip) is preserved and defers to DROP_GRATUITOUS_ARP.
+ * ARP Requests are left untouched per RFC 826.
+ */
+	if ((skb->pkt_type == PACKET_BROADCAST ||
+	     skb->pkt_type == PACKET_MULTICAST) &&
+	    IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST)) {
+		if (arp->ar_op == htons(ARPOP_REPLY) && sip != tip) {
+			kfree_skb_reason(skb,
+					 SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST);
+			return NET_RX_DROP;
+		}
+	}
+
  /*
   *	For some 802.11 wireless deployments (and possibly other networks),
   *	there will be an ARP proxy and gratuitous ARP frames are attacks
-- 
2.56.0.317.g454f8302e1-goog

                 reply	other threads:[~2026-10-30  3:11 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261030031136.607720-1-starchang@google.com \
    --to=starchang@google.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=ja@ssi.bg \
    --cc=johannes.berg@intel.com \
    --cc=johannes@sipsolutions.net \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=wangroger@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®