Use pskb_may_pull() to make sure the optional fields are in skb linear parts, so we can safely read them later.
It's easy to reproduce the issue with a net driver that supports paged skb data. Just create a L2TPv3 over IP tunnel and then generates some network traffic. Once reproduced, rx err in /sys/kernel/debug/l2tp/tunnels will increase. Signed-off-by: Jacob Wen <jian.w....@oracle.com> --- Changes in v2: 1. Only fix L2TPv3 to make code simple. To fix both L2TPv3 and L2TPv2, we'd better refactor l2tp_recv_common. It's complicated to do so. 2. Reloading pointers after pskb_may_pull --- net/l2tp/l2tp_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 26f1d435696a..e9a17c634c1a 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -625,6 +625,20 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, int offset; u32 ns, nr; + if (tunnel->version != L2TP_HDR_VER_2) { + int opt_len = session->peer_cookie_len + + l2tp_get_l2specific_len(session); + + if (opt_len > 0) { + int off = ptr - optr; + + if (!pskb_may_pull(skb, off + opt_len)) + goto discard; + optr = skb->data; + ptr = optr + off; + } + } + /* Parse and check optional cookie */ if (session->peer_cookie_len > 0) { if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { -- 2.17.1