From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 980F947125E; Tue, 21 Jul 2026 18:13:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784657585; cv=none; b=ory10iBUJqNqSpgB3mZ7BwrAg8gQLa6Nn3VvHbm8uf+SXRdUjWP7wBLqQOMfYWi91Yahp0T9XKrWlE79wNaeDoorSr7zwY4d1sfCsqyX+vP01FsDsdbe+c6S6tM+0Fkgc+i1hyyUwCxJr2njn5YRUXncdDenFtCsQ+qJOdKwLbg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784657585; c=relaxed/simple; bh=t0v8b7chr9NDHeWxa9yapOXkRtU3jPV3aUglQ0yHgkY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lw8qVnRwfVzwQDhX9/4R3Xdc2JW5EZrJxp1ScEeTPuyhKEuujLnwyAlfzMCBTmAWWeIDpTWQnqWCJkP1pbpWa+Z56aDuaQ+INPyHQWgsehUsQjQaFBxVQx2q2h9pDmjGsFvJ5ml7jSLjwVqakMLZs3Mm/wJDB7CFV5uOsGDJSSQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=aCGHBJBC; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="aCGHBJBC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F3B6C1F000E9; Tue, 21 Jul 2026 18:13:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1784657584; bh=jfjqehXTftysTFvTyoB077i6LH0SGxBUbc8fMhigxCY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aCGHBJBCnqujAjZkAtmXlxDu6PLLy5T5i9uwKDskW4gCNWaQZ++SDKLiV/f+oi7gJ gXy+z3+5grrx6ejCZAS3LStWFfQOQoponmiCsr5CNvISt+wy5+7rANnqhrq96g3ibi Uvctz4i3MMe0qqOG15yMc5iuQT51heRQG3paHcNs= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, syzbot+fa2f5b1fb06147be5e16@syzkaller.appspotmail.com, Yun Zhou , Jakub Kicinski , Sasha Levin Subject: [PATCH 6.18 0819/1611] flow_dissector: check device type before reading ETH_ADDRS Date: Tue, 21 Jul 2026 17:15:35 +0200 Message-ID: <20260721152533.812008149@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260721152514.750365251@linuxfoundation.org> References: <20260721152514.750365251@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Yun Zhou [ Upstream commit bf6e8af2c8be77489bedeae9f8a9654cb710e500 ] __skb_flow_dissect() unconditionally reads 12 bytes from eth_hdr(skb) when FLOW_DISSECTOR_KEY_ETH_ADDRS is requested. This assumes the skb has a valid Ethernet header at mac_header, which is not always the case. The problem can be triggered by: 1. Creating a TUN device in L3 mode (IFF_TUN, hard_header_len=0) 2. Attaching a multiq qdisc with a flower filter matching on eth_src 3. Sending a packet through AF_PACKET Since TUN in L3 mode has no link-layer header, mac_header points to the L3 data area. The flow dissector reads 12 bytes of uninitialized skb memory, which then propagates through fl_set_masked_key() and is used as a rhashtable lookup key in __fl_lookup(), as reported by KMSAN. Rejecting the filter in the control path (at tc filter add time) is not feasible because TC filter blocks can be shared between arbitrary devices -- a filter installed on an Ethernet device may later classify packets on a headerless device through a shared block. The device association is not fixed at filter creation time. Fix this by gating the memcpy on dev->type == ARPHRD_ETHER, which ensures only true Ethernet-framed packets have their addresses read. This is more precise than the previous hard_header_len >= 12 check, which would incorrectly pass for non-Ethernet link types like IPoIB (ARPHRD_INFINIBAND, hard_header_len=24) and FDDI (hard_header_len=21) whose L2 headers are not in Ethernet format. Additionally check skb_mac_header_was_set() to guard against the pathological case where mac_header is the unset sentinel (~0U), which would cause eth_hdr() to return a wild pointer. For the act_mirred redirect case (Ethernet packet redirected to a non-Ethernet device sharing a TC block), zeroing the key is the correct behavior: the packet is now being classified on the target device, where Ethernet address matching is not semantically meaningful. Note: on non-Ethernet devices, the zeroed key will match a filter configured with all-zero MAC addresses. This is an improvement over the previous behavior where uninitialized memory could randomly match any filter. Reported-by: syzbot+fa2f5b1fb06147be5e16@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=fa2f5b1fb06147be5e16 Fixes: 67a900cc0436 ("flow_dissector: introduce support for Ethernet addresses") Signed-off-by: Yun Zhou Link: https://patch.msgid.link/20260616123057.482154-1-yun.zhou@windriver.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/core/flow_dissector.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 2a98f5fa74eb09..8aa4f9b4df8101 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1173,13 +1173,21 @@ bool __skb_flow_dissect(const struct net *net, if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct ethhdr *eth = eth_hdr(skb); struct flow_dissector_key_eth_addrs *key_eth_addrs; key_eth_addrs = skb_flow_dissector_target(flow_dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS, target_container); - memcpy(key_eth_addrs, eth, sizeof(*key_eth_addrs)); + /* TC filter blocks can be shared across devices with + * different link types, so we cannot validate this + * when the filter is installed -- check at dissect time. + */ + if (skb && skb->dev && + skb->dev->type == ARPHRD_ETHER && + skb_mac_header_was_set(skb)) + memcpy(key_eth_addrs, eth_hdr(skb), sizeof(*key_eth_addrs)); + else + memset(key_eth_addrs, 0, sizeof(*key_eth_addrs)); } if (dissector_uses_key(flow_dissector, -- 2.53.0