Loading include/net/tcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,8 @@ void tcp_set_state(struct sock *sk, int state); void tcp_done(struct sock *sk); int tcp_abort(struct sock *sk, int err); static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) { rx_opt->dsack = 0; Loading net/ipv4/Kconfig +13 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,19 @@ config INET_UDP_DIAG Support for UDP socket monitoring interface used by the ss tool. If unsure, say Y. config INET_DIAG_DESTROY bool "INET: allow privileged process to administratively close sockets" depends on INET_DIAG default n ---help--- Provides a SOCK_DESTROY operation that allows privileged processes (e.g., a connection manager or a network administration tool such as ss) to close sockets opened by other processes. Closing a socket in this way interrupts any blocking read/write/connect operations on the socket and causes future socket calls to behave as if the socket had been disconnected. If unsure, say N. menuconfig TCP_CONG_ADVANCED bool "TCP: advanced congestion control" ---help--- Loading net/ipv4/tcp.c +32 −0 Original line number Diff line number Diff line Loading @@ -3057,6 +3057,38 @@ void tcp_done(struct sock *sk) } EXPORT_SYMBOL_GPL(tcp_done); int tcp_abort(struct sock *sk, int err) { if (!sk_fullsock(sk)) { sock_gen_put(sk); return -EOPNOTSUPP; } /* Don't race with userspace socket closes such as tcp_close. */ lock_sock(sk); /* Don't race with BH socket closes such as inet_csk_listen_stop. */ local_bh_disable(); bh_lock_sock(sk); if (!sock_flag(sk, SOCK_DEAD)) { sk->sk_err = err; /* This barrier is coupled with smp_rmb() in tcp_poll() */ smp_wmb(); sk->sk_error_report(sk); if (tcp_need_reset(sk->sk_state)) tcp_send_active_reset(sk, GFP_ATOMIC); tcp_done(sk); } bh_unlock_sock(sk); local_bh_enable(); release_sock(sk); sock_put(sk); return 0; } EXPORT_SYMBOL_GPL(tcp_abort); extern struct tcp_congestion_ops tcp_reno; static __initdata unsigned long thash_entries; Loading net/ipv4/tcp_diag.c +19 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ */ #include <linux/module.h> #include <linux/net.h> #include <linux/sock_diag.h> #include <linux/inet_diag.h> #include <linux/tcp.h> Loading Loading @@ -45,11 +47,28 @@ static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); } #ifdef CONFIG_INET_DIAG_DESTROY static int tcp_diag_destroy(struct sk_buff *in_skb, struct inet_diag_req_v2 *req) { struct net *net = sock_net(in_skb->sk); struct sock *sk = inet_diag_find_one_icsk(net, &tcp_hashinfo, req); if (IS_ERR(sk)) return PTR_ERR(sk); return sock_diag_destroy(sk, ECONNABORTED); } #endif static const struct inet_diag_handler tcp_diag_handler = { .dump = tcp_diag_dump, .dump_one = tcp_diag_dump_one, .idiag_get_info = tcp_diag_get_info, .idiag_type = IPPROTO_TCP, #ifdef CONFIG_INET_DIAG_DESTROY .destroy = tcp_diag_destroy, #endif }; static int __init tcp_diag_init(void) Loading net/ipv4/tcp_ipv4.c +1 −0 Original line number Diff line number Diff line Loading @@ -2428,6 +2428,7 @@ struct proto tcp_prot = { .destroy_cgroup = tcp_destroy_cgroup, .proto_cgroup = tcp_proto_cgroup, #endif .diag_destroy = tcp_abort, }; EXPORT_SYMBOL(tcp_prot); Loading Loading
include/net/tcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,8 @@ void tcp_set_state(struct sock *sk, int state); void tcp_done(struct sock *sk); int tcp_abort(struct sock *sk, int err); static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) { rx_opt->dsack = 0; Loading
net/ipv4/Kconfig +13 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,19 @@ config INET_UDP_DIAG Support for UDP socket monitoring interface used by the ss tool. If unsure, say Y. config INET_DIAG_DESTROY bool "INET: allow privileged process to administratively close sockets" depends on INET_DIAG default n ---help--- Provides a SOCK_DESTROY operation that allows privileged processes (e.g., a connection manager or a network administration tool such as ss) to close sockets opened by other processes. Closing a socket in this way interrupts any blocking read/write/connect operations on the socket and causes future socket calls to behave as if the socket had been disconnected. If unsure, say N. menuconfig TCP_CONG_ADVANCED bool "TCP: advanced congestion control" ---help--- Loading
net/ipv4/tcp.c +32 −0 Original line number Diff line number Diff line Loading @@ -3057,6 +3057,38 @@ void tcp_done(struct sock *sk) } EXPORT_SYMBOL_GPL(tcp_done); int tcp_abort(struct sock *sk, int err) { if (!sk_fullsock(sk)) { sock_gen_put(sk); return -EOPNOTSUPP; } /* Don't race with userspace socket closes such as tcp_close. */ lock_sock(sk); /* Don't race with BH socket closes such as inet_csk_listen_stop. */ local_bh_disable(); bh_lock_sock(sk); if (!sock_flag(sk, SOCK_DEAD)) { sk->sk_err = err; /* This barrier is coupled with smp_rmb() in tcp_poll() */ smp_wmb(); sk->sk_error_report(sk); if (tcp_need_reset(sk->sk_state)) tcp_send_active_reset(sk, GFP_ATOMIC); tcp_done(sk); } bh_unlock_sock(sk); local_bh_enable(); release_sock(sk); sock_put(sk); return 0; } EXPORT_SYMBOL_GPL(tcp_abort); extern struct tcp_congestion_ops tcp_reno; static __initdata unsigned long thash_entries; Loading
net/ipv4/tcp_diag.c +19 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ */ #include <linux/module.h> #include <linux/net.h> #include <linux/sock_diag.h> #include <linux/inet_diag.h> #include <linux/tcp.h> Loading Loading @@ -45,11 +47,28 @@ static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); } #ifdef CONFIG_INET_DIAG_DESTROY static int tcp_diag_destroy(struct sk_buff *in_skb, struct inet_diag_req_v2 *req) { struct net *net = sock_net(in_skb->sk); struct sock *sk = inet_diag_find_one_icsk(net, &tcp_hashinfo, req); if (IS_ERR(sk)) return PTR_ERR(sk); return sock_diag_destroy(sk, ECONNABORTED); } #endif static const struct inet_diag_handler tcp_diag_handler = { .dump = tcp_diag_dump, .dump_one = tcp_diag_dump_one, .idiag_get_info = tcp_diag_get_info, .idiag_type = IPPROTO_TCP, #ifdef CONFIG_INET_DIAG_DESTROY .destroy = tcp_diag_destroy, #endif }; static int __init tcp_diag_init(void) Loading
net/ipv4/tcp_ipv4.c +1 −0 Original line number Diff line number Diff line Loading @@ -2428,6 +2428,7 @@ struct proto tcp_prot = { .destroy_cgroup = tcp_destroy_cgroup, .proto_cgroup = tcp_proto_cgroup, #endif .diag_destroy = tcp_abort, }; EXPORT_SYMBOL(tcp_prot); Loading