net: Const qualify network templated ctl_tables Arrays

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>
Link: https://patch.msgid.link/20260810-jag-net_const_qualify-v4-3-77e888237c69@kernel.org
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Joel Granados
2026-08-10 15:01:04 +02:00
committed by Paolo Abeni
parent 09190c59cd
commit 0abc76bc20
8 changed files with 146 additions and 66 deletions

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,

View File

@@ -187,7 +187,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,
@@ -197,18 +197,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,

View File

@@ -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)) {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,