Re: [PATCH] netfilter: TCPMSS: fix dropped packets when MSS option is unaligned
From: Kacper Kokot <hidden>
Date: 2026-05-26 23:21:50
Also in:
lkml, llvm, netfilter-devel, oe-kbuild-all, stable
AFAICS, these issues are not present in real environments as MSS option is placed at the beginning of the options block making it aligned by default usually.
I agree, I haven't observed it in any real environment and wouldn't expect to. I found it by reading the code and had to craft a SYN to reproduce. That said the spec permits unaligned options and the kernel shouldn't silently drop legal packets just because nobody sends them today. I can note in the v2 commit message that this is a theoretical fix.
quoted
I wonder, if we are touching this code, we could use the opportunity to make it use get_unaligned_be16() instead.gcc and clang convert x[0] << 8 | x[1] (etc) to the appropriate single instruction (and maybe byteswap) on cpu that support misaligned accesses. So there is little to gain from doing it any other way.
Happy to go with whichever you prefer for v2.
and, of course, the code works fine because 0x1 != 0 is 1.
Ha - accidentally correct. I'll add the parens in v2 tomorrow.
Also the reproducer I sent with v1 was clunky. Here's a better
one with some results below:
#!/usr/bin/env python3
import argparse
from scapy.all import *
parser = argparse.ArgumentParser()
parser.add_argument("target_ip")
parser.add_argument("target_port", type=int)
args = parser.parse_args()
def gen_mss_syn_options(nops=0):
return nops * [("NOP", None)] + [("MSS", 1460)]
def syn_check(opts):
sport = RandShort()
ip = IP(dst=args.target_ip)
syn = TCP(sport=sport, dport=args.target_port, flags="S",
seq=1000, options=opts)
synack = sr1(ip/syn, timeout=1, verbose=False)
send(ip/TCP(sport=sport, dport=args.target_port, flags="R",
seq=syn.seq+1),
verbose=False)
return not not (synack and synack.haslayer(TCP) and
synack[TCP].flags == 0x12)
for i in range(7):
n = 5
ok = sum(syn_check(gen_mss_syn_options(i)) for _ in range(n))
print(f"{i} nops + mss, {ok}/{n} probes responded")
Before:
0 nops + mss, 5/5 probes responded
1 nops + mss, 0/5 probes responded
2 nops + mss, 5/5 probes responded
3 nops + mss, 0/5 probes responded
4 nops + mss, 5/5 probes responded
5 nops + mss, 0/5 probes responded
6 nops + mss, 5/5 probes responded
After:
0 nops + mss, 5/5 probes responded
1 nops + mss, 5/5 probes responded
2 nops + mss, 5/5 probes responded
3 nops + mss, 5/5 probes responded
4 nops + mss, 5/5 probes responded
5 nops + mss, 5/5 probes responded
6 nops + mss, 5/5 probes responded