VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45889

CVE-2026-45889

Description

In the Linux kernel, the following vulnerability has been resolved:

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

MPTCP-level OoOs are physiological when multiple subflows are active concurrently and will not cause retransmissions nor are caused by drops.

Accounting for them in mptcp_rcvbuf_grow() causes the rcvbuf slowly drifting towards tcp_rmem[2].

Remove such accounting. Note that subflows will still account for TCP-level OoO when the MPTCP-level rcvbuf is propagated.

This also closes a subtle and very unlikely race condition with rcvspace init; active sockets with user-space holding the msk-level socket lock, could complete such initialization in the receive callback, after that the first OoO data reaches the rcvbuf and potentially triggering a divide by zero Oops.

Affected products

1

Patches

6
fb7bf00b04a6

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index e4bb7e2d7b19a0..15a70af7b776dc 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    
6b329393502e

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index 9b8c51937eb2ac..758a6dcb1d7baa 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    
400ee4854ade

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index 8d323366741810..cfa38bdaf2a924 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    
fb7bf00b04a6

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index e4bb7e2d7b19a0..15a70af7b776dc 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    
400ee4854ade

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index 8d323366741810..cfa38bdaf2a924 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    
6b329393502e

mptcp: do not account for OoO in mptcp_rcvbuf_grow()

1 file changed · +0 7
  • net/mptcp/protocol.c+0 7 modified
    diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
    index 9b8c51937eb2ac..758a6dcb1d7baa 100644
    --- a/net/mptcp/protocol.c
    +++ b/net/mptcp/protocol.c
    @@ -224,9 +224,6 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 newval)
     	do_div(grow, oldval);
     	rcvwin += grow << 1;
     
    -	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
    -		rcvwin += MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq - msk->ack_seq;
    -
     	cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);
     
     	rcvbuf = min_t(u32, mptcp_space_from_win(sk, rcvwin), cap);
    @@ -350,9 +347,6 @@ merge_right:
     end:
     	skb_condense(skb);
     	skb_set_owner_r(skb, sk);
    -	/* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */
    -	if (sk->sk_socket)
    -		mptcp_rcvbuf_grow(sk, msk->rcvq_space.space);
     }
     
     static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset,
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Incorrectly accounting for MPTCP-level out-of-order data in `mptcp_rcvbuf_grow()` causes the receive buffer to inflate unnecessarily and introduces a race condition that can lead to a divide-by-zero Oops."

Attack vector

An attacker who can cause out-of-order (OoO) MPTCP data delivery — which is normal when multiple subflows are active concurrently — triggers the bug. Each OoO data arrival calls `mptcp_rcvbuf_grow()`, which adds the OoO gap size to the receive-window estimate, causing the receive buffer to slowly drift toward `tcp_rmem[2]` (the maximum). Additionally, a very unlikely race exists: if user-space holds the msk-level socket lock during `rcvspace` init, the first OoO data can reach the receive callback before initialization completes, potentially causing a divide-by-zero Oops [patch_id=2661647].

Affected code

The vulnerability is in `net/mptcp/protocol.c` within the `mptcp_rcvbuf_grow()` function and the receive-data path that calls it. Two code regions are removed by the patch: the OoO-queue size check in `mptcp_rcvbuf_grow()` (lines 227-228 of the old code) and the call to `mptcp_rcvbuf_grow()` at the end of the data-merge path (lines 350-352 of the old code) [patch_id=2661647][patch_id=2661648][patch_id=2661649][patch_id=2661644][patch_id=2661645][patch_id=2661646].

What the fix does

The patch removes two hunks from `net/mptcp/protocol.c`. First, it deletes the conditional that added the OoO gap (`end_seq - ack_seq`) to `rcvwin` inside `mptcp_rcvbuf_grow()`, because MPTCP-level OoO is physiological and should not inflate the buffer. Second, it removes the call to `mptcp_rcvbuf_grow()` from the data-merge path (the `end:` label), which was invoked on every received skb for non-orphaned sockets. Removing this call eliminates both the buffer drift and the race where `mptcp_rcvbuf_grow()` could run before `rcvspace` initialization completed, preventing the potential divide-by-zero Oops [patch_id=2661647][patch_id=2661648][patch_id=2661649][patch_id=2661644][patch_id=2661645][patch_id=2661646].

Preconditions

  • configThe MPTCP socket must have multiple active subflows to generate MPTCP-level out-of-order data.
  • authFor the divide-by-zero race: user-space must hold the msk-level socket lock during rcvspace initialization.
  • networkNo authentication or special network position is required beyond being able to send data over the MPTCP connection.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.