Commit 85083796 authored by Yang Yang's avatar Yang Yang Committed by Jakub Kicinski
Browse files

bridge: br_nd_send: validate ND option lengths



br_nd_send() walks ND options according to option-provided lengths.
A malformed option can make the parser advance beyond the computed
option span or use a too-short source LLADDR option payload.

Validate option lengths against the remaining NS option area before
advancing, and only read source LLADDR when the option is large enough
for an Ethernet address.

Fixes: ed842fae ("bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports")
Cc: stable@vger.kernel.org
Reported-by: default avatarYifan Wu <yifanwucs@gmail.com>
Reported-by: default avatarJuefei Pu <tomapufckgml@gmail.com>
Tested-by: default avatarAo Zhou <n05ec@lzu.edu.cn>
Co-developed-by: default avatarYuan Tan <tanyuan98@outlook.com>
Signed-off-by: default avatarYuan Tan <tanyuan98@outlook.com>
Suggested-by: default avatarXin Liu <bird@lzu.edu.cn>
Signed-off-by: default avatarYang Yang <n05ec@lzu.edu.cn>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Acked-by: default avatarNikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20260326034441.2037420-3-n05ec@lzu.edu.cn


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a01aee7c
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -288,11 +288,13 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
	ns_olen = request->len - (skb_network_offset(request) +
				  sizeof(struct ipv6hdr)) - sizeof(*ns);
	for (i = 0; i < ns_olen - 1; i += (ns->opt[i + 1] << 3)) {
		if (!ns->opt[i + 1]) {
		if (!ns->opt[i + 1] || i + (ns->opt[i + 1] << 3) > ns_olen) {
			kfree_skb(reply);
			return;
		}
		if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
			if ((ns->opt[i + 1] << 3) >=
			    sizeof(struct nd_opt_hdr) + ETH_ALEN)
				daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
			break;
		}