From: Fernando Fernandez Mancera <fmancera@suse.de>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, dsahern@kernel.org, horms@kernel.org,
idosch@nvidia.com, Fernando Fernandez Mancera <fmancera@suse.de>,
Willem de Bruijn <willemb@google.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
Kees Cook <kees@kernel.org>,
Richard Gobert <richardbgobert@gmail.com>,
Jiayuan Chen <jiayuan.chen@linux.dev>,
Jeff Layton <jlayton@kernel.org>, Qi Tang <tpluszz77@gmail.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 03/13 RFC net-next] net: inet: relocate ip_generic_getfrag and guard IPv4 socket logic
Date: Sun, 12 Jul 2026 03:39:01 +0200 [thread overview]
Message-ID: <20260712013941.4570-4-fmancera@suse.de> (raw)
In-Reply-To: <20260712013941.4570-1-fmancera@suse.de>
To enable compiling the INET subsystem without IPv4, shared generic
utilities must be relocated and IPv4 socket logic must be guarded for
CONFIG_IPV4.
This patch moves the generic ip_generec_getfrag() from ip_output.c to
af_inet.c. It also introduces CONFIG_IPV4 guards around af_inet.c to
reject IPv4-specific ioctls, protocol registrations and bind requests.
The same guard is added to reject IPv4-mapped IPv6.
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
net/ipv4/af_inet.c | 96 +++++++++++++++++++++++++++++++++++++-------
net/ipv4/ip_output.c | 18 ---------
net/ipv6/af_inet6.c | 5 +++
net/ipv6/datagram.c | 12 ++++++
4 files changed, 99 insertions(+), 32 deletions(-)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 32d006c1a8ee..cd8e129394e4 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -129,6 +129,28 @@
int disable_ipv6_mod;
EXPORT_SYMBOL(disable_ipv6_mod);
+/* Keep the function here for now as it is generic, it should be moved
+ * to a common L3 place
+ */
+int
+ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
+{
+ struct msghdr *msg = from;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (!copy_from_iter_full(to, len, &msg->msg_iter))
+ return -EFAULT;
+ } else {
+ __wsum csum = 0;
+
+ if (!csum_and_copy_from_iter_full(to, len, &csum, &msg->msg_iter))
+ return -EFAULT;
+ skb->csum = csum_block_add(skb->csum, csum, odd);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(ip_generic_getfrag);
+
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
*/
@@ -425,8 +447,10 @@ int inet_release(struct socket *sock)
if (!sk->sk_kern_sock)
BPF_CGROUP_RUN_PROG_INET_SOCK_RELEASE(sk);
+#if IS_ENABLED(CONFIG_IPV4)
/* Applications forget to leave groups before exiting */
ip_mc_drop_socket(sk);
+#endif
/* If linger is set, we don't return until the close
* is complete. Otherwise we return immediately. The
@@ -478,6 +502,7 @@ EXPORT_SYMBOL(inet_bind);
int __inet_bind(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len,
u32 flags)
{
+#if IS_ENABLED(CONFIG_IPV4)
struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
struct inet_sock *inet = inet_sk(sk);
struct net *net = sock_net(sk);
@@ -570,6 +595,9 @@ int __inet_bind(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len,
release_sock(sk);
out:
return err;
+#else
+ return -EAFNOSUPPORT;
+#endif
}
int inet_dgram_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
@@ -965,18 +993,24 @@ EXPORT_SYMBOL(inet_shutdown);
int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- int err = 0;
- struct net *net = sock_net(sk);
+#if IS_ENABLED(CONFIG_IPV4)
void __user *p = (void __user *)arg;
- struct ifreq ifr;
+ struct net *net = sock_net(sk);
struct rtentry rt;
+ struct ifreq ifr;
+#endif
+ int err = 0;
switch (cmd) {
case SIOCADDRT:
case SIOCDELRT:
+#if IS_ENABLED(CONFIG_IPV4)
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
return -EFAULT;
err = ip_rt_ioctl(net, cmd, &rt);
+#else
+ err = -EOPNOTSUPP;
+#endif
break;
case SIOCRTMSG:
err = -EINVAL;
@@ -984,18 +1018,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCDARP:
case SIOCGARP:
case SIOCSARP:
+#if IS_ENABLED(CONFIG_IPV4)
err = arp_ioctl(net, cmd, (void __user *)arg);
+#else
+ err = -EOPNOTSUPP;
+#endif
break;
case SIOCGIFADDR:
case SIOCGIFBRDADDR:
case SIOCGIFNETMASK:
case SIOCGIFDSTADDR:
case SIOCGIFPFLAGS:
+#if IS_ENABLED(CONFIG_IPV4)
if (get_user_ifreq(&ifr, NULL, p))
return -EFAULT;
err = devinet_ioctl(net, cmd, &ifr);
if (!err && put_user_ifreq(&ifr, p))
err = -EFAULT;
+#else
+ err = -EOPNOTSUPP;
+#endif
break;
case SIOCSIFADDR:
@@ -1004,9 +1046,13 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFDSTADDR:
case SIOCSIFPFLAGS:
case SIOCSIFFLAGS:
+#if IS_ENABLED(CONFIG_IPV4)
if (get_user_ifreq(&ifr, NULL, p))
return -EFAULT;
err = devinet_ioctl(net, cmd, &ifr);
+#else
+ err = -EOPNOTSUPP;
+#endif
break;
default:
if (sk->sk_prot->ioctl)
@@ -1023,6 +1069,7 @@ EXPORT_SYMBOL(inet_ioctl);
static int inet_compat_routing_ioctl(struct sock *sk, unsigned int cmd,
struct compat_rtentry __user *ur)
{
+#if IS_ENABLED(CONFIG_IPV4)
compat_uptr_t rtdev;
struct rtentry rt;
@@ -1038,6 +1085,9 @@ static int inet_compat_routing_ioctl(struct sock *sk, unsigned int cmd,
rt.rt_dev = compat_ptr(rtdev);
return ip_rt_ioctl(sock_net(sk), cmd, &rt);
+#else
+ return -EOPNOTSUPP;
+#endif
}
static int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
@@ -1156,6 +1206,7 @@ static const struct net_proto_family inet_family_ops = {
.owner = THIS_MODULE,
};
+#if IS_ENABLED(CONFIG_IPV4)
/* Upon startup we insert all the elements in inetsw_array[] into
* the linked list inetsw.
*/
@@ -1169,7 +1220,6 @@ static struct inet_protosw inetsw_array[] =
.flags = INET_PROTOSW_PERMANENT |
INET_PROTOSW_ICSK,
},
-
{
.type = SOCK_DGRAM,
.protocol = IPPROTO_UDP,
@@ -1196,6 +1246,7 @@ static struct inet_protosw inetsw_array[] =
};
#define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
+#endif
void inet_register_protosw(struct inet_protosw *p)
{
@@ -1261,6 +1312,7 @@ EXPORT_SYMBOL(inet_unregister_protosw);
static int inet_sk_reselect_saddr(struct sock *sk)
{
+#if IS_ENABLED(CONFIG_IPV4)
struct inet_sock *inet = inet_sk(sk);
__be32 old_saddr = inet->inet_saddr;
__be32 daddr = inet->inet_daddr;
@@ -1312,6 +1364,9 @@ static int inet_sk_reselect_saddr(struct sock *sk)
* uniqueness. Wait for troubles.
*/
return __sk_prot_rehash(sk);
+#else
+ return -EAFNOSUPPORT;
+#endif
}
int inet_sk_rebuild_header(struct sock *sk)
@@ -1364,6 +1419,7 @@ void inet_sk_state_store(struct sock *sk, int newstate)
struct sk_buff *inet_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
+#if IS_ENABLED(CONFIG_IPV4)
bool udpfrag = false, fixedid = false, gso_partial, encap;
struct sk_buff *segs = ERR_PTR(-EINVAL);
const struct net_offload *ops;
@@ -1454,6 +1510,9 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
out:
return segs;
+#else
+ return ERR_PTR(-EPROTONOSUPPORT);
+#endif
}
static struct sk_buff *ipip_gso_segment(struct sk_buff *skb,
@@ -1777,6 +1836,10 @@ static int __init init_ipv4_mibs(void)
return register_pernet_subsys(&ipv4_mib_ops);
}
+#if IS_ENABLED(CONFIG_IPV4)
+static int ipv4_proc_init(void);
+#endif
+
static __net_init int inet_init_net(struct net *net)
{
/*
@@ -1827,8 +1890,6 @@ static int __init init_inet_pernet_ops(void)
return register_pernet_subsys(&af_inet_ops);
}
-static int ipv4_proc_init(void);
-
/*
* IP protocol layer initialiser
*/
@@ -1873,26 +1934,30 @@ static int __init ipv4_offload_init(void)
fs_initcall(ipv4_offload_init);
+#if IS_ENABLED(CONFIG_IPV4)
static struct packet_type ip_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_IP),
.func = ip_rcv,
.list_func = ip_list_rcv,
};
+#endif
static int __init inet_init(void)
{
+#if IS_ENABLED(CONFIG_IPV4)
struct inet_protosw *q;
struct list_head *r;
int rc;
+#endif
sock_skb_cb_check_size(sizeof(struct inet_skb_parm));
+#if IS_ENABLED(CONFIG_IPV4)
raw_hashinfo_init(&raw_v4_hashinfo);
rc = proto_register(&tcp_prot, 1);
if (rc)
goto out;
-
rc = proto_register(&udp_prot, 1);
if (rc)
goto out_unregister_tcp_proto;
@@ -1929,7 +1994,6 @@ static int __init inet_init(void)
};
if (inet_add_protocol(&net_hotdata.udp_protocol, IPPROTO_UDP) < 0)
pr_crit("%s: Cannot add UDP protocol\n", __func__);
-
net_hotdata.tcp_protocol = (struct net_protocol) {
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
@@ -1961,7 +2025,7 @@ static int __init inet_init(void)
*/
ip_init();
-
+#endif /* CONFIG_IPV4 */
/* Initialise per-cpu ipv4 mibs */
if (init_ipv4_mibs())
panic("%s: Cannot init ipv4 mibs\n", __func__);
@@ -1983,6 +2047,9 @@ static int __init inet_init(void)
if (icmp_init() < 0)
panic("Failed to create the ICMP control socket.\n");
+ if (init_inet_pernet_ops())
+ pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__);
+#if IS_ENABLED(CONFIG_IPV4)
/*
* Initialise the multicast router
*/
@@ -1990,19 +2057,17 @@ static int __init inet_init(void)
if (ip_mr_init())
pr_crit("%s: Cannot init ipv4 mroute\n", __func__);
#endif
-
- if (init_inet_pernet_ops())
- pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__);
-
ipv4_proc_init();
ipfrag_init();
dev_add_pack(&ip_packet_type);
+#endif /* CONFIG_IPV4 */
ip_tunnel_core_init();
- rc = 0;
+ return 0;
+#if IS_ENABLED(CONFIG_IPV4)
out:
return rc;
out_unregister_raw_proto:
@@ -2012,12 +2077,14 @@ static int __init inet_init(void)
out_unregister_tcp_proto:
proto_unregister(&tcp_prot);
goto out;
+#endif
}
fs_initcall(inet_init);
/* ------------------------------------------------------------------------ */
+#if IS_ENABLED(CONFIG_IPV4)
#ifdef CONFIG_PROC_FS
static int __init ipv4_proc_init(void)
{
@@ -2054,3 +2121,4 @@ static int __init ipv4_proc_init(void)
return 0;
}
#endif /* CONFIG_PROC_FS */
+#endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e6dd1e5b8c32..beb2f6a27556 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -928,24 +928,6 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
}
EXPORT_SYMBOL(ip_do_fragment);
-int
-ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
-{
- struct msghdr *msg = from;
-
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (!copy_from_iter_full(to, len, &msg->msg_iter))
- return -EFAULT;
- } else {
- __wsum csum = 0;
- if (!csum_and_copy_from_iter_full(to, len, &csum, &msg->msg_iter))
- return -EFAULT;
- skb->csum = csum_block_add(skb->csum, csum, odd);
- }
- return 0;
-}
-EXPORT_SYMBOL(ip_generic_getfrag);
-
static int __ip_append_data(struct sock *sk,
struct flowi4 *fl4,
struct sk_buff_head *queue,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 282912a11999..5652069d5eaa 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -299,6 +299,7 @@ int __inet6_bind(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len,
/* Check if the address belongs to the host. */
if (addr_type == IPV6_ADDR_MAPPED) {
+#if IS_ENABLED(CONFIG_IPV4)
struct net_device *dev = NULL;
int chk_addr_ret;
@@ -329,6 +330,10 @@ int __inet6_bind(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len,
err = -EADDRNOTAVAIL;
goto out;
}
+#else
+ err = -EADDRNOTAVAIL;
+ goto out;
+#endif
} else {
if (addr_type != IPV6_ADDR_ANY) {
struct net_device *dev = NULL;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 38d7b4845281..8165277629ad 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -33,10 +33,12 @@
#include <linux/errqueue.h>
#include <linux/uaccess.h>
+#if IS_ENABLED(CONFIG_IPV4)
static bool ipv6_mapped_addr_any(const struct in6_addr *a)
{
return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0);
}
+#endif
static void ip6_datagram_flow_key_init(struct flowi6 *fl6,
const struct sock *sk)
@@ -153,10 +155,14 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr_unsized *uaddr,
int err;
if (usin->sin6_family == AF_INET) {
+#if IS_ENABLED(CONFIG_IPV4)
if (ipv6_only_sock(sk))
return -EAFNOSUPPORT;
err = __ip4_datagram_connect(sk, uaddr, addr_len);
goto ipv4_connected;
+#else
+ return -EAFNOSUPPORT;
+#endif
}
if (addr_len < SIN6_LEN_RFC2133)
@@ -184,6 +190,7 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr_unsized *uaddr,
daddr = &usin->sin6_addr;
if (addr_type & IPV6_ADDR_MAPPED) {
+#if IS_ENABLED(CONFIG_IPV4)
struct sockaddr_in sin;
if (ipv6_only_sock(sk)) {
@@ -217,6 +224,9 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr_unsized *uaddr,
}
goto out;
+#else
+ return -ENETUNREACH;
+#endif
}
if (__ipv6_addr_needs_scope_id(addr_type)) {
@@ -522,10 +532,12 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
ipv6_iface_scope_id(&sin->sin6_addr,
IP6CB(skb)->iif);
} else {
+#if IS_ENABLED(CONFIG_IPV4)
ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
&sin->sin6_addr);
if (inet_cmsg_flags(inet_sk(sk)))
ip_cmsg_recv(msg, skb);
+#endif
}
}
--
2.54.0
next prev parent reply other threads:[~2026-07-12 1:40 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260712013941.4570-1-fmancera@suse.de>
2026-07-12 1:38 ` [PATCH 01/13 RFC net-next] net: ipv4: introduce CONFIG_IPV4 to decouple the IPv4 stack Fernando Fernandez Mancera
2026-07-12 11:01 ` Arnd Bergmann
2026-07-12 1:39 ` [PATCH 02/13 RFC net-next] net: core: add IPv4 fallback stubs and guards for CONFIG_IPV4=n Fernando Fernandez Mancera
2026-07-12 1:39 ` Fernando Fernandez Mancera [this message]
2026-07-12 1:39 ` [PATCH 04/13 RFC net-next] net: tcp: move protocol agnostic TCP functions out of tcp_ipv4.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 05/13 RFC net-next] net: raw: split IPv4 specific logic into raw_ipv4.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 06/13 RFC net-next] net: udp: split IPv4 specific logic into udp_ipv4.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 07/13 RFC net-next] net: icmp: split IPv4 specific logic into icmp_ipv4.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 08/13 RFC net-next] net: ping: split IPv4 specific logic into ping_ipv4.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 09/13 RFC net-next] net: fib: split common nexthop logic to fib_core.c Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 10/13 RFC net-next] net: tunnel: guard IPv4 tunnel functions with CONFIG_IPV4 Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 11/13 RFC net-next] net: cipso: guard IPv4 packet manipulation functions Fernando Fernandez Mancera
2026-07-12 16:22 ` Paul Moore
2026-07-12 1:39 ` [PATCH 12/13 RFC net-next] netfilter: ipv4: guard ip_route_me_harder() with CONFIG_IPV4 Fernando Fernandez Mancera
2026-07-12 1:39 ` [PATCH 13/13 RFC net-next] net: ipv4: make CONFIG_IPV4 boolean Fernando Fernandez Mancera
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=20260712013941.4570-4-fmancera@suse.de \
--to=fmancera@suse.de \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=jiayuan.chen@linux.dev \
--cc=jlayton@kernel.org \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=richardbgobert@gmail.com \
--cc=tpluszz77@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox