net: enforce net sysctl registration

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>
Link: https://patch.msgid.link/20260810-jag-net_const_qualify-v4-1-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-13 13:12:21 +02:00
committed by Paolo Abeni
parent 68b3d4dbaf
commit ef6cb145e2
2 changed files with 15 additions and 13 deletions
+3 -2
View File
@@ -525,12 +525,13 @@ 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;
}
+12 -11
View File
@@ -114,16 +114,17 @@ out1:
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 +150,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);
/* 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);
}