From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.simonwunderlich.de (mail.simonwunderlich.de [23.88.38.48]) (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 0CB2444BCAE for ; Fri, 15 May 2026 09:56:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.38.48 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778838962; cv=none; b=qmoC2x9LbDtLlRe0CAjSS4YsJWz9iqN0h+cm7PJBcfBq2jnL8YGBf6JpbSLSMPeQwP5d+Q/p36LTe7UmvuVHxBBNGrHfn1ND5OfyWNh8FxE6tdYBgfs3/moKgbrkto8qLD5pGypx9b748PSTy7kOU/lq3vVoCA++G5Jx7zis594= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778838962; c=relaxed/simple; bh=jrm1Z46R994p1ARKxfPUyfcP43DgOmNzxbExoppy4ME=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B9Ud1M9stSDztQ8mAqKhXlgrk7g2fH4BC2hQ6bPXgSonLoCYU33ShLFatitIew9br0YGFBNYStZC4D0IU+xGVKhGqyU7VF4U3cbPC9QAjYgfvQ5NQIsw+T4YB/7qGLkFR9wMXPJOJVGueYVWz5cZKNAi6zdKqdxpmfObEp95XsQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de; spf=pass smtp.mailfrom=simonwunderlich.de; dkim=pass (2048-bit key) header.d=simonwunderlich.de header.i=@simonwunderlich.de header.b=1/bNwpfF; arc=none smtp.client-ip=23.88.38.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=simonwunderlich.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=simonwunderlich.de header.i=@simonwunderlich.de header.b="1/bNwpfF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=simonwunderlich.de; s=09092022; t=1778838954; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B9Sja0xiBRys6g0DgbxHi3DzYvtG7c3y9TxEzig6y4A=; b=1/bNwpfFc9xXEZebnwjT+9ufpSs5F/4qPtRTPM0aVTz3HWGBXve3aVlyQwQfLvrbmUXOWi 4oeI+X1fLrmefbPBja/tHekSpcq805uQ5evmlQuyutE1wtkK1ite1NWaT9SFUXfCajFanT EulPZDQD8VpxJLPmCy82imOHZYQEzAVQ4aUW7exRXNmAJctvc6D8SVNK8QCNfDtl3R9V3Y AHNu02gEeNuggTuI84dnRigviTCqIiJqGYutVDu9o0Z/RY9hceSYQ91fk7+W1vZDlqT3vF kfohgGWvO385rPFnAMja7qcthG+jA0tZUJVZ6Syk7/XZDGS/IvwmYwYPQki8xQ== From: Simon Wunderlich To: netdev@vger.kernel.org Cc: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , b.a.t.m.a.n@lists.open-mesh.org, Ruide Cao , stable@kernel.org, Yuan Tan , Yifan Wu , Juefei Pu , Xin Liu , Ren Wei , Ren Wei , Sven Eckelmann , Simon Wunderlich Subject: [PATCH net 09/14] batman-adv: fix fragment reassembly length accounting Date: Fri, 15 May 2026 11:55:34 +0200 Message-ID: <20260515095540.325586-10-sw@simonwunderlich.de> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260515095540.325586-1-sw@simonwunderlich.de> References: <20260515095540.325586-1-sw@simonwunderlich.de> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Ruide Cao batman-adv keeps a running payload length for queued fragments and uses it to validate a fragment chain before reassembly. That accounting currently allows the accumulated fragment length to be truncated during updates. As a result, malformed fragment chains can bypass the intended validation and drive reassembly with inconsistent length state, leading to a local denial of service. Fix the accounting by storing the accumulated length in a length-typed field and rejecting update overflows before the existing validation logic runs. The fix was verified against the original reproducer and against valid fragment reassembly paths. Fixes: 610bfc6bc99b ("batman-adv: Receive fragmented packets and merge") Cc: stable@kernel.org Reported-by: Yuan Tan Reported-by: Yifan Wu Reported-by: Juefei Pu Reported-by: Xin Liu Signed-off-by: Ruide Cao Tested-by: Ren Wei Signed-off-by: Ren Wei Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/fragmentation.c | 23 +++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index f4e45cc258164..1152c2ce0c1ea 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -80,9 +81,9 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node, * * Return: the maximum size of payload that can be fragmented. */ -static int batadv_frag_size_limit(void) +static size_t batadv_frag_size_limit(void) { - int limit = BATADV_FRAG_MAX_FRAG_SIZE; + size_t limit = BATADV_FRAG_MAX_FRAG_SIZE; limit -= sizeof(struct batadv_frag_packet); limit *= BATADV_FRAG_MAX_FRAGMENTS; @@ -143,7 +144,9 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, struct batadv_frag_packet *frag_packet; u8 bucket; u16 seqno, hdr_size = sizeof(struct batadv_frag_packet); + bool overflow = false; bool ret = false; + size_t data_len; /* Linearize packet to avoid linearizing 16 packets in a row when doing * the later merge. Non-linear merge should be added to remove this @@ -153,6 +156,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, goto err; frag_packet = (struct batadv_frag_packet *)skb->data; + data_len = skb->len - hdr_size; seqno = ntohs(frag_packet->seqno); bucket = seqno % BATADV_FRAG_BUFFER_COUNT; @@ -171,7 +175,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, spin_lock_bh(&chain->lock); if (batadv_frag_init_chain(chain, seqno)) { hlist_add_head(&frag_entry_new->list, &chain->fragment_list); - chain->size = skb->len - hdr_size; + chain->size = data_len; chain->timestamp = jiffies; chain->total_size = ntohs(frag_packet->total_size); ret = true; @@ -188,7 +192,11 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, if (frag_entry_curr->no < frag_entry_new->no) { hlist_add_before(&frag_entry_new->list, &frag_entry_curr->list); - chain->size += skb->len - hdr_size; + + if (check_add_overflow(chain->size, data_len, + &chain->size)) + overflow = true; + chain->timestamp = jiffies; ret = true; goto out; @@ -201,13 +209,16 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, /* Reached the end of the list, so insert after 'frag_entry_last'. */ if (likely(frag_entry_last)) { hlist_add_behind(&frag_entry_new->list, &frag_entry_last->list); - chain->size += skb->len - hdr_size; + + if (check_add_overflow(chain->size, data_len, &chain->size)) + overflow = true; + chain->timestamp = jiffies; ret = true; } out: - if (chain->size > batadv_frag_size_limit() || + if (overflow || chain->size > batadv_frag_size_limit() || chain->total_size != ntohs(frag_packet->total_size) || chain->total_size > batadv_frag_size_limit()) { /* Clear chain if total size of either the list or the packet diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 739439e2b2350..c8c3e8064f00c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -301,7 +301,7 @@ struct batadv_frag_table_entry { u16 seqno; /** @size: accumulated size of packets in list */ - u16 size; + size_t size; /** @total_size: expected size of the assembled packet */ u16 total_size; -- 2.47.3