Skip to content

Commit d8e5920

Browse files
authored
Merge pull request #2378 from tempesta-tech/MekhanikEvgenii/fix-2371
Close all sockets when Tempesta FW shutdowned
2 parents a24d83d + 39c65d3 commit d8e5920

File tree

2 files changed

+63
-38
lines changed

2 files changed

+63
-38
lines changed

fw/sock.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,14 @@ ss_do_close(struct sock *sk, int flags)
669669
tcp_set_state(sk, TCP_CLOSE);
670670
tcp_send_active_reset(sk, sk->sk_allocation);
671671
} else if (tcp_close_state(sk)) {
672+
/*
673+
* Set this flag to prevent calling `tcp_done` from
674+
* `tcp_send_fin` if error occurs to prevent double
675+
* free.
676+
*/
677+
sock_set_flag(sk, SOCK_TEMPESTA_IS_CLOSING);
672678
tcp_send_fin(sk);
679+
sock_reset_flag(sk, SOCK_TEMPESTA_IS_CLOSING);
673680
}
674681

675682
adjudge_to_death:
@@ -1496,7 +1503,14 @@ __sk_close_locked(struct sock *sk, int flags)
14961503
static inline void
14971504
ss_do_shutdown(struct sock *sk)
14981505
{
1506+
/*
1507+
* Set this flag to prevent calling `tcp_done` from
1508+
* `tcp_send_fin` if error occurs to prevent double
1509+
* free.
1510+
*/
1511+
sock_set_flag(sk, SOCK_TEMPESTA_IS_CLOSING);
14991512
tcp_shutdown(sk, SEND_SHUTDOWN);
1513+
sock_reset_flag(sk, SOCK_TEMPESTA_IS_CLOSING);
15001514
if (unlikely(sk->sk_state == TCP_CLOSE))
15011515
ss_linkerror(sk, 0);
15021516
else
@@ -1542,7 +1556,7 @@ ss_tx_action(void)
15421556
if (sk->sk_user_data
15431557
&& (SS_CONN_TYPE(sk) & Conn_Closing)
15441558
&& ss_is_closed_force(&sw))
1545-
ss_conn_drop_guard_exit(sk);
1559+
ss_linkerror(sk, SS_F_ABORT);
15461560
/* We've closed the socket on earlier job. */
15471561
bh_unlock_sock(sk);
15481562
goto dead_sock;

linux-5.10.35.patch

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ index 89163ef8c..49ad1ddc9 100644
950950
union {
951951
struct ip_options_rcu __rcu *ireq_opt;
952952
diff --git a/include/net/sock.h b/include/net/sock.h
953-
index 261195598..b277c7efb 100644
953+
index 261195598..f03d8b999 100644
954954
--- a/include/net/sock.h
955955
+++ b/include/net/sock.h
956956
@@ -506,6 +506,30 @@ struct sock {
@@ -984,18 +984,24 @@ index 261195598..b277c7efb 100644
984984
void (*sk_error_report)(struct sock *sk);
985985
int (*sk_backlog_rcv)(struct sock *sk,
986986
struct sk_buff *skb);
987-
@@ -861,6 +885,10 @@ enum sock_flags {
987+
@@ -861,6 +885,16 @@ enum sock_flags {
988988
SOCK_TXTIME,
989989
SOCK_XDP, /* XDP is attached */
990990
SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
991991
+#ifdef CONFIG_SECURITY_TEMPESTA
992992
+ SOCK_TEMPESTA, /* The socket is managed by Tempesta FW */
993-
+ SOCK_TEMPESTA_HAS_DATA /* The socket has data in Tempesta FW write queue */
993+
+ SOCK_TEMPESTA_HAS_DATA, /* The socket has data in Tempesta FW
994+
+ * write queue.
995+
+ */
996+
+ SOCK_TEMPESTA_IS_CLOSING, /* The socket is closing by Tempesta FW
997+
+ * from `ss_do_close`. `tcp_done` should
998+
+ * not be called from the kernel code.
999+
+ */
9941000
+#endif
9951001
};
9961002

9971003
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
998-
@@ -1081,6 +1109,16 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
1004+
@@ -1081,6 +1115,16 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
9991005
__rc; \
10001006
})
10011007

@@ -1012,7 +1018,7 @@ index 261195598..b277c7efb 100644
10121018
int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
10131019
int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
10141020
void sk_stream_wait_close(struct sock *sk, long timeo_p);
1015-
@@ -1915,8 +1953,7 @@ static inline bool sk_rethink_txhash(struct sock *sk)
1021+
@@ -1915,8 +1959,7 @@ static inline bool sk_rethink_txhash(struct sock *sk)
10161022
static inline struct dst_entry *
10171023
__sk_dst_get(struct sock *sk)
10181024
{
@@ -1023,7 +1029,7 @@ index 261195598..b277c7efb 100644
10231029

10241030
static inline struct dst_entry *
10251031
diff --git a/include/net/tcp.h b/include/net/tcp.h
1026-
index 7d66c61d2..440938820 100644
1032+
index 7d66c61d2..f85ea9a2b 100644
10271033
--- a/include/net/tcp.h
10281034
+++ b/include/net/tcp.h
10291035
@@ -307,6 +307,7 @@ bool tcp_check_oom(struct sock *sk, int shift);
@@ -1075,15 +1081,15 @@ index 7d66c61d2..440938820 100644
10751081
+ sk->sk_err = error;
10761082
+ sk->sk_error_report(sk);
10771083
+ tcp_write_queue_purge(sk);
1078-
+
10791084
+ /*
1080-
+ * If this function is called when error occurs during sending
1081-
+ * TCP FIN from `ss_do_close` or `tcp_shutdown`, we should not
1082-
+ * call `tcp_done` just set state to TCP_CLOSE and clear timers
1083-
+ * to prevent extra call of `inet_csk_destroy_sock`.
1085+
+ * SOCK_TEMPESTA_IS_CLOSING is set from `ss_do_close`
1086+
+ * or `ss_do_shutdown` function from Tempesta FW code.
1087+
+ * We should not call `tcp_done` if error occurs during
1088+
+ * one of this function, just set socket state to TCP_CLOSE,
1089+
+ * clear timers and socket write queue. Socket will be
1090+
+ * closed in one of this function.
10841091
+ */
1085-
+ if (unlikely(sk->sk_state == TCP_FIN_WAIT1
1086-
+ || sk->sk_state == TCP_LAST_ACK)) {
1092+
+ if (unlikely(sock_flag(sk, SOCK_TEMPESTA_IS_CLOSING))) {
10871093
+ tcp_set_state(sk, TCP_CLOSE);
10881094
+ tcp_clear_xmit_timers(sk);
10891095
+ } else {
@@ -2544,7 +2550,7 @@ index f0f67b25c..58fbfb071 100644
25442550
return NULL;
25452551
}
25462552
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
2547-
index f99494637..879836861 100644
2553+
index f99494637..042f9e38d 100644
25482554
--- a/net/ipv4/tcp_output.c
25492555
+++ b/net/ipv4/tcp_output.c
25502556
@@ -39,6 +39,9 @@
@@ -2753,7 +2759,7 @@ index f99494637..879836861 100644
27532759

27542760
len -= skb->len;
27552761
}
2756-
@@ -2310,6 +2364,75 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len)
2762+
@@ -2310,6 +2364,76 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len)
27572763
return true;
27582764
}
27592765

