diff options
| author | Paolo Abeni <pabeni@redhat.com> | 2026-07-02 12:29:08 +0200 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-07-02 12:29:08 +0200 |
| commit | 15fede6ca522fe192191df48856004497475b6a0 (patch) | |
| tree | 51d8c66e4742fbfec0b49cb6299d362815658a87 /include | |
| parent | b8ea7da314c2efcb9c2f559ed65b7a36c869d68e (diff) | |
| parent | f4d5e3a5c7bc3d789b5138ef127ab27e0128e2da (diff) | |
Merge branch 'net-convert-udp-getsockopt-to-sockopt_t'
Breno Leitao says:
====================
net: convert UDP getsockopt to sockopt_t
The leaf proto_ops getsockopt callbacks have been moving to the new
getsockopt_iter()/sockopt_t interface.
I was trying to get SMC into getsockop and retire .getsockopt, but,
I found the best approach is to keep converting other protocols.
This series starts the same conversion one layer down, at the struct proto
getsockopt path, beginning with UDP.
Example of the current code.
static int udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
if (level == SOL_UDP)
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
return ip_getsockopt(sk, level, optname, optval, optlen);
}
We want udp_getsockopt to go to .getsockopt_iter, and there are two
approaches in this case:
1) Create a patchset that moves both of them to getsockopt_iter, which
is will be a huge change (ip_getsockopt() is used in many places)
2) Break this down, and transform from bottoms up. First
udp_lib_getsockopt() up to the point we can easily convert
others, such as ip_getsockopt().
I am taking the approach 2), so, the intermediate code will be something
like:
static int udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
sockopt_t opt;
int err;
if (level != SOL_UDP)
return ip_getsockopt(sk, level, optname, optval, optlen);
// Convert optlen/optval in sockopt // (first patch)
err = udp_lib_getsockopt(sk, level, optname, &opt);
}
The work is bottom-up and mergeable in small steps: a protocol's inner
getsockopt helper is switched to sockopt_t behind its existing thin
__user wrapper, one patch at a time.
Once every inner helper speaks sockopt_t, a later series flips the shared
struct proto.getsockopt and inet_connection_sock_af_ops.getsockopt signatures
and drops the transitional wrappers.
Signed-off-by: Breno Leitao <leitao@debian.org>
====================
Link: https://patch.msgid.link/20260630-getsockopt_phase2-v2-0-193335f3d4d1@debian.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/net.h | 23 | ||||
| -rw-r--r-- | include/net/udp.h | 2 |
2 files changed, 24 insertions, 1 deletions
diff --git a/include/linux/net.h b/include/linux/net.h index f268f395ce47..277188a40c72 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -47,6 +47,29 @@ typedef struct sockopt { int optlen; } sockopt_t; +/* + * Initialize a user-backed sockopt_t from the (optval, optlen) __user pair of + * a getsockopt() callback. Used by transitional __user getsockopt wrappers + * while the proto-layer callbacks are converted to take a sockopt_t; the + * caller writes opt->optlen back to the user optlen after the callback. + */ +static inline int sockopt_init_user(sockopt_t *opt, char __user *optval, + int __user *optlen) +{ + int len; + + if (get_user(len, optlen)) + return -EFAULT; + if (len < 0) + return -EINVAL; + + iov_iter_ubuf(&opt->iter_out, ITER_DEST, optval, len); + iov_iter_ubuf(&opt->iter_in, ITER_SOURCE, optval, len); + opt->optlen = len; + + return 0; +} + struct poll_table_struct; struct pipe_inode_info; struct inode; diff --git a/include/net/udp.h b/include/net/udp.h index 8262e2b215b4..1fee17274745 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -430,7 +430,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features, bool is_ipv6); int udp_lib_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen); + sockopt_t *opt); int udp_lib_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen, int (*push_pending_frames)(struct sock *)); |
