[PATCH v5 4/4] net: diag: Support destroying TCP sockets.

2015-12-14 Thread Lorenzo Colitti
This implements SOCK_DESTROY for TCP sockets. It causes all
blocking calls on the socket to fail fast with ECONNABORTED and
causes a protocol close of the socket. It informs the other end
of the connection by sending a RST, i.e., initiating a TCP ABORT
as per RFC 793. ECONNABORTED was chosen for consistency with
FreeBSD.

Signed-off-by: Lorenzo Colitti 
---
 include/net/tcp.h   |  4 
 net/ipv4/Kconfig| 13 +
 net/ipv4/tcp.c  | 34 ++
 net/ipv4/tcp_diag.c | 19 +++
 net/ipv4/tcp_ipv4.c |  3 +++
 net/ipv6/tcp_ipv6.c |  3 +++
 6 files changed, 76 insertions(+)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index f80e74c..505cef5 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1170,6 +1170,10 @@ void tcp_set_state(struct sock *sk, int state);
 
 void tcp_done(struct sock *sk);
 
+#if CONFIG_INET_DIAG_DESTROY
+int tcp_abort(struct sock *sk);
+#endif
+
 static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
 {
rx_opt->dsack = 0;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 416dfa0..31c4496 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -436,6 +436,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 && (IPV6 || IPV6=n)
+   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/writes/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---
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c82cca1..fc5068d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3080,6 +3080,40 @@ void tcp_done(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(tcp_done);
 
+#ifdef CONFIG_INET_DIAG_DESTROY
+int tcp_abort(struct sock *sk)
+{
+   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 = ECONNABORTED;
+   /* 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);
+#endif
+
 extern struct tcp_congestion_ops tcp_reno;
 
 static __initdata unsigned long thash_entries;
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index b316040..8d435f17 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -10,6 +10,8 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 
 #include 
@@ -46,12 +48,29 @@ static int tcp_diag_dump_one(struct sk_buff *in_skb, const 
struct nlmsghdr *nlh,
return inet_diag_dump_one_icsk(_hashinfo, in_skb, nlh, req);
 }
 
+#ifdef CONFIG_INET_DIAG_DESTROY
+static int tcp_diag_destroy(struct sk_buff *in_skb,
+   const struct inet_diag_req_v2 *req)
+{
+   struct net *net = sock_net(in_skb->sk);
+   struct sock *sk = inet_diag_find_one_icsk(net, _hashinfo, req);
+
+   if (IS_ERR(sk))
+   return PTR_ERR(sk);
+
+   return sock_diag_destroy(sk);
+}
+#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,
.idiag_info_size = sizeof(struct tcp_info),
+#ifdef CONFIG_INET_DIAG_DESTROY
+   .destroy = tcp_diag_destroy,
+#endif
 };
 
 static int __init tcp_diag_init(void)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index db00343..5e28bf1 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2342,6 +2342,9 @@ struct proto tcp_prot = {
.destroy_cgroup = tcp_destroy_cgroup,
.proto_cgroup   = tcp_proto_cgroup,
 #endif
+#ifdef CONFIG_INET_DIAG_DESTROY
+   .diag_destroy   = tcp_abort,
+#endif
 };
 EXPORT_SYMBOL(tcp_prot);
 
diff --git a/net/ipv6/tcp_ipv6.c 

Re: [PATCH v5 4/4] net: diag: Support destroying TCP sockets.

2015-12-14 Thread David Miller
From: Lorenzo Colitti 
Date: Tue, 15 Dec 2015 02:29:57 +0900

> +#if CONFIG_INET_DIAG_DESTROY

Config symbols are to be checked with "ifdef" not "if".

> +config INET_DIAG_DESTROY
> + bool "INET: allow privileged process to administratively close sockets"
> + depends on INET_DIAG && (IPV6 || IPV6=n)
> + default n

As Eric Dumazet stated, this "(X || X=n)" construct only makes sense for
tristate Kconfig entries.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 4/4] net: diag: Support destroying TCP sockets.

2015-12-14 Thread kbuild test robot
Hi Lorenzo,

[auto build test WARNING on net/master]
[also build test WARNING on v4.4-rc5]
[cannot apply to next-20151214]

url:
https://github.com/0day-ci/linux/commits/Lorenzo-Colitti/net-diag-Add-the-ability-to-destroy-a-socket/20151215-013254
config: x86_64-randconfig-x013-12141150 (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from net/ipv4/route.c:103:0:
>> include/net/tcp.h:1173:5: warning: "CONFIG_INET_DIAG_DESTROY" is not defined 
>> [-Wundef]
#if CONFIG_INET_DIAG_DESTROY
^
   In file included from net/ipv4/route.c:103:0:
>> include/net/tcp.h:1173:5: warning: "CONFIG_INET_DIAG_DESTROY" is not defined 
>> [-Wundef]
#if CONFIG_INET_DIAG_DESTROY
^
--
   In file included from net/ipv4/ip_forward.c:31:0:
>> include/net/tcp.h:1173:5: warning: "CONFIG_INET_DIAG_DESTROY" is not defined 
>> [-Wundef]
#if CONFIG_INET_DIAG_DESTROY
^

vim +/CONFIG_INET_DIAG_DESTROY +1173 include/net/tcp.h

  1157  
  1158  bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
  1159  
  1160  #undef STATE_TRACE
  1161  
  1162  #ifdef STATE_TRACE
  1163  static const char *statename[]={
  1164  "Unused","Established","Syn Sent","Syn Recv",
  1165  "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
  1166  "Close Wait","Last ACK","Listen","Closing"
  1167  };
  1168  #endif
  1169  void tcp_set_state(struct sock *sk, int state);
  1170  
  1171  void tcp_done(struct sock *sk);
  1172  
> 1173  #if CONFIG_INET_DIAG_DESTROY
  1174  int tcp_abort(struct sock *sk);
  1175  #endif
  1176  
  1177  static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
  1178  {
  1179  rx_opt->dsack = 0;
  1180  rx_opt->num_sacks = 0;
  1181  }

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: Binary data


Re: [PATCH v5 4/4] net: diag: Support destroying TCP sockets.

2015-12-14 Thread Tom Herbert
On Mon, Dec 14, 2015 at 9:29 AM, Lorenzo Colitti  wrote:
> This implements SOCK_DESTROY for TCP sockets. It causes all
> blocking calls on the socket to fail fast with ECONNABORTED and
> causes a protocol close of the socket. It informs the other end
> of the connection by sending a RST, i.e., initiating a TCP ABORT
> as per RFC 793. ECONNABORTED was chosen for consistency with
> FreeBSD.
>
> Signed-off-by: Lorenzo Colitti 
> ---
>  include/net/tcp.h   |  4 
>  net/ipv4/Kconfig| 13 +
>  net/ipv4/tcp.c  | 34 ++
>  net/ipv4/tcp_diag.c | 19 +++
>  net/ipv4/tcp_ipv4.c |  3 +++
>  net/ipv6/tcp_ipv6.c |  3 +++
>  6 files changed, 76 insertions(+)
>
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index f80e74c..505cef5 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -1170,6 +1170,10 @@ void tcp_set_state(struct sock *sk, int state);
>
>  void tcp_done(struct sock *sk);
>
> +#if CONFIG_INET_DIAG_DESTROY
> +int tcp_abort(struct sock *sk);
> +#endif
> +
>  static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
>  {
> rx_opt->dsack = 0;
> diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
> index 416dfa0..31c4496 100644
> --- a/net/ipv4/Kconfig
> +++ b/net/ipv4/Kconfig
> @@ -436,6 +436,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 && (IPV6 || IPV6=n)
> +   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/writes/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---
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index c82cca1..fc5068d 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -3080,6 +3080,40 @@ void tcp_done(struct sock *sk)
>  }
>  EXPORT_SYMBOL_GPL(tcp_done);
>
> +#ifdef CONFIG_INET_DIAG_DESTROY

This is a general use function it should not be under a CONFIG.

> +int tcp_abort(struct sock *sk)

Please add an err argument for setting sk->err. A value of zero could
mean to use the default value (ECONNABORTED).

> +{
> +   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 = ECONNABORTED;
> +   /* 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);
> +#endif
> +
>  extern struct tcp_congestion_ops tcp_reno;
>
>  static __initdata unsigned long thash_entries;
> diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
> index b316040..8d435f17 100644
> --- a/net/ipv4/tcp_diag.c
> +++ b/net/ipv4/tcp_diag.c
> @@ -10,6 +10,8 @@
>   */
>
>  #include 
> +#include 
> +#include 
>  #include 
>
>  #include 
> @@ -46,12 +48,29 @@ static int tcp_diag_dump_one(struct sk_buff *in_skb, 
> const struct nlmsghdr *nlh,
> return inet_diag_dump_one_icsk(_hashinfo, in_skb, nlh, req);
>  }
>
> +#ifdef CONFIG_INET_DIAG_DESTROY
> +static int tcp_diag_destroy(struct sk_buff *in_skb,
> +   const struct inet_diag_req_v2 *req)
> +{
> +   struct net *net = sock_net(in_skb->sk);
> +   struct sock *sk = inet_diag_find_one_icsk(net, _hashinfo, req);
> +
> +   if (IS_ERR(sk))
> +   return PTR_ERR(sk);
> +
> +   return sock_diag_destroy(sk);
> +}
> +#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,
> .idiag_info_size = sizeof(struct tcp_info),
> +#ifdef CONFIG_INET_DIAG_DESTROY
> +   .destroy = 

Re: [PATCH v5 4/4] net: diag: Support destroying TCP sockets.

2015-12-14 Thread Eric Dumazet
On Tue, 2015-12-15 at 02:29 +0900, Lorenzo Colitti wrote:

> +config INET_DIAG_DESTROY
> + bool "INET: allow privileged process to administratively close sockets"
> + depends on INET_DIAG && (IPV6 || IPV6=n)
> + default n

I can see the effect of (IPV6 || IPv6=n) for a tristate,
but what is the intent for a bool ?

It seems INET_DIAG_DESTROY can be selected regardless of IPV6 being off,
on, or a module ?



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html