@@ -2776,16 +2782,17 @@ index f99494637..879836861 100644
27762782
+ int result;
27772783
+
27782784
+ /*
2779-
+ * If skb has tls type, but sk->sk_write_xmit is equal to zero
2780-
+ * it means that connection was already dropped. In this case
2781-
+ * there should not be any skbs with tls type in socket write
2782-
+ * queue, because we always recalculate sequence numbers of skb
2783-
+ * in `sk_write_xmit`, and if we don't call it skb will have
2784-
+ * incorrect sequence numbers, that leads to unclear warning
2785-
+ * later.
2785+
+ * If skb has tls type, but `sk->sk_write_xmit` is equal to zero
2786+
+ * it means that connection was already dropped. This skb is
2787+
+ * not valid, because we should recalculate sequence numbers of
2788+
+ * for this skb in `sk_write_xmit`, and if we don't call it skb
2789+
+ * will have incorrect sequence numbers. So we should return
2790+
+ * error code here and close socket using `tcp_tfw_handle_error`.
27862791
+ */
2787-
+ if (!skb_tfw_tls_type(skb) || WARN_ON_ONCE(!sk->sk_write_xmit))
2792+
+ if (!skb_tfw_tls_type(skb))
27882793
+ return 0;
2794+
+ else if (!sk->sk_write_xmit)
2795+
+ return -EPIPE;
27892796
+
27902797
+ /* Should be checked early. */
27912798
+ BUG_ON(after(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp)));
@@ -2829,7 +2836,7 @@ index f99494637..879836861 100644
28292836
/* Create a new MTU probe if we are ready.
28302837
* MTU probe is regularly attempting to increase the path MTU by
28312838
* deliberately sending larger packets. This discovers routing
2832-
@@ -2330,6 +2453,9 @@ static int tcp_mtu_probe(struct sock *sk)
2839+
@@ -2330,6 +2454,9 @@ static int tcp_mtu_probe(struct sock *sk)
28332840
int copy, len;
28342841
int mss_now;
28352842
int interval;
@@ -2839,15 +2846,15 @@ index f99494637..879836861 100644
28392846

28402847
/* Not currently probing/verifying,
28412848
* not in recovery,
2842-
@@ -2382,6 +2508,7 @@ static int tcp_mtu_probe(struct sock *sk)
2849+
@@ -2382,6 +2509,7 @@ static int tcp_mtu_probe(struct sock *sk)
28432850
return 0;
28442851
}
28452852

28462853
+ TFW_ADJUST_TLS_OVERHEAD(probe_size);
28472854
if (!tcp_can_coalesce_send_queue_head(sk, probe_size))
28482855
return -1;
28492856

2850-
@@ -2402,6 +2529,10 @@ static int tcp_mtu_probe(struct sock *sk)
2857+
@@ -2402,6 +2530,10 @@ static int tcp_mtu_probe(struct sock *sk)
28512858
nskb->csum = 0;
28522859
nskb->ip_summed = CHECKSUM_PARTIAL;
28532860

@@ -2858,13 +2865,17 @@ index f99494637..879836861 100644
28582865
tcp_insert_write_queue_before(nskb, skb, sk);
28592866
tcp_highest_sack_replace(sk, skb, nskb);
28602867

2861-
@@ -2440,6 +2571,20 @@ static int tcp_mtu_probe(struct sock *sk)
2868+
@@ -2440,6 +2572,24 @@ static int tcp_mtu_probe(struct sock *sk)
28622869
}
28632870
tcp_init_tso_segs(nskb, nskb->len);
28642871

28652872
+#ifdef CONFIG_SECURITY_TEMPESTA
2866-
+ if (!skb_tfw_tls_type(nskb) || WARN_ON_ONCE(!sk->sk_write_xmit))
2873+
+ if (!skb_tfw_tls_type(nskb))
28672874
+ goto transmit;
2875+
+ else if (!sk->sk_write_xmit) {
2876+
+ tcp_tfw_handle_error(sk, -EPIPE);
2877+
+ return 0;
2878+
+ }
28682879
+
28692880
+ result = sk->sk_write_xmit(sk, nskb, probe_size, probe_size);
28702881
+ if (unlikely(result)) {
@@ -2879,7 +2890,7 @@ index f99494637..879836861 100644
28792890
/* We're ready to send. If this fails, the probe will
28802891
* be resegmented into mss-sized pieces by tcp_write_xmit().
28812892
*/
2882-
@@ -2666,7 +2811,17 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
2893+
@@ -2666,7 +2816,17 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
28832894
cwnd_quota,
28842895
max_segs),
28852896
nonagle);
@@ -2898,7 +2909,7 @@ index f99494637..879836861 100644
28982909
if (skb->len > limit &&
28992910
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
29002911
break;
2901-
@@ -2681,7 +2836,13 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
2912+
@@ -2681,7 +2841,13 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
29022913
*/
29032914
if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq)
29042915
break;
@@ -2913,15 +2924,15 @@ index f99494637..879836861 100644
29132924
if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
29142925
break;
29152926

