Re: [PATCH] netfilter: TCPMSS: fix dropped packets when MSS option is unaligned
From: Kacper Kokot
Date: Tue May 26 2026 - 19:24:03 EST
> 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.
> > 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