* [PATCH net-next 1/3] netlink: convert to getsockopt_iter
2026-05-01 15:52 [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API Breno Leitao
@ 2026-05-01 15:52 ` Breno Leitao
2026-05-04 14:54 ` Stanislav Fomichev
2026-05-01 15:52 ` [PATCH net-next 2/3] vsock: " Breno Leitao
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Breno Leitao @ 2026-05-01 15:52 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel
Cc: netdev, linux-kernel, virtualization, linux-kselftest,
Breno Leitao, kernel-team
Convert AF_NETLINK's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input) and returned size (output)
- Use copy_to_iter() instead of put_user()/copy_to_user()
- For NETLINK_LIST_MEMBERSHIPS: walk the groups bitmap and emit each
u32 sequentially via copy_to_iter(), then set opt->optlen to the
total size required (ALIGN(BITS_TO_BYTES(ngroups), sizeof(u32))).
The wrapper writes opt->optlen back to userspace even on partial
failure, preserving the existing API that lets userspace discover
the needed allocation size.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/netlink/af_netlink.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2aeb0680807d6..db3be485b4804 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -39,6 +39,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/uio.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
@@ -1716,18 +1717,18 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
}
static int netlink_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk);
unsigned int flag;
int len, val;
+ u32 group;
if (level != SOL_NETLINK)
return -ENOPROTOOPT;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = opt->optlen;
if (len < 0)
return -EINVAL;
@@ -1751,14 +1752,14 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
idx = pos / sizeof(unsigned long);
shift = (pos % sizeof(unsigned long)) * 8;
- if (put_user((u32)(nlk->groups[idx] >> shift),
- (u32 __user *)(optval + pos))) {
+ group = (u32)(nlk->groups[idx] >> shift);
+ if (copy_to_iter(&group, sizeof(u32),
+ &opt->iter_out) != sizeof(u32)) {
err = -EFAULT;
break;
}
}
- if (put_user(ALIGN(BITS_TO_BYTES(nlk->ngroups), sizeof(u32)), optlen))
- err = -EFAULT;
+ opt->optlen = ALIGN(BITS_TO_BYTES(nlk->ngroups), sizeof(u32));
netlink_unlock_table();
return err;
}
@@ -1784,8 +1785,8 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
len = sizeof(int);
val = test_bit(flag, &nlk->flags);
- if (put_user(len, optlen) ||
- copy_to_user(optval, &val, len))
+ opt->optlen = len;
+ if (copy_to_iter(&val, len, &opt->iter_out) != len)
return -EFAULT;
return 0;
@@ -2813,7 +2814,7 @@ static const struct proto_ops netlink_ops = {
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = netlink_setsockopt,
- .getsockopt = netlink_getsockopt,
+ .getsockopt_iter = netlink_getsockopt,
.sendmsg = netlink_sendmsg,
.recvmsg = netlink_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net-next 1/3] netlink: convert to getsockopt_iter
2026-05-01 15:52 ` [PATCH net-next 1/3] netlink: convert to getsockopt_iter Breno Leitao
@ 2026-05-04 14:54 ` Stanislav Fomichev
0 siblings, 0 replies; 11+ messages in thread
From: Stanislav Fomichev @ 2026-05-04 14:54 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
On 05/01, Breno Leitao wrote:
> Convert AF_NETLINK's getsockopt implementation to use the new
> getsockopt_iter callback with sockopt_t.
>
> Key changes:
> - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
> - Use opt->optlen for buffer length (input) and returned size (output)
> - Use copy_to_iter() instead of put_user()/copy_to_user()
> - For NETLINK_LIST_MEMBERSHIPS: walk the groups bitmap and emit each
> u32 sequentially via copy_to_iter(), then set opt->optlen to the
> total size required (ALIGN(BITS_TO_BYTES(ngroups), sizeof(u32))).
> The wrapper writes opt->optlen back to userspace even on partial
> failure, preserving the existing API that lets userspace discover
> the needed allocation size.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net-next 2/3] vsock: convert to getsockopt_iter
2026-05-01 15:52 [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API Breno Leitao
2026-05-01 15:52 ` [PATCH net-next 1/3] netlink: convert to getsockopt_iter Breno Leitao
@ 2026-05-01 15:52 ` Breno Leitao
2026-05-01 17:32 ` Bobby Eshleman
2026-05-04 14:54 ` Stanislav Fomichev
2026-05-01 15:52 ` [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests Breno Leitao
2026-05-05 2:20 ` [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API patchwork-bot+netdevbpf
3 siblings, 2 replies; 11+ messages in thread
From: Breno Leitao @ 2026-05-01 15:52 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel
Cc: netdev, linux-kernel, virtualization, linux-kselftest,
Breno Leitao, kernel-team
Convert AF_VSOCK's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t. The single
vsock_connectible_getsockopt() callback is shared by both
vsock_stream_ops and vsock_seqpacket_ops, so both proto_ops are
updated to use .getsockopt_iter.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input) and returned size (output)
- Use copy_to_iter() instead of put_user()/copy_to_user()
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/vmw_vsock/af_vsock.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 44037b066a5ff..d4a97eeb596e6 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -155,6 +155,7 @@
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/smp.h>
+#include <linux/uio.h>
#include <linux/socket.h>
#include <linux/stddef.h>
#include <linux/sysctl.h>
@@ -2091,8 +2092,7 @@ static int vsock_connectible_setsockopt(struct socket *sock,
static int vsock_connectible_getsockopt(struct socket *sock,
int level, int optname,
- char __user *optval,
- int __user *optlen)
+ sockopt_t *opt)
{
struct sock *sk = sock->sk;
struct vsock_sock *vsk = vsock_sk(sk);
@@ -2110,8 +2110,7 @@ static int vsock_connectible_getsockopt(struct socket *sock,
if (level != AF_VSOCK)
return -ENOPROTOOPT;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = opt->optlen;
memset(&v, 0, sizeof(v));
@@ -2142,11 +2141,10 @@ static int vsock_connectible_getsockopt(struct socket *sock,
return -EINVAL;
if (len > lv)
len = lv;
- if (copy_to_user(optval, &v, len))
+ if (copy_to_iter(&v, len, &opt->iter_out) != len)
return -EFAULT;
- if (put_user(len, optlen))
- return -EFAULT;
+ opt->optlen = len;
return 0;
}
@@ -2631,7 +2629,7 @@ static const struct proto_ops vsock_stream_ops = {
.listen = vsock_listen,
.shutdown = vsock_shutdown,
.setsockopt = vsock_connectible_setsockopt,
- .getsockopt = vsock_connectible_getsockopt,
+ .getsockopt_iter = vsock_connectible_getsockopt,
.sendmsg = vsock_connectible_sendmsg,
.recvmsg = vsock_connectible_recvmsg,
.mmap = sock_no_mmap,
@@ -2653,7 +2651,7 @@ static const struct proto_ops vsock_seqpacket_ops = {
.listen = vsock_listen,
.shutdown = vsock_shutdown,
.setsockopt = vsock_connectible_setsockopt,
- .getsockopt = vsock_connectible_getsockopt,
+ .getsockopt_iter = vsock_connectible_getsockopt,
.sendmsg = vsock_connectible_sendmsg,
.recvmsg = vsock_connectible_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net-next 2/3] vsock: convert to getsockopt_iter
2026-05-01 15:52 ` [PATCH net-next 2/3] vsock: " Breno Leitao
@ 2026-05-01 17:32 ` Bobby Eshleman
2026-05-01 21:21 ` David Laight
2026-05-04 14:54 ` Stanislav Fomichev
1 sibling, 1 reply; 11+ messages in thread
From: Bobby Eshleman @ 2026-05-01 17:32 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
On Fri, May 01, 2026 at 08:52:52AM -0700, Breno Leitao wrote:
> Convert AF_VSOCK's getsockopt implementation to use the new
> getsockopt_iter callback with sockopt_t. The single
> vsock_connectible_getsockopt() callback is shared by both
> vsock_stream_ops and vsock_seqpacket_ops, so both proto_ops are
> updated to use .getsockopt_iter.
>
> Key changes:
> - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
> - Use opt->optlen for buffer length (input) and returned size (output)
> - Use copy_to_iter() instead of put_user()/copy_to_user()
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> net/vmw_vsock/af_vsock.c | 16 +++++++---------
> 1 file changed, 7 insertions(+), 9 deletions(-)
>
> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index 44037b066a5ff..d4a97eeb596e6 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -155,6 +155,7 @@
> #include <linux/random.h>
> #include <linux/skbuff.h>
> #include <linux/smp.h>
> +#include <linux/uio.h>
> #include <linux/socket.h>
> #include <linux/stddef.h>
> #include <linux/sysctl.h>
> @@ -2091,8 +2092,7 @@ static int vsock_connectible_setsockopt(struct socket *sock,
>
> static int vsock_connectible_getsockopt(struct socket *sock,
> int level, int optname,
> - char __user *optval,
> - int __user *optlen)
> + sockopt_t *opt)
> {
> struct sock *sk = sock->sk;
> struct vsock_sock *vsk = vsock_sk(sk);
> @@ -2110,8 +2110,7 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> if (level != AF_VSOCK)
> return -ENOPROTOOPT;
>
> - if (get_user(len, optlen))
> - return -EFAULT;
> + len = opt->optlen;
>
> memset(&v, 0, sizeof(v));
>
> @@ -2142,11 +2141,10 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> return -EINVAL;
> if (len > lv)
> len = lv;
> - if (copy_to_user(optval, &v, len))
> + if (copy_to_iter(&v, len, &opt->iter_out) != len)
> return -EFAULT;
>
> - if (put_user(len, optlen))
> - return -EFAULT;
> + opt->optlen = len;
>
> return 0;
> }
> @@ -2631,7 +2629,7 @@ static const struct proto_ops vsock_stream_ops = {
> .listen = vsock_listen,
> .shutdown = vsock_shutdown,
> .setsockopt = vsock_connectible_setsockopt,
> - .getsockopt = vsock_connectible_getsockopt,
> + .getsockopt_iter = vsock_connectible_getsockopt,
> .sendmsg = vsock_connectible_sendmsg,
> .recvmsg = vsock_connectible_recvmsg,
> .mmap = sock_no_mmap,
> @@ -2653,7 +2651,7 @@ static const struct proto_ops vsock_seqpacket_ops = {
> .listen = vsock_listen,
> .shutdown = vsock_shutdown,
> .setsockopt = vsock_connectible_setsockopt,
> - .getsockopt = vsock_connectible_getsockopt,
> + .getsockopt_iter = vsock_connectible_getsockopt,
> .sendmsg = vsock_connectible_sendmsg,
> .recvmsg = vsock_connectible_recvmsg,
> .mmap = sock_no_mmap,
>
> --
> 2.52.0
>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH net-next 2/3] vsock: convert to getsockopt_iter
2026-05-01 17:32 ` Bobby Eshleman
@ 2026-05-01 21:21 ` David Laight
0 siblings, 0 replies; 11+ messages in thread
From: David Laight @ 2026-05-01 21:21 UTC (permalink / raw)
To: Bobby Eshleman
Cc: Breno Leitao, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Stefano Garzarella, Shuah Khan,
sdf.kernel, netdev, linux-kernel, virtualization, linux-kselftest,
kernel-team
On Fri, 1 May 2026 10:32:44 -0700
Bobby Eshleman <bobbyeshleman@gmail.com> wrote:
> On Fri, May 01, 2026 at 08:52:52AM -0700, Breno Leitao wrote:
> > Convert AF_VSOCK's getsockopt implementation to use the new
> > getsockopt_iter callback with sockopt_t. The single
> > vsock_connectible_getsockopt() callback is shared by both
> > vsock_stream_ops and vsock_seqpacket_ops, so both proto_ops are
> > updated to use .getsockopt_iter.
> >
> > Key changes:
> > - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
> > - Use opt->optlen for buffer length (input) and returned size (output)
> > - Use copy_to_iter() instead of put_user()/copy_to_user()
> >
> > Signed-off-by: Breno Leitao <leitao@debian.org>
> > ---
> > net/vmw_vsock/af_vsock.c | 16 +++++++---------
> > 1 file changed, 7 insertions(+), 9 deletions(-)
> >
> > diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> > index 44037b066a5ff..d4a97eeb596e6 100644
> > --- a/net/vmw_vsock/af_vsock.c
> > +++ b/net/vmw_vsock/af_vsock.c
> > @@ -155,6 +155,7 @@
> > #include <linux/random.h>
> > #include <linux/skbuff.h>
> > #include <linux/smp.h>
> > +#include <linux/uio.h>
> > #include <linux/socket.h>
> > #include <linux/stddef.h>
> > #include <linux/sysctl.h>
> > @@ -2091,8 +2092,7 @@ static int vsock_connectible_setsockopt(struct socket *sock,
> >
> > static int vsock_connectible_getsockopt(struct socket *sock,
> > int level, int optname,
> > - char __user *optval,
> > - int __user *optlen)
> > + sockopt_t *opt)
> > {
> > struct sock *sk = sock->sk;
> > struct vsock_sock *vsk = vsock_sk(sk);
> > @@ -2110,8 +2110,7 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> > if (level != AF_VSOCK)
> > return -ENOPROTOOPT;
> >
> > - if (get_user(len, optlen))
> > - return -EFAULT;
> > + len = opt->optlen;
> >
> > memset(&v, 0, sizeof(v));
> >
> > @@ -2142,11 +2141,10 @@ static int vsock_connectible_getsockopt(struct socket *sock,
> > return -EINVAL;
> > if (len > lv)
> > len = lv;
> > - if (copy_to_user(optval, &v, len))
> > + if (copy_to_iter(&v, len, &opt->iter_out) != len)
I'd wrap that as copy_to_sockopt(&v, len, opt).
or to make the edits easier: copy_to_sockopt(opt, &v, len).
Then if someone decides to change the implementation none of the call
sites need changing.
-- David
> > return -EFAULT;
> >
> > - if (put_user(len, optlen))
> > - return -EFAULT;
> > + opt->optlen = len;
> >
> > return 0;
> > }
> > @@ -2631,7 +2629,7 @@ static const struct proto_ops vsock_stream_ops = {
> > .listen = vsock_listen,
> > .shutdown = vsock_shutdown,
> > .setsockopt = vsock_connectible_setsockopt,
> > - .getsockopt = vsock_connectible_getsockopt,
> > + .getsockopt_iter = vsock_connectible_getsockopt,
> > .sendmsg = vsock_connectible_sendmsg,
> > .recvmsg = vsock_connectible_recvmsg,
> > .mmap = sock_no_mmap,
> > @@ -2653,7 +2651,7 @@ static const struct proto_ops vsock_seqpacket_ops = {
> > .listen = vsock_listen,
> > .shutdown = vsock_shutdown,
> > .setsockopt = vsock_connectible_setsockopt,
> > - .getsockopt = vsock_connectible_getsockopt,
> > + .getsockopt_iter = vsock_connectible_getsockopt,
> > .sendmsg = vsock_connectible_sendmsg,
> > .recvmsg = vsock_connectible_recvmsg,
> > .mmap = sock_no_mmap,
> >
> > --
> > 2.52.0
> >
>
> Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net-next 2/3] vsock: convert to getsockopt_iter
2026-05-01 15:52 ` [PATCH net-next 2/3] vsock: " Breno Leitao
2026-05-01 17:32 ` Bobby Eshleman
@ 2026-05-04 14:54 ` Stanislav Fomichev
1 sibling, 0 replies; 11+ messages in thread
From: Stanislav Fomichev @ 2026-05-04 14:54 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
On 05/01, Breno Leitao wrote:
> Convert AF_VSOCK's getsockopt implementation to use the new
> getsockopt_iter callback with sockopt_t. The single
> vsock_connectible_getsockopt() callback is shared by both
> vsock_stream_ops and vsock_seqpacket_ops, so both proto_ops are
> updated to use .getsockopt_iter.
>
> Key changes:
> - Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
> - Use opt->optlen for buffer length (input) and returned size (output)
> - Use copy_to_iter() instead of put_user()/copy_to_user()
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests
2026-05-01 15:52 [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API Breno Leitao
2026-05-01 15:52 ` [PATCH net-next 1/3] netlink: convert to getsockopt_iter Breno Leitao
2026-05-01 15:52 ` [PATCH net-next 2/3] vsock: " Breno Leitao
@ 2026-05-01 15:52 ` Breno Leitao
2026-05-01 17:17 ` Bobby Eshleman
2026-05-04 14:57 ` Stanislav Fomichev
2026-05-05 2:20 ` [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API patchwork-bot+netdevbpf
3 siblings, 2 replies; 11+ messages in thread
From: Breno Leitao @ 2026-05-01 15:52 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel
Cc: netdev, linux-kernel, virtualization, linux-kselftest,
Breno Leitao, kernel-team
Add a single kselftest covering the proto_ops getsockopt_iter
conversions for AF_NETLINK and AF_VSOCK, using one fixture per protocol:
netlink:
NETLINK_PKTINFO covers the flag-style int path (exact size, oversize
clamp, undersize -EINVAL); NETLINK_LIST_MEMBERSHIPS covers the
size-discovery path that always reports the required buffer length back
via optlen, even when the user buffer is too small to receive any group
bits.
vsock:
SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path (exact size, oversize
clamp, undersize -EINVAL).
Each fixture also exercises an unknown optname and a bogus level so
the returned-length / errno semantics preserved by the sockopt_t
conversion are pinned down.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
tools/testing/selftests/net/Makefile | 1 +
tools/testing/selftests/net/getsockopt_iter.c | 213 ++++++++++++++++++++++++++
2 files changed, 214 insertions(+)
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index a275ed5840265..baa30287cf222 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -176,6 +176,7 @@ TEST_GEN_PROGS := \
bind_timewait \
bind_wildcard \
epoll_busy_poll \
+ getsockopt_iter \
icmp_rfc4884 \
ipv6_fragmentation \
proc_net_pktgen \
diff --git a/tools/testing/selftests/net/getsockopt_iter.c b/tools/testing/selftests/net/getsockopt_iter.c
new file mode 100644
index 0000000000000..179f9e84926fd
--- /dev/null
+++ b/tools/testing/selftests/net/getsockopt_iter.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Quick test for getsockopt{_iter} tests.
+ *
+ * Each fixture targets one converted protocol and pins down the
+ * returned-length / errno semantics across buffer-size variations,
+ * an unknown optname and a bogus level.
+ *
+ * - netlink: NETLINK_PKTINFO covers the flag-style int path; the
+ * NETLINK_LIST_MEMBERSHIPS cases cover the size-discovery path
+ * that always reports the required buffer length back via optlen,
+ * even when the user buffer is too small to receive any group bits.
+ * - vsock: SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path.
+ *
+ * Author: Breno Leitao <leitao@debian.org>
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/vm_sockets.h>
+#include <sys/socket.h>
+#include "kselftest_harness.h"
+
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+
+/* ---------- netlink ---------- */
+
+FIXTURE(netlink)
+{
+ int fd;
+};
+
+FIXTURE_SETUP(netlink)
+{
+ int group = RTNLGRP_LINK;
+
+ self->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (self->fd < 0)
+ SKIP(return, "AF_NETLINK socket: %s", strerror(errno));
+
+ /* Joining a multicast group grows nlk->ngroups so the
+ * NETLINK_LIST_MEMBERSHIPS path has a non-zero size to report.
+ */
+ if (setsockopt(self->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &group, sizeof(group)) < 0)
+ SKIP(return, "NETLINK_ADD_MEMBERSHIP: %s", strerror(errno));
+}
+
+FIXTURE_TEARDOWN(netlink)
+{
+ if (self->fd >= 0)
+ close(self->fd);
+}
+
+TEST_F(netlink, pktinfo_exact)
+{
+ int val = -1;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
+ &val, &optlen));
+ ASSERT_EQ(sizeof(int), optlen);
+ ASSERT_TRUE(val == 0 || val == 1);
+}
+
+TEST_F(netlink, pktinfo_oversize_clamped)
+{
+ char buf[16] = {};
+ socklen_t optlen = sizeof(buf);
+
+ ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
+ buf, &optlen));
+ ASSERT_EQ(sizeof(int), optlen);
+}
+
+TEST_F(netlink, pktinfo_undersize)
+{
+ char buf[2] = {};
+ socklen_t optlen = sizeof(buf);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
+ buf, &optlen));
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST_F(netlink, list_memberships_size_discovery)
+{
+ socklen_t optlen = 0;
+ char dummy;
+
+ ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
+ NETLINK_LIST_MEMBERSHIPS,
+ &dummy, &optlen));
+ ASSERT_GT(optlen, 0);
+ ASSERT_EQ(0, optlen % sizeof(__u32));
+}
+
+TEST_F(netlink, list_memberships_full_read)
+{
+ __u32 buf[64] = {};
+ socklen_t optlen = sizeof(buf);
+
+ ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
+ NETLINK_LIST_MEMBERSHIPS,
+ buf, &optlen));
+ ASSERT_GT(optlen, 0);
+ ASSERT_LE(optlen, sizeof(buf));
+ ASSERT_EQ(0, optlen % sizeof(__u32));
+}
+
+TEST_F(netlink, bad_level)
+{
+ int val;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1, NETLINK_PKTINFO,
+ &val, &optlen));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
+TEST_F(netlink, bad_optname)
+{
+ int val;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, 0x7fff,
+ &val, &optlen));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
+/* ---------- vsock ---------- */
+
+FIXTURE(vsock)
+{
+ int fd;
+};
+
+FIXTURE_SETUP(vsock)
+{
+ self->fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+ if (self->fd < 0)
+ SKIP(return, "AF_VSOCK socket: %s", strerror(errno));
+}
+
+FIXTURE_TEARDOWN(vsock)
+{
+ if (self->fd >= 0)
+ close(self->fd);
+}
+
+TEST_F(vsock, buffer_size_exact)
+{
+ uint64_t val = 0;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_BUFFER_SIZE,
+ &val, &optlen));
+ ASSERT_EQ(sizeof(uint64_t), optlen);
+ ASSERT_GT(val, 0);
+}
+
+TEST_F(vsock, buffer_size_oversize_clamped)
+{
+ char buf[16] = {};
+ socklen_t optlen = sizeof(buf);
+
+ ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_BUFFER_SIZE,
+ buf, &optlen));
+ ASSERT_EQ(sizeof(uint64_t), optlen);
+}
+
+TEST_F(vsock, buffer_size_undersize)
+{
+ char buf[4] = {};
+ socklen_t optlen = sizeof(buf);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_BUFFER_SIZE,
+ buf, &optlen));
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST_F(vsock, bad_level)
+{
+ uint64_t val;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1,
+ SO_VM_SOCKETS_BUFFER_SIZE,
+ &val, &optlen));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
+TEST_F(vsock, bad_optname)
+{
+ uint64_t val;
+ socklen_t optlen = sizeof(val);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK, 0x7fff,
+ &val, &optlen));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
+TEST_HARNESS_MAIN
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests
2026-05-01 15:52 ` [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests Breno Leitao
@ 2026-05-01 17:17 ` Bobby Eshleman
2026-05-04 14:57 ` Stanislav Fomichev
1 sibling, 0 replies; 11+ messages in thread
From: Bobby Eshleman @ 2026-05-01 17:17 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, sdf.kernel, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
On Fri, May 01, 2026 at 08:52:53AM -0700, Breno Leitao wrote:
> Add a single kselftest covering the proto_ops getsockopt_iter
> conversions for AF_NETLINK and AF_VSOCK, using one fixture per protocol:
>
> netlink:
>
> NETLINK_PKTINFO covers the flag-style int path (exact size, oversize
> clamp, undersize -EINVAL); NETLINK_LIST_MEMBERSHIPS covers the
> size-discovery path that always reports the required buffer length back
> via optlen, even when the user buffer is too small to receive any group
> bits.
>
> vsock:
> SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path (exact size, oversize
> clamp, undersize -EINVAL).
>
> Each fixture also exercises an unknown optname and a bogus level so
> the returned-length / errno semantics preserved by the sockopt_t
> conversion are pinned down.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
This all looks good to me. My only thought was
SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW/OLD would be a nice add-on for testing
greater than u64, but probably overkill since you already have
NETLINK_LIST_MEMBERSHIPS.
Code all looks reasonable.
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
> ---
> tools/testing/selftests/net/Makefile | 1 +
> tools/testing/selftests/net/getsockopt_iter.c | 213 ++++++++++++++++++++++++++
> 2 files changed, 214 insertions(+)
>
> diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
> index a275ed5840265..baa30287cf222 100644
> --- a/tools/testing/selftests/net/Makefile
> +++ b/tools/testing/selftests/net/Makefile
> @@ -176,6 +176,7 @@ TEST_GEN_PROGS := \
> bind_timewait \
> bind_wildcard \
> epoll_busy_poll \
> + getsockopt_iter \
> icmp_rfc4884 \
> ipv6_fragmentation \
> proc_net_pktgen \
> diff --git a/tools/testing/selftests/net/getsockopt_iter.c b/tools/testing/selftests/net/getsockopt_iter.c
> new file mode 100644
> index 0000000000000..179f9e84926fd
> --- /dev/null
> +++ b/tools/testing/selftests/net/getsockopt_iter.c
> @@ -0,0 +1,213 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Quick test for getsockopt{_iter} tests.
> + *
> + * Each fixture targets one converted protocol and pins down the
> + * returned-length / errno semantics across buffer-size variations,
> + * an unknown optname and a bogus level.
> + *
> + * - netlink: NETLINK_PKTINFO covers the flag-style int path; the
> + * NETLINK_LIST_MEMBERSHIPS cases cover the size-discovery path
> + * that always reports the required buffer length back via optlen,
> + * even when the user buffer is too small to receive any group bits.
> + * - vsock: SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path.
> + *
> + * Author: Breno Leitao <leitao@debian.org>
> + */
> +
> +#include <errno.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <linux/netlink.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/vm_sockets.h>
> +#include <sys/socket.h>
> +#include "kselftest_harness.h"
> +
> +#ifndef AF_VSOCK
> +#define AF_VSOCK 40
> +#endif
> +
> +/* ---------- netlink ---------- */
> +
> +FIXTURE(netlink)
> +{
> + int fd;
> +};
> +
> +FIXTURE_SETUP(netlink)
> +{
> + int group = RTNLGRP_LINK;
> +
> + self->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
> + if (self->fd < 0)
> + SKIP(return, "AF_NETLINK socket: %s", strerror(errno));
> +
> + /* Joining a multicast group grows nlk->ngroups so the
> + * NETLINK_LIST_MEMBERSHIPS path has a non-zero size to report.
> + */
> + if (setsockopt(self->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
> + &group, sizeof(group)) < 0)
> + SKIP(return, "NETLINK_ADD_MEMBERSHIP: %s", strerror(errno));
> +}
> +
> +FIXTURE_TEARDOWN(netlink)
> +{
> + if (self->fd >= 0)
> + close(self->fd);
> +}
> +
> +TEST_F(netlink, pktinfo_exact)
> +{
> + int val = -1;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + &val, &optlen));
> + ASSERT_EQ(sizeof(int), optlen);
> + ASSERT_TRUE(val == 0 || val == 1);
> +}
> +
> +TEST_F(netlink, pktinfo_oversize_clamped)
> +{
> + char buf[16] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + buf, &optlen));
> + ASSERT_EQ(sizeof(int), optlen);
> +}
> +
> +TEST_F(netlink, pktinfo_undersize)
> +{
> + char buf[2] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
> + buf, &optlen));
> + ASSERT_EQ(EINVAL, errno);
> +}
> +
> +TEST_F(netlink, list_memberships_size_discovery)
> +{
> + socklen_t optlen = 0;
> + char dummy;
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
> + NETLINK_LIST_MEMBERSHIPS,
> + &dummy, &optlen));
> + ASSERT_GT(optlen, 0);
> + ASSERT_EQ(0, optlen % sizeof(__u32));
> +}
> +
> +TEST_F(netlink, list_memberships_full_read)
> +{
> + __u32 buf[64] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
> + NETLINK_LIST_MEMBERSHIPS,
> + buf, &optlen));
> + ASSERT_GT(optlen, 0);
> + ASSERT_LE(optlen, sizeof(buf));
> + ASSERT_EQ(0, optlen % sizeof(__u32));
> +}
> +
> +TEST_F(netlink, bad_level)
> +{
> + int val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1, NETLINK_PKTINFO,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_F(netlink, bad_optname)
> +{
> + int val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, 0x7fff,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +/* ---------- vsock ---------- */
> +
> +FIXTURE(vsock)
> +{
> + int fd;
> +};
> +
> +FIXTURE_SETUP(vsock)
> +{
> + self->fd = socket(AF_VSOCK, SOCK_STREAM, 0);
> + if (self->fd < 0)
> + SKIP(return, "AF_VSOCK socket: %s", strerror(errno));
> +}
> +
> +FIXTURE_TEARDOWN(vsock)
> +{
> + if (self->fd >= 0)
> + close(self->fd);
> +}
> +
> +TEST_F(vsock, buffer_size_exact)
> +{
> + uint64_t val = 0;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + &val, &optlen));
> + ASSERT_EQ(sizeof(uint64_t), optlen);
> + ASSERT_GT(val, 0);
> +}
> +
> +TEST_F(vsock, buffer_size_oversize_clamped)
> +{
> + char buf[16] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + buf, &optlen));
> + ASSERT_EQ(sizeof(uint64_t), optlen);
> +}
> +
> +TEST_F(vsock, buffer_size_undersize)
> +{
> + char buf[4] = {};
> + socklen_t optlen = sizeof(buf);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + buf, &optlen));
> + ASSERT_EQ(EINVAL, errno);
> +}
> +
> +TEST_F(vsock, bad_level)
> +{
> + uint64_t val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1,
> + SO_VM_SOCKETS_BUFFER_SIZE,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_F(vsock, bad_optname)
> +{
> + uint64_t val;
> + socklen_t optlen = sizeof(val);
> +
> + ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK, 0x7fff,
> + &val, &optlen));
> + ASSERT_EQ(ENOPROTOOPT, errno);
> +}
> +
> +TEST_HARNESS_MAIN
>
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests
2026-05-01 15:52 ` [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests Breno Leitao
2026-05-01 17:17 ` Bobby Eshleman
@ 2026-05-04 14:57 ` Stanislav Fomichev
1 sibling, 0 replies; 11+ messages in thread
From: Stanislav Fomichev @ 2026-05-04 14:57 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stefano Garzarella, Shuah Khan, netdev,
linux-kernel, virtualization, linux-kselftest, kernel-team
On 05/01, Breno Leitao wrote:
> Add a single kselftest covering the proto_ops getsockopt_iter
> conversions for AF_NETLINK and AF_VSOCK, using one fixture per protocol:
>
> netlink:
>
> NETLINK_PKTINFO covers the flag-style int path (exact size, oversize
> clamp, undersize -EINVAL); NETLINK_LIST_MEMBERSHIPS covers the
> size-discovery path that always reports the required buffer length back
> via optlen, even when the user buffer is too small to receive any group
> bits.
>
> vsock:
> SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path (exact size, oversize
> clamp, undersize -EINVAL).
>
> Each fixture also exercises an unknown optname and a bogus level so
> the returned-length / errno semantics preserved by the sockopt_t
> conversion are pinned down.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
A few nits if you happen to respin (or for similar tests in the future):
- add ASSERT_EQ(optlen, xxx), won't hurt
- christmas tree (although not sure how much we care, you'll have to move
optlen = sizeof() assignment)
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API
2026-05-01 15:52 [PATCH net-next 0/3] net: Convert AF_NETLINK and AF_VSOCK to getsockopt_iter API Breno Leitao
` (2 preceding siblings ...)
2026-05-01 15:52 ` [PATCH net-next 3/3] net: selftests: add getsockopt_iter regression tests Breno Leitao
@ 2026-05-05 2:20 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-05-05 2:20 UTC (permalink / raw)
To: Breno Leitao
Cc: davem, edumazet, kuba, pabeni, horms, sgarzare, shuah, sdf.kernel,
netdev, linux-kernel, virtualization, linux-kselftest,
kernel-team
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 01 May 2026 08:52:50 -0700 you wrote:
> Continue the work to convert protocols to the new getsockopt_iter API.
>
> Convert AF_NETLINK and AF_VSOCK getsockopt implementations to the new
> sockopt_t/getsockopt_iter API, and add kselftests that verify the size
> and errno semantics are preserved across the conversion.
>
> I chose these two socket families because they are probably one of the
> most used protocols,, ensuring that any potential bugs will be
> discovered and reported quickly.
>
> [...]
Here is the summary with links:
- [net-next,1/3] netlink: convert to getsockopt_iter
https://git.kernel.org/netdev/net-next/c/390bf43b7788
- [net-next,2/3] vsock: convert to getsockopt_iter
https://git.kernel.org/netdev/net-next/c/e21bf72954df
- [net-next,3/3] net: selftests: add getsockopt_iter regression tests
https://git.kernel.org/netdev/net-next/c/d39887f55d8e
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 11+ messages in thread