2916-
@@ -2866,6 +3027,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
2927+
@@ -2866,6 +3032,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
29172928
sk_gfp_mask(sk, GFP_ATOMIC)))
29182929
tcp_check_probe_timer(sk);
29192930
}
29202931
+EXPORT_SYMBOL(__tcp_push_pending_frames);
29212932

29222933
/* Send _single_ skb sitting at the send head. This function requires
29232934
* true push pending frames to setup probe timer etc.
2924-
@@ -3183,7 +3345,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
2935+
@@ -3183,7 +3350,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
29252936
cur_mss, GFP_ATOMIC))
29262937
return -ENOMEM; /* We'll try again later. */
29272938
} else {
@@ -2930,31 +2941,31 @@ index f99494637..879836861 100644
29302941
return -ENOMEM;
29312942

29322943
diff = tcp_skb_pcount(skb);
2933-
@@ -3374,6 +3536,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size)
2944+
@@ -3374,6 +3541,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size)
29342945
if (mem_cgroup_sockets_enabled && sk->sk_memcg)
29352946
mem_cgroup_charge_skmem(sk->sk_memcg, amt);
29362947
}
29372948
+EXPORT_SYMBOL(sk_forced_mem_schedule);
29382949

29392950
/* Send a FIN. The caller locks the socket for us.
29402951
* We should try to send a FIN packet really hard, but eventually give up.
2941-
@@ -3421,6 +3584,7 @@ void tcp_send_fin(struct sock *sk)
2952+
@@ -3421,6 +3589,7 @@ void tcp_send_fin(struct sock *sk)
29422953
}
29432954
__tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF);
29442955
}
29452956
+EXPORT_SYMBOL(tcp_send_fin);
29462957

29472958
/* We get here when a process closes a file descriptor (either due to
29482959
* an explicit close() or as a byproduct of exit()'ing) and there
2949-
@@ -3454,6 +3618,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
2960+
@@ -3454,6 +3623,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
29502961
*/
29512962
trace_tcp_send_reset(sk, NULL);
29522963
}
29532964
+EXPORT_SYMBOL(tcp_send_active_reset);
29542965

29552966
/* Send a crossed SYN-ACK during socket establishment.
29562967
* WARNING: This routine must only be called when we have already sent
2957-
@@ -4044,6 +4209,17 @@ int tcp_write_wakeup(struct sock *sk, int mib)
2968+
@@ -4044,6 +4214,17 @@ int tcp_write_wakeup(struct sock *sk, int mib)
29582969
if (seg_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq ||
29592970
skb->len > mss) {
29602971
seg_size = min(seg_size, mss);
@@ -2972,7 +2983,7 @@ index f99494637..879836861 100644
29722983
TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
29732984
if (tcp_fragment(sk, TCP_FRAG_IN_WRITE_QUEUE,
29742985
skb, seg_size, mss, GFP_ATOMIC))
2975-
@@ -4052,6 +4228,15 @@ int tcp_write_wakeup(struct sock *sk, int mib)
2986+
@@ -4052,6 +4233,15 @@ int tcp_write_wakeup(struct sock *sk, int mib)
29762987
tcp_set_skb_tso_segs(skb, mss);
29772988

29782989
TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;

0 commit comments

Comments
 (0)