From: Breno Leitao <leitao@debian.org>
To: David Ahern <dsahern@kernel.org>,
Ido Schimmel <idosch@nvidia.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
John Fastabend <john.fastabend@gmail.com>,
Stanislav Fomichev <sdf@fomichev.me>,
Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org, linux-kselftest@vger.kernel.org,
david.laight.linux@gmail.com, Breno Leitao <leitao@debian.org>,
kernel-team@meta.com
Subject: [PATCH net-next 5/6] ipv6: convert do_ipv6_getsockopt() to sockopt_t
Date: Fri, 25 Sep 2026 08:55:20 -0700 [thread overview]
Message-ID: <20260925-sockopt_expand_out_v2-v1-5-c3ef2e3bb5c0@debian.org> (raw)
In-Reply-To: <20260925-sockopt_expand_out_v2-v1-0-c3ef2e3bb5c0@debian.org>
Convert the SOL_IPV6 switch and its two remaining sockptr_t leaves,
ip6_mroute_getsockopt() and ipv6_getsockopt_sticky(). The
MCAST_MSFILTER bridge goes away.
ipv6_getsockopt() builds the sockopt_t with sockopt_init_user() after
its own level checks, and writes optlen back unconditionally.
IPV6_2292PKTOPTIONS takes its buffer off iter_out; IPV6_FLOWLABEL_MGR
reads through iter_in. The argument is sopt, since the sticky options
already have an ipv6_txoptions local named opt.
MRT6_* is still dispatched before optlen is validated, so a negative
optlen there wins over -EOPNOTSUPP.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
include/linux/mroute6.h | 5 ++--
include/net/ipv6.h | 2 +-
net/core/filter.c | 18 ++++++++---
net/ipv6/ip6mr.c | 13 +++-----
net/ipv6/ipv6_sockglue.c | 78 ++++++++++++++++++++----------------------------
5 files changed, 53 insertions(+), 63 deletions(-)
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index fddafdc168f733..ab4d206fb32065 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -27,7 +27,7 @@ struct sock;
#ifdef CONFIG_IPV6_MROUTE
extern int ip6_mroute_setsockopt(struct sock *, int, sockptr_t, unsigned int);
-extern int ip6_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t);
+int ip6_mroute_getsockopt(struct sock *sk, int optname, sockopt_t *sopt);
extern int ip6_mr_input(struct sk_buff *skb);
extern int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
extern int ip6_mr_init(void);
@@ -42,8 +42,7 @@ static inline int ip6_mroute_setsockopt(struct sock *sock, int optname,
}
static inline
-int ip6_mroute_getsockopt(struct sock *sock,
- int optname, sockptr_t optval, sockptr_t optlen)
+int ip6_mroute_getsockopt(struct sock *sock, int optname, sockopt_t *sopt)
{
return -ENOPROTOOPT;
}
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 9bb68d75890364..a1e1de7da8c70d 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -1142,7 +1142,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval
int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
unsigned int optlen);
int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
- sockptr_t optval, sockptr_t optlen);
+ sockopt_t *sopt);
int ipv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
diff --git a/net/core/filter.c b/net/core/filter.c
index 9a706ec1f7f122..e0b79c78c9a9c8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5774,10 +5774,20 @@ static int sol_ipv6_sockopt(struct sock *sk, int optname,
return -EINVAL;
}
- if (getopt)
- return do_ipv6_getsockopt(sk, SOL_IPV6, optname,
- KERNEL_SOCKPTR(optval),
- KERNEL_SOCKPTR(optlen));
+ if (getopt) {
+ struct kvec kvec;
+ sockopt_t opt;
+ int err;
+
+ err = sockptr_to_sockopt(&opt, KERNEL_SOCKPTR(optval),
+ KERNEL_SOCKPTR(optlen), &kvec);
+ if (err)
+ return err;
+
+ err = do_ipv6_getsockopt(sk, SOL_IPV6, optname, &opt);
+ *optlen = opt.optlen;
+ return err;
+ }
return do_ipv6_setsockopt(sk, SOL_IPV6, optname,
KERNEL_SOCKPTR(optval), *optlen);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 36f117ad367081..9513258b95fb88 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1893,8 +1893,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
* Getsock opt support for the multicast routing system.
*/
-int ip6_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
- sockptr_t optlen)
+int ip6_mroute_getsockopt(struct sock *sk, int optname, sockopt_t *sopt)
{
int olr;
int val;
@@ -1925,16 +1924,12 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
return -ENOPROTOOPT;
}
- if (copy_from_sockptr(&olr, optlen, sizeof(int)))
- return -EFAULT;
-
- olr = min_t(int, olr, sizeof(int));
+ olr = min_t(int, sopt->optlen, sizeof(int));
if (olr < 0)
return -EINVAL;
- if (copy_to_sockptr(optlen, &olr, sizeof(int)))
- return -EFAULT;
- if (copy_to_sockptr(optval, &val, olr))
+ sopt->optlen = olr;
+ if (copy_to_iter(&val, olr, &sopt->iter_out) != olr)
return -EFAULT;
return 0;
}
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 1bdb3e001e4fe6..3a43e26234eea3 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -889,7 +889,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
EXPORT_SYMBOL(ipv6_setsockopt);
static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
- int optname, sockptr_t optval, int len)
+ int optname, sockopt_t *sopt, int len)
{
struct ipv6_opt_hdr *hdr;
@@ -917,7 +917,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
return 0;
len = min_t(unsigned int, len, ipv6_optlen(hdr));
- if (copy_to_sockptr(optval, hdr, len))
+ if (copy_to_iter(hdr, len, &sopt->iter_out) != len)
return -EFAULT;
return len;
}
@@ -997,39 +997,23 @@ static int compat_ipv6_get_msfilter(struct sock *sk, sockopt_t *opt)
return 0;
}
-int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
- sockptr_t optval, sockptr_t optlen)
+int do_ipv6_getsockopt(struct sock *sk, int level, int optname, sockopt_t *sopt)
{
struct ipv6_pinfo *np = inet6_sk(sk);
int len;
int val;
if (ip6_mroute_opt(optname))
- return ip6_mroute_getsockopt(sk, optname, optval, optlen);
+ return ip6_mroute_getsockopt(sk, optname, sopt);
- if (copy_from_sockptr(&len, optlen, sizeof(int)))
- return -EFAULT;
+ len = sopt->optlen;
if (len < 0)
return -EINVAL;
switch (optname) {
case MCAST_MSFILTER:
- {
- struct kvec kvec;
- sockopt_t opt;
- int err;
-
- err = sockptr_to_sockopt(&opt, optval, optlen, &kvec);
- if (err)
- return err;
-
if (in_compat_syscall())
- err = compat_ipv6_get_msfilter(sk, &opt);
- else
- err = ipv6_get_msfilter(sk, &opt);
- if (!err && copy_to_sockptr(optlen, &opt.optlen, sizeof(int)))
- err = -EFAULT;
- return err;
- }
+ return compat_ipv6_get_msfilter(sk, sopt);
+ return ipv6_get_msfilter(sk, sopt);
case IPV6_2292PKTOPTIONS:
{
struct msghdr msg;
@@ -1038,12 +1022,12 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (sk->sk_type != SOCK_STREAM)
return -ENOPROTOOPT;
- if (optval.is_kernel) {
+ if (iov_iter_is_kvec(&sopt->iter_out)) {
msg.msg_control_is_user = false;
- msg.msg_control = optval.kernel;
+ msg.msg_control = sopt->iter_out.kvec->iov_base;
} else {
msg.msg_control_is_user = true;
- msg.msg_control_user = optval.user;
+ msg.msg_control_user = sopt->iter_out.ubuf;
}
msg.msg_controllen = len;
msg.msg_flags = 0;
@@ -1094,8 +1078,8 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
put_cmsg(&msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
}
}
- len -= msg.msg_controllen;
- return copy_to_sockptr(optlen, &len, sizeof(int));
+ sopt->optlen = len - msg.msg_controllen;
+ return 0;
}
case IPV6_MTU:
{
@@ -1150,12 +1134,13 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
sockopt_lock_sock(sk);
opt = rcu_dereference_protected(np->opt,
lockdep_sock_is_held(sk));
- len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
+ len = ipv6_getsockopt_sticky(sk, opt, optname, sopt, len);
sockopt_release_sock(sk);
/* check if ipv6_getsockopt_sticky() returns err code */
if (len < 0)
return len;
- return copy_to_sockptr(optlen, &len, sizeof(int));
+ sopt->optlen = len;
+ return 0;
}
case IPV6_RECVHOPOPTS:
@@ -1209,9 +1194,8 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (!mtuinfo.ip6m_mtu)
return -ENOTCONN;
- if (copy_to_sockptr(optlen, &len, sizeof(int)))
- return -EFAULT;
- if (copy_to_sockptr(optval, &mtuinfo, len))
+ sopt->optlen = len;
+ if (copy_to_iter(&mtuinfo, len, &sopt->iter_out) != len)
return -EFAULT;
return 0;
@@ -1288,7 +1272,8 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (len < sizeof(freq))
return -EINVAL;
- if (copy_from_sockptr(&freq, optval, sizeof(freq)))
+ if (copy_from_iter(&freq, sizeof(freq), &sopt->iter_in) !=
+ sizeof(freq))
return -EFAULT;
if (freq.flr_action != IPV6_FL_A_GET)
@@ -1303,9 +1288,8 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (val < 0)
return val;
- if (copy_to_sockptr(optlen, &len, sizeof(int)))
- return -EFAULT;
- if (copy_to_sockptr(optval, &freq, len))
+ sopt->optlen = len;
+ if (copy_to_iter(&freq, len, &sopt->iter_out) != len)
return -EFAULT;
return 0;
@@ -1363,9 +1347,8 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
return -ENOPROTOOPT;
}
len = min_t(unsigned int, sizeof(int), len);
- if (copy_to_sockptr(optlen, &len, sizeof(int)))
- return -EFAULT;
- if (copy_to_sockptr(optval, &val, len))
+ sopt->optlen = len;
+ if (copy_to_iter(&val, len, &sopt->iter_out) != len)
return -EFAULT;
return 0;
}
@@ -1373,6 +1356,7 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
int ipv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
+ sockopt_t sopt;
int err;
if (level == SOL_IP && sk->sk_type != SOCK_RAW)
@@ -1381,15 +1365,17 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
if (level != SOL_IPV6)
return -ENOPROTOOPT;
- err = do_ipv6_getsockopt(sk, level, optname,
- USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
+ err = sockopt_init_user(&sopt, optval, optlen);
+ if (err)
+ return err;
+
+ err = do_ipv6_getsockopt(sk, level, optname, &sopt);
+ if (put_user(sopt.optlen, optlen))
+ return -EFAULT;
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
- int len;
-
- if (get_user(len, optlen))
- return -EFAULT;
+ int len = sopt.optlen;
err = nf_getsockopt(sk, PF_INET6, optname, optval, &len);
if (err >= 0)
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-25 15:56 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 15:55 [PATCH net-next 0/6] ipv4,ipv6: convert the getsockopt switches to sockopt_t Breno Leitao
2026-09-25 15:55 ` [PATCH net-next 1/6] ipv6: reject a negative optlen in do_ipv6_getsockopt() Breno Leitao
2026-09-25 19:02 ` Stanislav Fomichev
2026-09-27 6:53 ` David Laight
2026-09-29 12:14 ` Breno Leitao
2026-09-28 18:55 ` netdev-bot+sashiko
2026-09-25 15:55 ` [PATCH net-next 2/6] ipv6: mcast: convert ip6_mc_msfget() to sockopt_t Breno Leitao
2026-09-28 18:55 ` netdev-bot+sashiko
2026-09-25 15:55 ` [PATCH net-next 3/6] ipv4: igmp: convert ip_mc_gsfget() " Breno Leitao
2026-09-28 18:55 ` netdev-bot+sashiko
2026-09-25 15:55 ` [PATCH net-next 4/6] ipv4: convert do_ip_getsockopt() " Breno Leitao
2026-09-28 18:55 ` netdev-bot+sashiko
2026-09-25 15:55 ` Breno Leitao [this message]
2026-09-28 18:55 ` [PATCH net-next 5/6] ipv6: convert do_ipv6_getsockopt() " netdev-bot+sashiko
2026-09-25 15:55 ` [PATCH net-next 6/6] selftests: net: getsockopt_iter: cover ip and ipv6 Breno Leitao
2026-09-28 18:55 ` netdev-bot+sashiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925-sockopt_expand_out_v2-v1-5-c3ef2e3bb5c0@debian.org \
--to=leitao@debian.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=david.laight.linux@gmail.com \
--cc=dsahern@kernel.org \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=emil@etsalapatis.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox