* [PATCH RFC net-next v3 1/3] net: enforce net sysctl registration
2026-07-13 11:07 [PATCH RFC net-next v3 0/3] net: sysctl: Const Qualify sysctl ctl_table arrays Joel Granados
@ 2026-07-13 11:07 ` Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 2/3] net: Const qualify ctl_tables that kmemdup unconditionally Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 3/3] net: Const qualify network templated ctl_tables Arrays Joel Granados
2 siblings, 0 replies; 4+ messages in thread
From: Joel Granados @ 2026-07-13 11:07 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, David Ahern, Ido Schimmel, Pablo Neira Ayuso,
Florian Westphal, Phil Sutter, Marcelo Ricardo Leitner, Xin Long,
Steffen Klassert, Herbert Xu, D. Wythe, Dust Li, Sidraya Jayagond,
Wenjia Zhang, Mahanta Jambigi, Tony Lu, Wen Gu, Kuniyuki Iwashima,
Stefano Garzarella
Cc: netdev, linux-kernel, netfilter-devel, coreteam, linux-sctp,
linux-rdma, linux-s390, virtualization, Joel Granados
Replace the warning and file permission change with an error when an
"unsafe" net sysctl registration is detected.
One of the barriers preventing the const qualification of the ctl_tables
in the net directory is the permission (->mode) change in
ensure_safe_net_sysctl. This prep commit removes that barrier and
ensures that the received ctl_table pointer to the net ctl_table
register function is const.
Signed-off-by: Joel Granados <joel.granados@kernel.org>
---
include/net/net_namespace.h | 4 ++--
net/sysctl_net.c | 24 ++++++++++++------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 80de5e98a66d6c9273aa7c5b9d489b22cef8559a..dca0ec809483bec604f4ca3d99dfea32834af8fa 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -522,12 +522,12 @@ struct ctl_table;
#ifdef CONFIG_SYSCTL
int net_sysctl_init(void);
struct ctl_table_header *register_net_sysctl_sz(struct net *net, const char *path,
- struct ctl_table *table, size_t table_size);
+ const struct ctl_table *table, size_t table_size);
void unregister_net_sysctl_table(struct ctl_table_header *header);
#else
static inline int net_sysctl_init(void) { return 0; }
static inline struct ctl_table_header *register_net_sysctl_sz(struct net *net,
- const char *path, struct ctl_table *table, size_t table_size)
+ const char *path, const struct ctl_table *table, size_t table_size)
{
return NULL;
}
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 19e8048241bacb18de853d3b904d0f97fd2fe78a..4714887113d90a191c300c9c49a6317d5609efeb 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -114,16 +114,16 @@ __init int net_sysctl_init(void)
goto out;
}
-/* Verify that sysctls for non-init netns are safe by either:
+/* Return error when sysctls for non-init netns are unsafe by verifying:
* 1) being read-only, or
* 2) having a data pointer which points outside of the global kernel/module
* data segment, and rather into the heap where a per-net object was
* allocated.
*/
-static void ensure_safe_net_sysctl(struct net *net, const char *path,
- struct ctl_table *table, size_t table_size)
+static int ensure_safe_net_sysctl(struct net *net, const char *path,
+ const struct ctl_table *table, size_t table_size)
{
- struct ctl_table *ent;
+ const struct ctl_table *ent;
pr_debug("Registering net sysctl (net %p): %s\n", net, path);
ent = table;
@@ -149,24 +149,24 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path,
else
continue;
- /* If it is writable and points to kernel/module global
- * data, then it's probably a netns leak.
- */
+ /* Warn on netns leak. */
WARN(1, "sysctl %s/%s: data points to %s global data: %ps\n",
- path, ent->procname, where, ent->data);
+ path, ent->procname, where, ent->data);
- /* Make it "safe" by dropping writable perms */
- ent->mode &= ~0222;
+ return -EACCES;
}
+
+ return 0;
}
struct ctl_table_header *register_net_sysctl_sz(struct net *net,
const char *path,
- struct ctl_table *table,
+ const struct ctl_table *table,
size_t table_size)
{
if (!net_eq(net, &init_net))
- ensure_safe_net_sysctl(net, path, table, table_size);
+ if (ensure_safe_net_sysctl(net, path, table, table_size))
+ return NULL;
return __register_sysctl_table(&net->sysctls, path, table, table_size);
}
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH RFC net-next v3 2/3] net: Const qualify ctl_tables that kmemdup unconditionally
2026-07-13 11:07 [PATCH RFC net-next v3 0/3] net: sysctl: Const Qualify sysctl ctl_table arrays Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 1/3] net: enforce net sysctl registration Joel Granados
@ 2026-07-13 11:07 ` Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 3/3] net: Const qualify network templated ctl_tables Arrays Joel Granados
2 siblings, 0 replies; 4+ messages in thread
From: Joel Granados @ 2026-07-13 11:07 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, David Ahern, Ido Schimmel, Pablo Neira Ayuso,
Florian Westphal, Phil Sutter, Marcelo Ricardo Leitner, Xin Long,
Steffen Klassert, Herbert Xu, D. Wythe, Dust Li, Sidraya Jayagond,
Wenjia Zhang, Mahanta Jambigi, Tony Lu, Wen Gu, Kuniyuki Iwashima,
Stefano Garzarella
Cc: netdev, linux-kernel, netfilter-devel, coreteam, linux-sctp,
linux-rdma, linux-s390, virtualization, Joel Granados
Const qualify clt_table arrays in the net directory that always pass a
memory duplicate to sysctl register. The template would then be in
.rodata and the kmemdup'ed array would be outside.
Signed-off-by: Joel Granados <joel.granados@kernel.org>
---
net/ipv4/devinet.c | 2 +-
net/ipv6/icmp.c | 2 +-
net/ipv6/route.c | 2 +-
net/ipv6/sysctl_net_ipv6.c | 2 +-
net/netfilter/nf_conntrack_standalone.c | 2 +-
net/sctp/sysctl.c | 2 +-
net/xfrm/xfrm_sysctl.c | 2 +-
7 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a35b72662e431661da1672f428cae6bb3110480b..19edc08ae20c4f16d3bcf479dc25022d55cbb5af 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2798,7 +2798,7 @@ static void devinet_sysctl_unregister(struct in_device *idev)
neigh_sysctl_unregister(idev->arp_parms);
}
-static struct ctl_table ctl_forward_entry[] = {
+static const struct ctl_table ctl_forward_entry[] = {
{
.procname = "ip_forward",
.data = &ipv4_devconf.data[
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index efb23807a0262e8d68aa1afc8d96ee94eab89d50..a95b0351824f3237815e43bf8448110070955884 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -1374,7 +1374,7 @@ EXPORT_SYMBOL(icmpv6_err_convert);
static u32 icmpv6_errors_extension_mask_all =
GENMASK_U8(ICMP_ERR_EXT_COUNT - 1, 0);
-static struct ctl_table ipv6_icmp_table_template[] = {
+static const struct ctl_table ipv6_icmp_table_template[] = {
{
.procname = "ratelimit",
.data = &init_net.ipv6.sysctl.icmpv6_time,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a1301334da48c0f911da06ce448a76ecfb0d25cf..96b37c102a634c6715a5fbd1d39ca415302ff859 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -6555,7 +6555,7 @@ static int ipv6_sysctl_rtcache_flush(const struct ctl_table *ctl, int write,
return 0;
}
-static struct ctl_table ipv6_route_table_template[] = {
+static const struct ctl_table ipv6_route_table_template[] = {
{
.procname = "max_size",
.data = &init_net.ipv6.sysctl.ip6_rt_max_size,
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index d2cd33e2698d5c88df4718c9622dba2d574fa309..1a0a36dcdabc1be961d0ab69e5c93b05c53f46a8 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -61,7 +61,7 @@ proc_rt6_multipath_hash_fields(const struct ctl_table *table, int write, void *b
return ret;
}
-static struct ctl_table ipv6_table_template[] = {
+static const struct ctl_table ipv6_table_template[] = {
{
.procname = "bindv6only",
.data = &init_net.ipv6.sysctl.bindv6only,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index be2953c7d702e92031d4bcf7e707741abed0f49c..f4f2d82192d54ed9831b9677743f1139820e5a2e 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -639,7 +639,7 @@ enum nf_ct_sysctl_index {
NF_SYSCTL_CT_LAST_SYSCTL,
};
-static struct ctl_table nf_ct_sysctl_table[] = {
+static const struct ctl_table nf_ct_sysctl_table[] = {
[NF_SYSCTL_CT_MAX] = {
.procname = "nf_conntrack_max",
.data = &nf_conntrack_max,
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 15e7db9a3ab2e325f3951ac20c067a973a049618..331f45af9c4990d78a10a5c2c4efbcbca21813dc 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -92,7 +92,7 @@ static struct ctl_table sctp_table[] = {
#define SCTP_PF_RETRANS_IDX 2
#define SCTP_PS_RETRANS_IDX 3
-static struct ctl_table sctp_net_table[] = {
+static const struct ctl_table sctp_net_table[] = {
[SCTP_RTO_MIN_IDX] = {
.procname = "rto_min",
.data = &init_net.sctp.rto_min,
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index ca003e8a03760cd8dbb9e9f7cd5a9738eeeb7e71..357152a50faf10e5c33468c034dd1777e0bed079 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -13,7 +13,7 @@ static void __net_init __xfrm_sysctl_init(struct net *net)
}
#ifdef CONFIG_SYSCTL
-static struct ctl_table xfrm_table[] = {
+static const struct ctl_table xfrm_table[] = {
{
.procname = "xfrm_aevent_etime",
.maxlen = sizeof(u32),
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH RFC net-next v3 3/3] net: Const qualify network templated ctl_tables Arrays
2026-07-13 11:07 [PATCH RFC net-next v3 0/3] net: sysctl: Const Qualify sysctl ctl_table arrays Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 1/3] net: enforce net sysctl registration Joel Granados
2026-07-13 11:07 ` [PATCH RFC net-next v3 2/3] net: Const qualify ctl_tables that kmemdup unconditionally Joel Granados
@ 2026-07-13 11:07 ` Joel Granados
2 siblings, 0 replies; 4+ messages in thread
From: Joel Granados @ 2026-07-13 11:07 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, David Ahern, Ido Schimmel, Pablo Neira Ayuso,
Florian Westphal, Phil Sutter, Marcelo Ricardo Leitner, Xin Long,
Steffen Klassert, Herbert Xu, D. Wythe, Dust Li, Sidraya Jayagond,
Wenjia Zhang, Mahanta Jambigi, Tony Lu, Wen Gu, Kuniyuki Iwashima,
Stefano Garzarella
Cc: netdev, linux-kernel, netfilter-devel, coreteam, linux-sctp,
linux-rdma, linux-s390, virtualization, Joel Granados
Add duplication helpers in the cases where the ctl_table array elements
are modified after duplication. Helpers return a ctl_table as const
pointer allowing the const qualification of the static global ctl_table
array.
Signed-off-by: Joel Granados <joel.granados@kernel.org>
---
net/core/sysctl_net_core.c | 38 +++++++++++++++++----------
net/ipv4/sysctl_net_ipv4.c | 54 +++++++++++++++++++++++----------------
net/ipv4/xfrm4_policy.c | 22 ++++++++++++----
net/ipv6/xfrm6_policy.c | 22 ++++++++++++----
net/netfilter/nf_hooks_lwtunnel.c | 4 +--
net/smc/smc_sysctl.c | 26 ++++++++++++++-----
net/unix/sysctl_net_unix.c | 21 +++++++++++----
net/vmw_vsock/af_vsock.c | 25 +++++++++++++-----
8 files changed, 146 insertions(+), 66 deletions(-)
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index b508618bfc12393ba926ebf5a2dd4ea73ef03ee8..eb35da3556f4aa00cecd4582ab94e339d2518506 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -678,7 +678,7 @@ static struct ctl_table net_core_table[] = {
},
};
-static struct ctl_table netns_core_table[] = {
+static const struct ctl_table netns_core_table[] = {
#if IS_ENABLED(CONFIG_RPS)
{
.procname = "rps_default_mask",
@@ -787,26 +787,38 @@ static int __init fb_tunnels_only_for_init_net_sysctl_setup(char *str)
}
__setup("fb_tunnels=", fb_tunnels_only_for_init_net_sysctl_setup);
-static __net_init int sysctl_core_net_init(struct net *net)
+static const struct ctl_table *netns_core_table_dup(struct net *net)
{
size_t table_size = ARRAY_SIZE(netns_core_table);
struct ctl_table *tbl;
+ int i;
+
+ tbl = kmemdup(netns_core_table, sizeof(netns_core_table), GFP_KERNEL);
+ if (!tbl)
+ return NULL;
+
+ for (i = 0; i < table_size; ++i) {
+ if (tbl[i].data == &sysctl_wmem_max)
+ break;
+
+ tbl[i].data += (char *)net - (char *)&init_net;
+ }
+ for (; i < table_size; ++i)
+ tbl[i].mode &= ~0222;
+
+ return tbl;
+}
+
+static __net_init int sysctl_core_net_init(struct net *net)
+{
+ size_t table_size = ARRAY_SIZE(netns_core_table);
+ const struct ctl_table *tbl;
tbl = netns_core_table;
if (!net_eq(net, &init_net)) {
- int i;
- tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
+ tbl = netns_core_table_dup(net);
if (tbl == NULL)
goto err_dup;
-
- for (i = 0; i < table_size; ++i) {
- if (tbl[i].data == &sysctl_wmem_max)
- break;
-
- tbl[i].data += (char *)net - (char *)&init_net;
- }
- for (; i < table_size; ++i)
- tbl[i].mode &= ~0222;
}
net->core.sysctl_hdr = register_net_sysctl_sz(net, "net/core", tbl, table_size);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index ca1180dba1dea9ce72028ba49b7f953da343336b..2f0363bca2a88d68276670cfce6fb04398f82bc5 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -624,7 +624,7 @@ static struct ctl_table ipv4_table[] = {
},
};
-static struct ctl_table ipv4_net_table[] = {
+static const struct ctl_table ipv4_net_table[] = {
{
.procname = "tcp_max_tw_buckets",
.data = &init_net.ipv4.tcp_death_row.sysctl_max_tw_buckets,
@@ -1654,35 +1654,45 @@ static struct ctl_table ipv4_net_table[] = {
},
};
-static __net_init int ipv4_sysctl_init_net(struct net *net)
+static const struct ctl_table *ipv4_net_table_dup(struct net *net)
{
size_t table_size = ARRAY_SIZE(ipv4_net_table);
struct ctl_table *table;
+ int i;
+
+ table = kmemdup(ipv4_net_table, sizeof(ipv4_net_table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ for (i = 0; i < table_size; i++) {
+ if (table[i].data) {
+ /* Update the variables to point into
+ * the current struct net
+ */
+ table[i].data += (void *)net - (void *)&init_net;
+ } else {
+ /* Entries without data pointer are global;
+ * Make them read-only in non-init_net ns
+ */
+ table[i].mode &= ~0222;
+ }
+ if (table[i].extra2 >= (void *)&init_net.ipv4 &&
+ table[i].extra2 < (void *)(&init_net.ipv4 + 1))
+ table[i].extra2 += (void *)net - (void *)&init_net;
+ }
+ return table;
+}
+
+static __net_init int ipv4_sysctl_init_net(struct net *net)
+{
+ size_t table_size = ARRAY_SIZE(ipv4_net_table);
+ const struct ctl_table *table;
table = ipv4_net_table;
if (!net_eq(net, &init_net)) {
- int i;
-
- table = kmemdup(table, sizeof(ipv4_net_table), GFP_KERNEL);
+ table = ipv4_net_table_dup(net);
if (!table)
goto err_alloc;
-
- for (i = 0; i < table_size; i++) {
- if (table[i].data) {
- /* Update the variables to point into
- * the current struct net
- */
- table[i].data += (void *)net - (void *)&init_net;
- } else {
- /* Entries without data pointer are global;
- * Make them read-only in non-init_net ns
- */
- table[i].mode &= ~0222;
- }
- if (table[i].extra2 >= (void *)&init_net.ipv4 &&
- table[i].extra2 < (void *)(&init_net.ipv4 + 1))
- table[i].extra2 += (void *)net - (void *)&init_net;
- }
}
net->ipv4.ipv4_hdr = register_net_sysctl_sz(net, "net/ipv4", table,
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 58faf1ddd2b151e4569bb6351029718dac37521b..ab7a01029d490416d36482f7a3189f83d6670f42 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -141,7 +141,7 @@ static const struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
};
#ifdef CONFIG_SYSCTL
-static struct ctl_table xfrm4_policy_table[] = {
+static const struct ctl_table xfrm4_policy_table[] = {
{
.procname = "xfrm4_gc_thresh",
.data = &init_net.xfrm.xfrm4_dst_ops.gc_thresh,
@@ -151,18 +151,30 @@ static struct ctl_table xfrm4_policy_table[] = {
},
};
-static __net_init int xfrm4_net_sysctl_init(struct net *net)
+static const struct ctl_table *xfrm4_policy_table_dup(struct net *net)
{
struct ctl_table *table;
+
+ table = kmemdup(xfrm4_policy_table, sizeof(xfrm4_policy_table),
+ GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ table[0].data = &net->xfrm.xfrm4_dst_ops.gc_thresh;
+
+ return table;
+}
+
+static __net_init int xfrm4_net_sysctl_init(struct net *net)
+{
+ const struct ctl_table *table;
struct ctl_table_header *hdr;
table = xfrm4_policy_table;
if (!net_eq(net, &init_net)) {
- table = kmemdup(table, sizeof(xfrm4_policy_table), GFP_KERNEL);
+ table = xfrm4_policy_table_dup(net);
if (!table)
goto err_alloc;
-
- table[0].data = &net->xfrm.xfrm4_dst_ops.gc_thresh;
}
hdr = register_net_sysctl_sz(net, "net/ipv4", table,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 125ea9a5b8a082052380b7fd7ed7123f5247d7cc..1e0385b62cde3f6d23382f92bbad5d7fdd09f1ef 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -186,7 +186,7 @@ static void xfrm6_policy_fini(void)
}
#ifdef CONFIG_SYSCTL
-static struct ctl_table xfrm6_policy_table[] = {
+static const struct ctl_table xfrm6_policy_table[] = {
{
.procname = "xfrm6_gc_thresh",
.data = &init_net.xfrm.xfrm6_dst_ops.gc_thresh,
@@ -196,18 +196,30 @@ static struct ctl_table xfrm6_policy_table[] = {
},
};
-static int __net_init xfrm6_net_sysctl_init(struct net *net)
+static const struct ctl_table *xfrm6_policy_table_dup(struct net *net)
{
struct ctl_table *table;
+
+ table = kmemdup(xfrm6_policy_table, sizeof(xfrm6_policy_table),
+ GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ table[0].data = &net->xfrm.xfrm6_dst_ops.gc_thresh;
+
+ return table;
+}
+
+static int __net_init xfrm6_net_sysctl_init(struct net *net)
+{
+ const struct ctl_table *table;
struct ctl_table_header *hdr;
table = xfrm6_policy_table;
if (!net_eq(net, &init_net)) {
- table = kmemdup(table, sizeof(xfrm6_policy_table), GFP_KERNEL);
+ table = xfrm6_policy_table_dup(net);
if (!table)
goto err_alloc;
-
- table[0].data = &net->xfrm.xfrm6_dst_ops.gc_thresh;
}
hdr = register_net_sysctl_sz(net, "net/ipv6", table,
diff --git a/net/netfilter/nf_hooks_lwtunnel.c b/net/netfilter/nf_hooks_lwtunnel.c
index 2d890dd04ff89041e6aec3741f24cdd7bc47d1fe..4e1eef1ba0f1559ca35f024723af551c6c9e7d35 100644
--- a/net/netfilter/nf_hooks_lwtunnel.c
+++ b/net/netfilter/nf_hooks_lwtunnel.c
@@ -54,7 +54,7 @@ int nf_hooks_lwtunnel_sysctl_handler(const struct ctl_table *table, int write,
}
EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_sysctl_handler);
-static struct ctl_table nf_lwtunnel_sysctl_table[] = {
+static const struct ctl_table nf_lwtunnel_sysctl_table[] = {
{
.procname = "nf_hooks_lwtunnel",
.data = NULL,
@@ -66,8 +66,8 @@ static struct ctl_table nf_lwtunnel_sysctl_table[] = {
static int __net_init nf_lwtunnel_net_init(struct net *net)
{
+ const struct ctl_table *table;
struct ctl_table_header *hdr;
- struct ctl_table *table;
table = nf_lwtunnel_sysctl_table;
if (!net_eq(net, &init_net)) {
diff --git a/net/smc/smc_sysctl.c b/net/smc/smc_sysctl.c
index b1efed5462435b1a6f2f59584a4cf47f5f6e1981..09dad48337f6164f5765fa793412bdebf47e61ca 100644
--- a/net/smc/smc_sysctl.c
+++ b/net/smc/smc_sysctl.c
@@ -97,7 +97,7 @@ static int proc_smc_hs_ctrl(const struct ctl_table *ctl, int write,
}
#endif /* CONFIG_SMC_HS_CTRL_BPF */
-static struct ctl_table smc_table[] = {
+static const struct ctl_table smc_table[] = {
{
.procname = "autocorking_size",
.data = &init_net.smc.sysctl_autocorking_size,
@@ -195,14 +195,29 @@ static struct ctl_table smc_table[] = {
#endif /* CONFIG_SMC_HS_CTRL_BPF */
};
-int __net_init smc_sysctl_net_init(struct net *net)
+static const struct ctl_table *smc_table_dup(struct net *net)
{
size_t table_size = ARRAY_SIZE(smc_table);
struct ctl_table *table;
+ int i;
+
+ table = kmemdup(smc_table, sizeof(smc_table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ for (i = 0; i < table_size; i++)
+ table[i].data += (void *)net - (void *)&init_net;
+
+ return table;
+}
+
+int __net_init smc_sysctl_net_init(struct net *net)
+{
+ size_t table_size = ARRAY_SIZE(smc_table);
+ const struct ctl_table *table;
table = smc_table;
if (!net_eq(net, &init_net)) {
- int i;
#if IS_ENABLED(CONFIG_SMC_HS_CTRL_BPF)
struct smc_hs_ctrl *ctrl;
@@ -214,12 +229,9 @@ int __net_init smc_sysctl_net_init(struct net *net)
rcu_read_unlock();
#endif /* CONFIG_SMC_HS_CTRL_BPF */
- table = kmemdup(table, sizeof(smc_table), GFP_KERNEL);
+ table = smc_table_dup(net);
if (!table)
goto err_alloc;
-
- for (i = 0; i < table_size; i++)
- table[i].data += (void *)net - (void *)&init_net;
}
net->smc.smc_hdr = register_net_sysctl_sz(net, "net/smc", table,
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index e02ed6e3955c06b60cf4afb02656df8956f075ba..47660d5726bbd7d812762f4feffa9a0a42499d7d 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -13,7 +13,7 @@
#include "af_unix.h"
-static struct ctl_table unix_table[] = {
+static const struct ctl_table unix_table[] = {
{
.procname = "max_dgram_qlen",
.data = &init_net.unx.sysctl_max_dgram_qlen,
@@ -23,18 +23,29 @@ static struct ctl_table unix_table[] = {
},
};
-int __net_init unix_sysctl_register(struct net *net)
+static const struct ctl_table *unix_table_dup(struct net *net)
{
struct ctl_table *table;
+ table = kmemdup(unix_table, sizeof(unix_table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ table[0].data = &net->unx.sysctl_max_dgram_qlen;
+
+ return table;
+}
+
+int __net_init unix_sysctl_register(struct net *net)
+{
+ const struct ctl_table *table;
+
if (net_eq(net, &init_net)) {
table = unix_table;
} else {
- table = kmemdup(unix_table, sizeof(unix_table), GFP_KERNEL);
+ table = unix_table_dup(net);
if (!table)
goto err_alloc;
-
- table[0].data = &net->unx.sysctl_max_dgram_qlen;
}
net->unx.ctl = register_net_sysctl_sz(net, "net/unix", table,
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 622dbd0467994428f1a590f559b78d8c17f6ba60..caebef73ea58d2b6043ca3fe3b6872f92fbe9fa6 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -2899,7 +2899,7 @@ static int vsock_net_child_mode_string(const struct ctl_table *table, int write,
return 0;
}
-static struct ctl_table vsock_table[] = {
+static const struct ctl_table vsock_table[] = {
{
.procname = "ns_mode",
.data = &init_net.vsock.mode,
@@ -2925,20 +2925,31 @@ static struct ctl_table vsock_table[] = {
},
};
-static int __net_init vsock_sysctl_register(struct net *net)
+static const struct ctl_table *vsock_table_dup(struct net *net)
{
struct ctl_table *table;
+ table = kmemdup(vsock_table, sizeof(vsock_table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ table[0].data = &net->vsock.mode;
+ table[1].data = &net->vsock.child_ns_mode;
+ table[2].data = &net->vsock.g2h_fallback;
+
+ return table;
+}
+
+static int __net_init vsock_sysctl_register(struct net *net)
+{
+ const struct ctl_table *table;
+
if (net_eq(net, &init_net)) {
table = vsock_table;
} else {
- table = kmemdup(vsock_table, sizeof(vsock_table), GFP_KERNEL);
+ table = vsock_table_dup(net);
if (!table)
goto err_alloc;
-
- table[0].data = &net->vsock.mode;
- table[1].data = &net->vsock.child_ns_mode;
- table[2].data = &net->vsock.g2h_fallback;
}
net->vsock.sysctl_hdr = register_net_sysctl_sz(net, "net/vsock", table,
--
2.50.1
^ permalink raw reply related [flat|nested] 4+ messages in thread