lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180426175805.2590-1-jhs@emojatatu.com>
Date:   Thu, 26 Apr 2018 13:58:05 -0400
From:   Jamal Hadi Salim <jhs@...atatu.com>
To:     davem@...emloft.net
Cc:     kraig@...gle.com, netdev@...r.kernel.org, eric.dumazet@...il.com,
        kernel@...atatu.com, Jamal Hadi Salim <hadi@...atatu.com>,
        Jamal Hadi Salim <jhs@...atatu.com>
Subject: [PATCH net-next 1/1] inet_diag: fetch cong algo info when socket is destroyed

From: Jamal Hadi Salim <hadi@...atatu.com>

When a user dumps an existing established tcp socket state
via inet diag, it is possible to retrieve the congestion control
details.
When an the sock is destroyed, the generated event has all the
details available in the dump sans congestion control info.
This patch fixes it.

Signed-off-by: Jamal Hadi Salim <jhs@...atatu.com>
---
 net/core/sock_diag.c |  3 +++
 net/ipv4/inet_diag.c | 48 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index c37b5be7c5e4..0bf64dd70aee 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -7,6 +7,7 @@
 #include <net/net_namespace.h>
 #include <linux/module.h>
 #include <net/sock.h>
+#include <net/tcp.h>
 #include <linux/kernel.h>
 #include <linux/tcp.h>
 #include <linux/workqueue.h>
@@ -112,6 +113,8 @@ static size_t sock_diag_nlmsg_size(void)
 {
 	return NLMSG_ALIGN(sizeof(struct inet_diag_msg)
 	       + nla_total_size(sizeof(u8)) /* INET_DIAG_PROTOCOL */
+	       + nla_total_size(TCP_CA_NAME_MAX) /* INET_DIAG_CONG */
+	       + nla_total_size(sizeof(union tcp_cc_info))
 	       + nla_total_size_64bit(sizeof(struct tcp_info))); /* INET_DIAG_INFO */
 }
 
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 4e5bc4b2f14e..9722f31cc9c5 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -159,6 +159,35 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(inet_diag_msg_attrs_fill);
 
+static int inet_csk_cong_fill(struct sock *sk, struct sk_buff *skb, int ext)
+{
+	struct inet_connection_sock *icsk = inet_csk(sk);
+	const struct tcp_congestion_ops *ca_ops;
+	union tcp_cc_info info;
+	int attr, err = 0;
+	size_t sz = 0;
+
+	rcu_read_lock();
+	ca_ops = READ_ONCE(icsk->icsk_ca_ops);
+	if (ca_ops) {
+		if (ca_ops->get_info)
+			sz = ca_ops->get_info(sk, ext, &attr, &info);
+		if (ext & (1 << (INET_DIAG_CONG - 1))) {
+			err = nla_put_string(skb, INET_DIAG_CONG, ca_ops->name);
+			if (err < 0) {
+				rcu_read_unlock();
+				return err;
+			}
+		}
+	}
+	rcu_read_unlock();
+
+	if (sz)
+		err = nla_put(skb, attr, sz, &info);
+
+	return err;
+}
+
 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 		      struct user_namespace *user_ns,
@@ -274,16 +303,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 			goto errout;
 
 	if (sk->sk_state < TCP_TIME_WAIT) {
-		union tcp_cc_info info;
-		size_t sz = 0;
-		int attr;
-
-		rcu_read_lock();
-		ca_ops = READ_ONCE(icsk->icsk_ca_ops);
-		if (ca_ops && ca_ops->get_info)
-			sz = ca_ops->get_info(sk, ext, &attr, &info);
-		rcu_read_unlock();
-		if (sz && nla_put(skb, attr, sz, &info) < 0)
+		if (inet_csk_cong_fill(sk, skb, ext))
 			goto errout;
 	}
 
@@ -1215,6 +1235,14 @@ int inet_diag_handler_get_info(struct sk_buff *skb, struct sock *sk)
 	if (attr)
 		info = nla_data(attr);
 
+#define EXT_MASK (1 << (INET_DIAG_VEGASINFO - 1) | 1 << (INET_DIAG_CONG - 1))
+	err = inet_csk_cong_fill(sk, skb, EXT_MASK);
+	if (err) {
+		inet_diag_unlock_handler(handler);
+		nlmsg_cancel(skb, nlh);
+		return err;
+	}
+
 	handler->idiag_get_info(sk, r, info);
 	inet_diag_unlock_handler(handler);
 
-- 
2.11.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