From: Guikun Yang <yangguikun19@qq.com>
To: Guillaume Nault <gnault@redhat.com>
Cc: James Chapman <jchapman@katalix.com>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [BUG] l2tp: OOB read in l2tp_recv_common() for L2TPv2 sessions with 8-byte peer cookie
Date: Mon, 26 Oct 2026 01:35:25 +0800 [thread overview]
Message-ID: <tencent_389453EACB37DA0886D3896959D4A4CF5006@qq.com> (raw)
Hi Guillaume,
l2tp_recv_common() (net/l2tp/l2tp_core.c) reads L2TPv2 optional header
fields beyond the linear area guaranteed by the caller, for sessions
configured with an 8-byte peer cookie.
The UDP entry path only guarantees the first L2TP_HDR_SIZE_MAX (14)
bytes:
if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX))
goto pass;
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
Inside l2tp_recv_common(), for a L2TPv2 session with peer_cookie_len =
8, the cookie check consumes bytes [6, 14):
if (session->peer_cookie_len > 0) {
if (memcmp(ptr, &session->peer_cookie[0],
session->peer_cookie_len)) { ... discard }
ptr += session->peer_cookie_len; /* ptr = optr + 14 */
}
Then the sequence-number branch for L2TPv2 reads at ptr:
if (hdrflags & L2TP_HDRFLAG_S) {
L2TP_SKB_CB(skb)->ns = ntohs(*(__be16 *)ptr); /* [14, 16) OOB */
ptr += 2;
ptr += 2;
}
With a minimal 14-byte L2TPv2 packet (6-byte fixed header + 8-byte
cookie, no payload, L2TP_HDRFLAG_S set), skb->len is exactly 14 after
__skb_pull(udphdr), so the read at [14, 16) is past the end of the
linear area — a 2-byte slab-out-of-bounds read (KASAN catchable). The
subsequent `ptr += 2 + offset` handling for L2TP_HDRFLAG_O can read
even further out ([18, 20) with the same setup).
Trigger conditions:
- an L2TPv2 session with peer_cookie_len == 8 (admin-configured),
- a UDP packet whose L2TP payload is exactly 14 bytes, with
L2TP_HDRFLAG_S set and the correct cookie.
The peer address is not verified on the UDP path (l2tp_v2_session_get()
matches only on tunnel_id/session_id), so any host that knows the
cookie — i.e. a peer of the tunnel, or anyone when no cookie is
configured (in which case the OOB read does not trigger, since the
pointer stays at 6 and the seq read lands at [6, 10)) — can send such a
packet.
This is the L2TPv2 counterpart of the L2TPv3 optional-fields OOB fixed
in 2019 by commit 4522a70db7aa ("l2tp: fix reading optional fields of
L2TPv3"), which added l2tp_v3_ensure_opt_in_linear(). The commit
message of that fix explicitly noted that fixing L2TPv2 as well would
require refactoring l2tp_recv_common() and was deferred:
To fix both L2TPv3 and L2TPv2, we'd better refactor
l2tp_recv_common. It's complicated to do so.
L2TPv2 has remained unprotected since. The in-function
pskb_may_pull(skb, offset) at the end of l2tp_recv_common() runs only
after all the header reads have already happened, so it cannot help.
A minimal fix for the v2 path could ensure the header is fully linear
before parsing — e.g. in l2tp_udp_encap_recv(), after determining
version == L2TP_HDR_VER_2 and before calling l2tp_recv_common():
if (session->tunnel->version == L2TP_HDR_VER_2 &&
!pskb_may_pull(skb, 6 + session->peer_cookie_len +
(hdrflags & L2TP_HDRFLAG_S ? 4 : 0)))
goto invalid;
(or a full refactor pulling the cookie/seq handling into a
l2tp_v2_ensure_opt_in_linear() helper mirroring the v3 one).
Checked against 7.3.0-rc7 and linux-next (2026-10-24): neither carries a
fix; l2tp_v3_ensure_opt_in_linear() is still v3-only. I found no
report of this specific OOB on lore/marc.
Best,
Guikun Yang
next reply other threads:[~2026-10-25 17:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-25 17:35 Guikun Yang [this message]
2026-10-26 11:19 ` Guillaume Nault
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=tencent_389453EACB37DA0886D3896959D4A4CF5006@qq.com \
--to=yangguikun19@qq.com \
--cc=edumazet@google.com \
--cc=gnault@redhat.com \
--cc=jchapman@katalix.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/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
all inboxes | Powered by JetHome®