From b410dc74f80451143200ea5e7fbb3faca9b36c42 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 3 Feb 2022 19:07:33 +0100 Subject: [PATCH] 4.19-stable patches added patches: tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch --- queue-4.19/series | 1 + ...socket-leaks-in-internal-pacing-mode.patch | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 queue-4.19/tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch diff --git a/queue-4.19/series b/queue-4.19/series index dc2ea36fc40..f035102131d 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -45,3 +45,4 @@ ipv4-raw-lock-the-socket-in-raw_bind.patch ipv4-tcp-send-zero-ipid-in-synack-messages.patch netfilter-nat-remove-l4-protocol-port-rovers.patch netfilter-nat-limit-port-clash-resolution-attempts.patch +tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch diff --git a/queue-4.19/tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch b/queue-4.19/tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch new file mode 100644 index 00000000000..9938a828b81 --- /dev/null +++ b/queue-4.19/tcp-fix-possible-socket-leaks-in-internal-pacing-mode.patch @@ -0,0 +1,104 @@ +From eric.dumazet@gmail.com Thu Feb 3 18:59:23 2022 +From: Eric Dumazet +Date: Mon, 31 Jan 2022 10:26:03 -0800 +Subject: tcp: fix possible socket leaks in internal pacing mode +To: "David S . Miller" , Jakub Kicinski +Cc: netdev , Eric Dumazet , Eric Dumazet , Jason Xing , Zhang Changzhong , liweishi , Shujin Li , Neal Cardwell , Greg Kroah-Hartman +Message-ID: <20220131182603.3804056-1-eric.dumazet@gmail.com> + + +From: Eric Dumazet + +This patch is addressing an issue in stable linux-4.19 only. + +In linux-4.20, TCP stack adopted EDT (Earliest Departure +Time) model and this issue was incidentally fixed. + +Issue at hand was an extra sock_hold() from tcp_internal_pacing() +in paths not using tcp_xmit_retransmit_queue() + +Jason Xing reported this leak and provided a patch stopping +the extra sock_hold() to happen. + +This patch is more complete and makes sure to avoid +unnecessary extra delays, by reprogramming the high +resolution timer. + +Fixes: 73a6bab5aa2a ("tcp: switch pacing timer to softirq based hrtimer") +Reference: https://lore.kernel.org/all/CANn89i+7-wE4xr5D9DpH+N-xkL1SB8oVghCKgz+CT5eG1ODQhA@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reported-by: Jason Xing +Reported-by: Zhang Changzhong +Cc: liweishi +Cc: Shujin Li +Cc: Neal Cardwell +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_output.c | 31 +++++++++++++++++++++++-------- + 1 file changed, 23 insertions(+), 8 deletions(-) + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -968,6 +968,8 @@ enum hrtimer_restart tcp_pace_kick(struc + + static void tcp_internal_pacing(struct sock *sk, const struct sk_buff *skb) + { ++ struct tcp_sock *tp = tcp_sk(sk); ++ ktime_t expire, now; + u64 len_ns; + u32 rate; + +@@ -979,12 +981,28 @@ static void tcp_internal_pacing(struct s + + len_ns = (u64)skb->len * NSEC_PER_SEC; + do_div(len_ns, rate); +- hrtimer_start(&tcp_sk(sk)->pacing_timer, +- ktime_add_ns(ktime_get(), len_ns), ++ now = ktime_get(); ++ /* If hrtimer is already armed, then our caller has not ++ * used tcp_pacing_check(). ++ */ ++ if (unlikely(hrtimer_is_queued(&tp->pacing_timer))) { ++ expire = hrtimer_get_softexpires(&tp->pacing_timer); ++ if (ktime_after(expire, now)) ++ now = expire; ++ if (hrtimer_try_to_cancel(&tp->pacing_timer) == 1) ++ __sock_put(sk); ++ } ++ hrtimer_start(&tp->pacing_timer, ktime_add_ns(now, len_ns), + HRTIMER_MODE_ABS_PINNED_SOFT); + sock_hold(sk); + } + ++static bool tcp_pacing_check(const struct sock *sk) ++{ ++ return tcp_needs_internal_pacing(sk) && ++ hrtimer_is_queued(&tcp_sk(sk)->pacing_timer); ++} ++ + static void tcp_update_skb_after_send(struct tcp_sock *tp, struct sk_buff *skb) + { + skb->skb_mstamp = tp->tcp_mstamp; +@@ -2121,6 +2139,9 @@ static int tcp_mtu_probe(struct sock *sk + if (!tcp_can_coalesce_send_queue_head(sk, probe_size)) + return -1; + ++ if (tcp_pacing_check(sk)) ++ return -1; ++ + /* We're allowed to probe. Build it now. */ + nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); + if (!nskb) +@@ -2194,12 +2215,6 @@ static int tcp_mtu_probe(struct sock *sk + return -1; + } + +-static bool tcp_pacing_check(const struct sock *sk) +-{ +- return tcp_needs_internal_pacing(sk) && +- hrtimer_is_queued(&tcp_sk(sk)->pacing_timer); +-} +- + /* TCP Small Queues : + * Control number of packets in qdisc/devices to two packets / or ~1 ms. + * (These limits are doubled for retransmits) -- 2.47.3