Merge branch 'tcp-ulp-diag-expose-more-to-non-net-admin-users'

Matthieu Baerts says:

====================
tcp: ulp: diag: expose more to non net admin users

Since its introduction in commit 61723b3932 ("tcp: ulp: add functions
to dump ulp-specific information"), the ULP diag info have been exported
only to users with CAP_NET_ADMIN capability.

Not everything is sensitive, and some info can be exported to all users
in order to ease the debugging from the userspace side without requiring
additional capabilities.

First, the ULP name can be easily exported. Then more depending on each
layer:

 - On kTLS side, it looks like everything can be exported to all users:
   version, cipher type, tx/rx user config type, plus some flags.

 - On MPTCP side, everything but the sequence numbers are exported to
   all non net admin users, similar to TCP.
====================

Link: https://patch.msgid.link/20250306-net-next-tcp-ulp-diag-net-admin-v1-0-06afdd860fc9@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-03-07 19:39:57 -08:00
commit 530581047d
4 changed files with 40 additions and 31 deletions

View File

@ -2598,8 +2598,8 @@ struct tcp_ulp_ops {
/* cleanup ulp */
void (*release)(struct sock *sk);
/* diagnostic */
int (*get_info)(struct sock *sk, struct sk_buff *skb);
size_t (*get_info_size)(const struct sock *sk);
int (*get_info)(struct sock *sk, struct sk_buff *skb, bool net_admin);
size_t (*get_info_size)(const struct sock *sk, bool net_admin);
/* clone ulp */
void (*clone)(const struct request_sock *req, struct sock *newsk,
const gfp_t priority);

View File

@ -83,7 +83,7 @@ static int tcp_diag_put_md5sig(struct sk_buff *skb,
#endif
static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk,
const struct tcp_ulp_ops *ulp_ops)
const struct tcp_ulp_ops *ulp_ops, bool net_admin)
{
struct nlattr *nest;
int err;
@ -97,7 +97,7 @@ static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk,
goto nla_failure;
if (ulp_ops->get_info)
err = ulp_ops->get_info(sk, skb);
err = ulp_ops->get_info(sk, skb, net_admin);
if (err)
goto nla_failure;
@ -113,6 +113,7 @@ static int tcp_diag_get_aux(struct sock *sk, bool net_admin,
struct sk_buff *skb)
{
struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_ulp_ops *ulp_ops;
int err = 0;
#ifdef CONFIG_TCP_MD5SIG
@ -129,15 +130,13 @@ static int tcp_diag_get_aux(struct sock *sk, bool net_admin,
}
#endif
if (net_admin) {
const struct tcp_ulp_ops *ulp_ops;
ulp_ops = icsk->icsk_ulp_ops;
if (ulp_ops)
err = tcp_diag_put_ulp(skb, sk, ulp_ops);
if (err)
ulp_ops = icsk->icsk_ulp_ops;
if (ulp_ops) {
err = tcp_diag_put_ulp(skb, sk, ulp_ops, net_admin);
if (err < 0)
return err;
}
return 0;
}
@ -164,7 +163,7 @@ static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin)
}
#endif
if (net_admin && sk_fullsock(sk)) {
if (sk_fullsock(sk)) {
const struct tcp_ulp_ops *ulp_ops;
ulp_ops = icsk->icsk_ulp_ops;
@ -172,7 +171,7 @@ static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin)
size += nla_total_size(0) +
nla_total_size(TCP_ULP_NAME_MAX);
if (ulp_ops->get_info_size)
size += ulp_ops->get_info_size(sk);
size += ulp_ops->get_info_size(sk, net_admin);
}
}
return size;

View File

@ -12,7 +12,7 @@
#include <net/netlink.h>
#include "protocol.h"
static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
static int subflow_get_info(struct sock *sk, struct sk_buff *skb, bool net_admin)
{
struct mptcp_subflow_context *sf;
struct nlattr *start;
@ -56,15 +56,6 @@ static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
if (nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_REM, sf->remote_token) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_LOC, sf->token) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
sf->rel_write_seq) ||
nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq,
MPTCP_SUBFLOW_ATTR_PAD) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
sf->map_subflow_seq) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) ||
nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
sf->map_data_len) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) ||
nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) ||
nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, subflow_get_local_id(sf))) {
@ -72,6 +63,21 @@ static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
goto nla_failure;
}
/* Only export seq related counters to user with CAP_NET_ADMIN */
if (net_admin &&
(nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
sf->rel_write_seq) ||
nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq,
MPTCP_SUBFLOW_ATTR_PAD) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
sf->map_subflow_seq) ||
nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) ||
nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
sf->map_data_len))) {
err = -EMSGSIZE;
goto nla_failure;
}
rcu_read_unlock();
unlock_sock_fast(sk, slow);
nla_nest_end(skb, start);
@ -84,22 +90,26 @@ static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
return err;
}
static size_t subflow_get_info_size(const struct sock *sk)
static size_t subflow_get_info_size(const struct sock *sk, bool net_admin)
{
size_t size = 0;
size += nla_total_size(0) + /* INET_ULP_INFO_MPTCP */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_REM */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */
nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_LOC */
0;
if (net_admin)
size += nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
0;
return size;
}

View File

@ -1057,7 +1057,7 @@ static u16 tls_user_config(struct tls_context *ctx, bool tx)
return 0;
}
static int tls_get_info(struct sock *sk, struct sk_buff *skb)
static int tls_get_info(struct sock *sk, struct sk_buff *skb, bool net_admin)
{
u16 version, cipher_type;
struct tls_context *ctx;
@ -1115,7 +1115,7 @@ static int tls_get_info(struct sock *sk, struct sk_buff *skb)
return err;
}
static size_t tls_get_info_size(const struct sock *sk)
static size_t tls_get_info_size(const struct sock *sk, bool net_admin)
{
size_t size = 0;