[PATCH 2/2] net: socket: implement SO_DESCRIPTION
From: Pascal Bouchareine <hidden>
Date: 2020-08-15 21:56:35
Also in:
lkml, netdev
Subsystem:
generic include/asm header files, networking [general], networking [sockets], the rest · Maintainers:
Arnd Bergmann, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Kuniyuki Iwashima, Willem de Bruijn, Linus Torvalds
This command attaches the zero terminated string in optval to the socket for troubleshooting purposes. The free string is displayed in the process fdinfo file for that fd (/proc/<pid>/fdinfo/<fd>). One intended usage is to allow processes to self-document sockets for netstat and friends to report We ignore optlen and constrain the string to a static max size Signed-off-by: Pascal Bouchareine <redacted> --- include/net/sock.h | 4 ++++ include/uapi/asm-generic/socket.h | 2 ++ net/core/sock.c | 23 +++++++++++++++++++++++ net/socket.c | 5 +++++ 4 files changed, 34 insertions(+)
diff --git a/include/net/sock.h b/include/net/sock.h
index 1183507df95b..6b4fd1383282 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h@@ -342,6 +342,7 @@ struct bpf_sk_storage; * @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME * @sk_txtime_report_errors: set report errors mode for SO_TXTIME * @sk_txtime_unused: unused txtime flags + * @sk_description: user supplied with SO_DESCRIPTION */ struct sock { /*
@@ -519,6 +520,9 @@ struct sock { struct bpf_sk_storage __rcu *sk_bpf_storage; #endif struct rcu_head sk_rcu; + +#define SK_MAX_DESC_SIZE 256 + char *sk_description; }; enum sk_pacing {
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 77f7c1638eb1..fb51c4bb7a12 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h@@ -119,6 +119,8 @@ #define SO_DETACH_REUSEPORT_BPF 68 +#define SO_DESCRIPTION 69 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff --git a/net/core/sock.c b/net/core/sock.c
index 2e5b7870e5d3..2cb44a0e38b7 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c@@ -828,6 +828,24 @@ void sock_set_rcvbuf(struct sock *sk, int val) } EXPORT_SYMBOL(sock_set_rcvbuf); +int sock_set_description(struct sock *sk, char __user *user_desc) +{ + char *old, *desc; + + desc = strndup_user(user_desc, SK_MAX_DESC_SIZE, GFP_KERNEL_ACCOUNT); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + lock_sock(sk); + old = sk->sk_description; + sk->sk_description = desc; + release_sock(sk); + + kfree(old); + + return 0; +} + /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic.
@@ -850,6 +868,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if (optname == SO_BINDTODEVICE) return sock_setbindtodevice(sk, optval, optlen); + if (optname == SO_DESCRIPTION) + return sock_set_description(sk, optval); + if (optlen < sizeof(int)) return -EINVAL;
@@ -1792,6 +1813,8 @@ static void __sk_destruct(struct rcu_head *head) RCU_INIT_POINTER(sk->sk_filter, NULL); } + kfree(sk->sk_description); + sock_disable_timestamp(sk, SK_FLAGS_TIMESTAMP); #ifdef CONFIG_BPF_SYSCALL
diff --git a/net/socket.c b/net/socket.c
index 976426d03f09..4f2c1a7744b0 100644
--- a/net/socket.c
+++ b/net/socket.c@@ -134,6 +134,11 @@ static void sock_show_fdinfo(struct seq_file *m, struct file *f) { struct socket *sock = f->private_data; + lock_sock(sock->sk); + if (sock->sk->sk_description) + seq_printf(m, "desc:\t%s\n", sock->sk->sk_description); + release_sock(sock->sk); + if (sock->ops->show_fdinfo) sock->ops->show_fdinfo(m, sock); }
--
2.25.1