Unverified Commit d4956313 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10240 CVE-2024-41007

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhengchao Shao <shaozhengchao@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/IKFUTZYGUIZVMLFV2QXHGQ2I72WPATWN/ 
Fix CVE-2024-41007

Eric Dumazet (3):
  tcp: refactor tcp_retransmit_timer()
  tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
  tcp: avoid too many retransmit packets

Menglong Dong (1):
  net: tcp: fix unexcepted socket die when snd_wnd is 0

Neal Cardwell (1):
  tcp: fix incorrect undo caused by DSACK of TLP retransmit


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/IAD4B4 
 
Link:https://gitee.com/openeuler/kernel/pulls/10240

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
parents 08481d63 20f53d49
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1935,8 +1935,16 @@ void tcp_clear_retrans(struct tcp_sock *tp)
static inline void tcp_init_undo(struct tcp_sock *tp)
{
	tp->undo_marker = tp->snd_una;

	/* Retransmission still in flight may cause DSACKs later. */
	tp->undo_retrans = tp->retrans_out ? : -1;
	/* First, account for regular retransmits in flight: */
	tp->undo_retrans = tp->retrans_out;
	/* Next, account for TLP retransmits in flight: */
	if (tp->tlp_high_seq && tp->tlp_retrans)
		tp->undo_retrans++;
	/* Finally, avoid 0, because undo_retrans==0 means "can undo now": */
	if (!tp->undo_retrans)
		tp->undo_retrans = -1;
}

static bool tcp_is_rack(const struct sock *sk)
@@ -2015,6 +2023,7 @@ void tcp_enter_loss(struct sock *sk)

	tcp_set_ca_state(sk, TCP_CA_Loss);
	tp->high_seq = tp->snd_nxt;
	tp->tlp_high_seq = 0;
	tcp_ecn_queue_cwr(tp);

	/* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous
+41 −4
Original line number Diff line number Diff line
@@ -411,6 +411,39 @@ static void tcp_fastopen_synack_timer(struct sock *sk)
			  TCP_TIMEOUT_INIT << req->num_timeout, TCP_RTO_MAX);
}

static bool tcp_rtx_probe0_timed_out(const struct sock *sk,
				     const struct sk_buff *skb)
{
	const struct inet_connection_sock *icsk = inet_csk(sk);
	u32 user_timeout = READ_ONCE(icsk->icsk_user_timeout);
	const struct tcp_sock *tp = tcp_sk(sk);
	int timeout = TCP_RTO_MAX * 2;
	u32 rtx_delta;
	s32 rcv_delta;

	rtx_delta = (u32)msecs_to_jiffies(tcp_time_stamp(tp) -
			(tp->retrans_stamp ?: tcp_skb_timestamp(skb)));

	if (user_timeout) {
		/* If user application specified a TCP_USER_TIMEOUT,
		 * it does not want win 0 packets to 'reset the timer'
		 * while retransmits are not making progress.
		 */
		if (rtx_delta > user_timeout)
			return true;
		timeout = min_t(u32, timeout, msecs_to_jiffies(user_timeout));
	}

	/* Note: timer interrupt might have been delayed by at least one jiffy,
	 * and tp->rcv_tstamp might very well have been written recently.
	 * rcv_delta can thus be negative.
	 */
	rcv_delta = icsk->icsk_timeout - tp->rcv_tstamp;
	if (rcv_delta <= timeout)
		return false;

	return rtx_delta > timeout;
}

/**
 *  tcp_retransmit_timer() - The TCP retransmit timeout handler
@@ -428,6 +461,7 @@ void tcp_retransmit_timer(struct sock *sk)
	struct tcp_sock *tp = tcp_sk(sk);
	struct net *net = sock_net(sk);
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct sk_buff *skb;

	if (tp->fastopen_rsk) {
		WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
@@ -438,10 +472,13 @@ void tcp_retransmit_timer(struct sock *sk)
		 */
		return;
	}
	if (!tp->packets_out || WARN_ON_ONCE(tcp_rtx_queue_empty(sk)))

	if (!tp->packets_out)
		return;

	tp->tlp_high_seq = 0;
	skb = tcp_rtx_queue_head(sk);
	if (WARN_ON_ONCE(!skb))
		return;

	if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) &&
	    !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) {
@@ -467,12 +504,12 @@ void tcp_retransmit_timer(struct sock *sk)
					    tp->snd_una, tp->snd_nxt);
		}
#endif
		if (tcp_jiffies32 - tp->rcv_tstamp > TCP_RTO_MAX) {
		if (tcp_rtx_probe0_timed_out(sk, skb)) {
			tcp_write_err(sk);
			goto out;
		}
		tcp_enter_loss(sk);
		tcp_retransmit_skb(sk, tcp_rtx_queue_head(sk), 1);
		tcp_retransmit_skb(sk, skb, 1);
		__sk_dst_reset(sk);
		goto out_reset_timer;
	}