Const Qualifying
loadpin_sysctl_table
Pending: implement a new proc_handler function that handles the setting of load_root_writable
Creating a custom proc_handler: - It is not possible to create a proc_handler that defines param to pass to
do_proc_dointvec because do_proc_dointvec is static.
we need to do like what is done for proc_dointvec_jiffies which defies the push towards moving everything away from sysctl.c
We are tackling this in :ref: Release 7.00
memory_allocation_profiling_sysctls
We are tackling this in :ref: Release 7.00
s390 internal ctl_table
For Now ignore the inner non-const ctl_table definitions for s390.
There are two proc_handlers with inner ctl_tables: cmm_pages_handler and cmm_timed_pages_handler.
These handle two variables. One variable is used when writing and the other when reading
cmm_timed_pages_handler is special in that it does not set the variable when it is in writing mode (its not doing a var=value). It is incrementing the value (its doing a var+=value). This currently does not fit into any proc_handlers.
Const qualify the net directory
Note
net sysctl use the kmemdup pattern: in order to give a sysctl to a namespace they duplicate a template sysctl and create a “personalized” namespace sysctl.
What is the point of const qualifying a ctl_table if it will get kmemdup’ed and live outside the .rodata anyway? At that point you are just doing it for consistency. is it worth it?????
For all the patterns that use kmemdup, Don’t try to const qualify. We need another solution for that.!!!!!!
The reason all net sysctl are not const is the ensure_safe_net_sysctl call. This will change the ->mode bits (remove writable) to ensure that the base net sysctl variables are not overridden by nsnet variables. - Introduced in 2021 by Jonathon Reinhart in commit 31c4d2f160eb7 (“net:
Ensure net namespace isolation of sysctls”)
- ProposalThe first thing to do to const qualify the net sysctl is to
remove the modification in the ensure_save_net_sysctl. This would mean to just return error instead of making it readonly.
Consider this diff once we figure out what to do:
diff --git i/include/net/net_namespace.h w/include/net/net_namespace.h
index cb664f6e3558..dedac6e53691 100644
--- i/include/net/net_namespace.h
+++ w/include/net/net_namespace.h
@@ -517,7 +517,8 @@ 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; }
diff --git i/net/core/neighbour.c w/net/core/neighbour.c
index bddfa389effa..62e4ef36e663 100644
--- i/net/core/neighbour.c
+++ w/net/core/neighbour.c
@@ -3760,7 +3760,7 @@ static int neigh_proc_base_reachable_time(const struct ctl_table *ctl, int write
static struct neigh_sysctl_table {
struct ctl_table_header *sysctl_header;
struct ctl_table neigh_vars[NEIGH_VAR_MAX];
-} neigh_sysctl_template __read_mostly = {
+} const neigh_sysctl_template = {
.neigh_vars = {
NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
diff --git i/net/core/sysctl_net_core.c w/net/core/sysctl_net_core.c
index 8cf04b57ade1..8e07da7ac719 100644
--- i/net/core/sysctl_net_core.c
+++ w/net/core/sysctl_net_core.c
@@ -389,7 +389,7 @@ proc_dolongvec_minmax_bpf_restricted(const struct ctl_table *table, int write,
}
#endif
-static struct ctl_table net_core_table[] = {
+const static struct ctl_table net_core_table[] = {
{
.procname = "mem_pcpu_rsv",
.data = &net_hotdata.sysctl_mem_pcpu_rsv,
diff --git i/net/ieee802154/6lowpan/reassembly.c w/net/ieee802154/6lowpan/reassembly.c
index ddb6a5817d09..b9befa566129 100644
--- i/net/ieee802154/6lowpan/reassembly.c
+++ w/net/ieee802154/6lowpan/reassembly.c
@@ -349,7 +349,7 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = {
/* secret interval has been deprecated */
static int lowpan_frags_secret_interval_unused;
-static struct ctl_table lowpan_frags_ctl_table[] = {
+const static struct ctl_table lowpan_frags_ctl_table[] = {
{
.procname = "6lowpanfrag_secret_interval",
.data = &lowpan_frags_secret_interval_unused,
diff --git i/net/sctp/sysctl.c w/net/sctp/sysctl.c
index 15e7db9a3ab2..331f45af9c49 100644
--- i/net/sctp/sysctl.c
+++ w/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 i/net/sysctl_net.c w/net/sysctl_net.c
index 19e8048241ba..8af2e6e73855 100644
--- i/net/sysctl_net.c
+++ w/net/sysctl_net.c
@@ -120,10 +120,11 @@ __init int net_sysctl_init(void)
* 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;
@@ -155,18 +156,19 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path,
WARN(1, "sysctl %s/%s: data points to %s global data: %ps\n",
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);
}