From: Kuniyuki Iwashima <kuniyu@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Neal Cardwell <ncardwell@google.com>,
Willem de Bruijn <willemb@google.com>,
David Ahern <dsahern@kernel.org>,
Ido Schimmel <idosch@nvidia.com>
Cc: Simon Horman <horms@kernel.org>,
Kuniyuki Iwashima <kuniyu@google.com>,
Kuniyuki Iwashima <kuni1840@gmail.com>,
netdev@vger.kernel.org, Daehyeon Ko <4ncienth@gmail.com>,
Hyunwoo Kim <imv4bel@gmail.com>
Subject: [PATCH v1 net-next 2/2] ipv6: Remove IPV6_ADDRFORM.
Date: Fri, 4 Sep 2026 03:35:29 +0000 [thread overview]
Message-ID: <20260904033543.2635540-3-kuniyu@google.com> (raw)
In-Reply-To: <20260904033543.2635540-1-kuniyu@google.com>
Recently, IPV6_ADDRFORM has received many AI-driven bug reports.
Fixing them properly would needlessly churn the fast paths in TCP
and UDP.
IPV6_ADDRFORM was initially introduced in RFC 2133 in 1997,
but only two years later, it was removed from RFC 2553 in 1999.
In 2026, modern applications natively support dual-stack sockets;
notably, systemd's socket activation does not use IPV6_ADDRFORM.
Also, getsockopt(IPV6_ADDRFORM) can be replaced with SO_DOMAIN.
Let's remove IPV6_ADDRFORM.
Later, we can remove sk->sk_prot_creator and revert commit
c26c192c3d48 ("udp: properly deal with xfrm encap and ADDRFORM").
Reported-by: Daehyeon Ko <4ncienth@gmail.com>
Closes: https://lore.kernel.org/netdev/20260902010408.1057857-1-4ncienth@gmail.com/
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Closes: https://lore.kernel.org/netdev/20260824033331.1084971-1-imv4bel@gmail.com/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
include/linux/net.h | 2 +-
net/core/sock.c | 4 +-
net/ipv4/af_inet.c | 3 --
net/ipv6/af_inet6.c | 4 --
net/ipv6/ipv6_sockglue.c | 87 ----------------------------------------
5 files changed, 2 insertions(+), 98 deletions(-)
diff --git a/include/linux/net.h b/include/linux/net.h
index 3d82966e2243..470100ae7107 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -166,7 +166,7 @@ struct socket {
struct file *file;
struct sock *sk;
- const struct proto_ops *ops; /* Might change with IPV6_ADDRFORM or MPTCP. */
+ const struct proto_ops *ops; /* Might change with MPTCP. */
struct socket_wq wq;
};
diff --git a/net/core/sock.c b/net/core/sock.c
index fa60b7494c58..1d5927cd49a1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -770,7 +770,7 @@ bool sk_mc_loop(const struct sock *sk)
return false;
if (!sk)
return true;
- /* IPV6_ADDRFORM can change sk->sk_family under us. */
+
switch (READ_ONCE(sk->sk_family)) {
case AF_INET:
return inet_test_bit(MC_LOOP, sk);
@@ -4010,7 +4010,6 @@ int sock_common_getsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk = sock->sk;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
return READ_ONCE(sk->sk_prot)->getsockopt(sk, level, optname, optval, optlen);
}
EXPORT_SYMBOL(sock_common_getsockopt);
@@ -4032,7 +4031,6 @@ int sock_common_setsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk = sock->sk;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
return READ_ONCE(sk->sk_prot)->setsockopt(sk, level, optname, optval, optlen);
}
EXPORT_SYMBOL(sock_common_setsockopt);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 32d006c1a8ee..d9421ac38d78 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -582,7 +582,6 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
if (addr_len < sizeof(uaddr->sa_family))
return -EINVAL;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
if (uaddr->sa_family == AF_UNSPEC)
@@ -789,7 +788,6 @@ int inet_accept(struct socket *sock, struct socket *newsock,
{
struct sock *sk1 = sock->sk, *sk2;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
arg->err = -EINVAL;
sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, arg);
if (!sk2)
@@ -875,7 +873,6 @@ void inet_splice_eof(struct socket *sock)
if (unlikely(inet_send_prepare(sk)))
return;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
if (prot->splice_eof)
prot->splice_eof(sock);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 282912a11999..f0efdc13baf4 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -429,7 +429,6 @@ int inet6_bind_sk(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len)
const struct proto *prot;
int err = 0;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
/* If the socket has its own bind function then use it. */
if (prot->bind)
@@ -567,7 +566,6 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFDSTADDR:
return addrconf_set_dstaddr(net, argp);
default:
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
if (!prot->ioctl)
return -ENOIOCTLCMD;
@@ -636,7 +634,6 @@ int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (unlikely(inet_send_prepare(sk)))
return -EAGAIN;
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
return INDIRECT_CALL_2(prot->sendmsg, tcp_sendmsg, udpv6_sendmsg,
sk, msg, size);
@@ -651,7 +648,6 @@ int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
if (likely(!(flags & MSG_ERRQUEUE)))
sock_rps_record_flow(sk);
- /* IPV6_ADDRFORM can change sk->sk_prot under us. */
prot = READ_ONCE(sk->sk_prot);
return INDIRECT_CALL_2(prot->recvmsg, tcp_recvmsg, udpv6_recvmsg,
sk, msg, size, flags);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index b4c977434c2e..1f68fb64a43e 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -547,86 +547,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
sockopt_lock_sock(sk);
- /* Another thread has converted the socket into IPv4 with
- * IPV6_ADDRFORM concurrently.
- */
- if (unlikely(sk->sk_family != AF_INET6))
- goto unlock;
-
switch (optname) {
-
- case IPV6_ADDRFORM:
- if (optlen < sizeof(int))
- goto e_inval;
- if (val == PF_INET) {
- if (sk->sk_type == SOCK_RAW)
- break;
-
- if (sk->sk_protocol == IPPROTO_UDP) {
- if (udp_sk(sk)->pending == AF_INET6) {
- retv = -EBUSY;
- break;
- }
- } else if (sk->sk_protocol == IPPROTO_TCP) {
- if (sk->sk_prot != &tcpv6_prot) {
- retv = -EBUSY;
- break;
- }
- } else {
- break;
- }
-
- if (sk->sk_state != TCP_ESTABLISHED) {
- retv = -ENOTCONN;
- break;
- }
-
- if (ipv6_only_sock(sk) ||
- !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) {
- retv = -EADDRNOTAVAIL;
- break;
- }
-
- __ipv6_sock_mc_close(sk);
- __ipv6_sock_ac_close(sk);
-
- if (sk->sk_protocol == IPPROTO_TCP) {
- struct inet_connection_sock *icsk = inet_csk(sk);
-
- sock_prot_inuse_add(net, sk->sk_prot, -1);
- sock_prot_inuse_add(net, &tcp_prot, 1);
-
- /* Paired with READ_ONCE(sk->sk_prot) in inet6_stream_ops */
- WRITE_ONCE(sk->sk_prot, &tcp_prot);
- /* Paired with READ_ONCE() in tcp_(get|set)sockopt() */
- WRITE_ONCE(icsk->icsk_af_ops, &ipv4_specific);
- WRITE_ONCE(sk->sk_socket->ops, &inet_stream_ops);
- WRITE_ONCE(sk->sk_family, PF_INET);
- tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
- } else {
- sock_prot_inuse_add(net, sk->sk_prot, -1);
- sock_prot_inuse_add(net, &udp_prot, 1);
-
- /* Paired with READ_ONCE(sk->sk_prot) in inet6_dgram_ops */
- WRITE_ONCE(sk->sk_prot, &udp_prot);
- WRITE_ONCE(sk->sk_socket->ops, &inet_dgram_ops);
- WRITE_ONCE(sk->sk_family, PF_INET);
- }
-
- /* Disable all options not to allocate memory anymore,
- * but there is still a race. See the lockless path
- * in udpv6_sendmsg() and ipv6_local_rxpmtu().
- */
- np->rxopt.all = 0;
-
- inet6_cleanup_sock(sk);
-
- module_put(THIS_MODULE);
- retv = 0;
- break;
- }
- goto e_inval;
-
case IPV6_V6ONLY:
if (optlen < sizeof(int) ||
inet_sk(sk)->inet_num)
@@ -1088,14 +1009,6 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
if (copy_from_sockptr(&len, optlen, sizeof(int)))
return -EFAULT;
switch (optname) {
- case IPV6_ADDRFORM:
- if (sk->sk_protocol != IPPROTO_UDP &&
- sk->sk_protocol != IPPROTO_TCP)
- return -ENOPROTOOPT;
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
- val = sk->sk_family;
- break;
case MCAST_MSFILTER:
if (in_compat_syscall())
return compat_ipv6_get_msfilter(sk, optval, optlen, len);
--
2.55.0.1003.g10538fe699-goog
next prev parent reply other threads:[~2026-09-04 3:36 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 3:35 [PATCH v1 net-next 0/2] net: Disallow buggy TCP transitions and IPV6_ADDRFORM Kuniyuki Iwashima
2026-09-04 3:35 ` [PATCH v1 net-next 1/2] tcp: Do not allow buggy transitions between ehash and lhash2 Kuniyuki Iwashima
2026-09-04 11:32 ` Jakub Sitnicki
2026-09-07 4:19 ` netdev-bot+sashiko
2026-09-17 12:49 ` Daniel Zahka
2026-09-17 18:36 ` Kuniyuki Iwashima
2026-09-04 3:35 ` Kuniyuki Iwashima [this message]
2026-09-04 9:10 ` [PATCH v1 net-next 2/2] ipv6: Remove IPV6_ADDRFORM Paolo Abeni
2026-09-07 4:19 ` netdev-bot+sashiko
2026-09-08 9:21 ` David Laight
2026-09-08 1:00 ` [PATCH v1 net-next 0/2] net: Disallow buggy TCP transitions and IPV6_ADDRFORM patchwork-bot+netdevbpf
2026-09-18 22:35 ` Hyunwoo Kim
2026-09-19 21:20 ` Jakub Kicinski
2026-09-20 7:45 ` Greg Kroah-Hartman
2026-09-21 17:23 ` Jakub Kicinski
2026-09-22 0:42 ` Hyunwoo Kim
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=20260904033543.2635540-3-kuniyu@google.com \
--to=kuniyu@google.com \
--cc=4ncienth@gmail.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=imv4bel@gmail.com \
--cc=kuba@kernel.org \
--cc=kuni1840@gmail.com \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=willemb@google.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.