From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Florian Westphal <fw@strlen.de>, sungzii <sungzii@pm.me>,
Sasha Levin <sashal@kernel.org>,
pablo@netfilter.org, netfilter-devel@vger.kernel.org,
coreteam@netfilter.org
Subject: [PATCH AUTOSEL 6.19-5.10] netfilter: xt_tcpmss: check remaining length before reading optlen
Date: Sat, 14 Feb 2026 16:23:40 -0500 [thread overview]
Message-ID: <20260214212452.782265-75-sashal@kernel.org> (raw)
In-Reply-To: <20260214212452.782265-1-sashal@kernel.org>
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 735ee8582da3d239eb0c7a53adca61b79fb228b3 ]
Quoting reporter:
In net/netfilter/xt_tcpmss.c (lines 53-68), the TCP option parser reads
op[i+1] directly without validating the remaining option length.
If the last byte of the option field is not EOL/NOP (0/1), the code attempts
to index op[i+1]. In the case where i + 1 == optlen, this causes an
out-of-bounds read, accessing memory past the optlen boundary
(either reading beyond the stack buffer _opt or the
following payload).
Reported-by: sungzii <sungzii@pm.me>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Analysis of netfilter: xt_tcpmss: check remaining length before
reading optlen
### 1. COMMIT MESSAGE ANALYSIS
The commit message is clear and detailed. The reporter (sungzii)
explains the exact bug mechanism:
- In the TCP option parser in `xt_tcpmss.c`, when iterating through TCP
options, the code reads `op[i+1]` without first checking that `i+1` is
within bounds.
- If the last byte of the option field is not EOL/NOP (value 0 or 1),
the code falls through to the `else` branch and reads `op[i+1]`, which
is an **out-of-bounds read** when `i + 1 == optlen`.
Key indicators:
- **"Reported-by: sungzii"** - a user found and reported this bug
- **Out-of-bounds read** - a real memory safety bug
- **Netfilter subsystem** - network-facing, security-sensitive code that
processes packets
### 2. CODE CHANGE ANALYSIS
The fix is a single-line change:
```c
- if (op[i] < 2)
+ if (op[i] < 2 || i == optlen - 1)
```
**What was wrong:** The TCP option parsing loop iterates through option
bytes. Options with values 0 (EOL) and 1 (NOP) are single-byte. All
other options use a TLV (type-length-value) format where `op[i+1]`
contains the length. The code checks `if (op[i] < 2)` to handle single-
byte options, and otherwise reads `op[i+1]` for the length. But if `i`
is the last valid index (`i == optlen - 1`), and the option byte is >=
2, the code reads `op[i+1]` which is **past the end of the buffer**.
**The fix:** Before reading `op[i+1]`, the code now also checks if `i`
is at the last byte (`i == optlen - 1`). If so, it treats it as a
single-byte increment (just `i++`), which will terminate the loop on the
next iteration since `i` will then equal `optlen`.
This is:
- **Obviously correct** - if there's only one byte left, we can't read a
2-byte option header
- **Minimal** - one condition added to an existing check
- **Safe** - the worst case is we skip a malformed trailing option byte,
which is the right behavior
### 3. CLASSIFICATION
- **Bug type:** Out-of-bounds read (memory safety)
- **Security relevance:** HIGH - this is in the netfilter packet
processing path. An attacker could craft TCP packets with malformed
options to trigger the OOB read. This could leak kernel memory
contents or trigger a crash depending on the memory layout.
- **Category:** Bounds validation fix
### 4. SCOPE AND RISK ASSESSMENT
- **Lines changed:** 1 line modified
- **Files changed:** 1 file (`net/netfilter/xt_tcpmss.c`)
- **Risk of regression:** Extremely low. The added condition only
activates when `i == optlen - 1`, meaning the last byte of the
options. In that case, incrementing by 1 exits the loop. This cannot
break valid TCP option parsing because valid multi-byte options always
have at least 2 bytes.
- **Subsystem:** Netfilter - core networking/firewall code used by
virtually all Linux deployments
### 5. USER IMPACT
- **Who is affected:** Anyone using the `tcpmss` iptables/nftables match
rule, which is common in firewall configurations
- **Trigger:** Receiving a TCP packet with malformed options (last
option byte >= 2 with no room for the length byte)
- **Severity:** Out-of-bounds read in packet processing - potential
information leak or crash
- **Exploitability:** Could be triggered remotely by sending crafted TCP
packets
### 6. STABILITY INDICATORS
- Author is Florian Westphal, a well-known netfilter maintainer
- The fix is trivial and obviously correct
- The code being fixed has existed for a very long time (the `xt_tcpmss`
module is ancient)
### 7. DEPENDENCY CHECK
- No dependencies on other commits
- The affected code exists in all stable trees (this is long-standing
code)
- The patch applies cleanly as a standalone fix
### CONCLUSION
This is a textbook stable backport candidate:
- **Fixes a real bug:** Out-of-bounds read in TCP option parsing
- **Security-sensitive:** In the netfilter packet processing path,
remotely triggerable
- **Minimal and surgical:** One condition added to one line
- **Zero regression risk:** The additional check is strictly correct
- **No new features:** Pure bug fix
- **Author is subsystem maintainer:** Florian Westphal maintains
netfilter
- **Affects all stable trees:** The vulnerable code is ancient
**YES**
net/netfilter/xt_tcpmss.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 37704ab017992..0d32d4841cb32 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -61,7 +61,7 @@ tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par)
return (mssval >= info->mss_min &&
mssval <= info->mss_max) ^ info->invert;
}
- if (op[i] < 2)
+ if (op[i] < 2 || i == optlen - 1)
i++;
else
i += op[i+1] ? : 1;
--
2.51.0
prev parent reply other threads:[~2026-02-14 21:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260214212452.782265-1-sashal@kernel.org>
2026-02-14 21:22 ` [PATCH AUTOSEL 6.19-5.10] netfilter: nf_conntrack: Add allow_clash to generic protocol handler Sasha Levin
2026-02-14 21:23 ` Sasha Levin [this message]
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=20260214212452.782265-75-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=coreteam@netfilter.org \
--cc=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
--cc=sungzii@pm.me \
/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