2023-12-04 07:53:24

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Problem description:

The kernel contains a lot of struct ctl_table throught the tree.
These are very often 'static' definitions.
It would be good to make the tables unmodifiable by marking them "const"
to avoid accidental or malicious modifications.
This is in line with a general effort to move as much data as possible
into .rodata. (See for example[0] and [1])

Unfortunately the tables can not be made const right now because the
core registration functions expect mutable tables.

This is for two main reasons:

1) sysctl_{set,clear}_perm_empty_ctl_header in the sysctl core modify
the table.
2) The table is passed to the handler function as a non-const pointer.

This series migrates the core and all handlers.

Structure of the series:

Patch 1-3: Cleanup patches
Patch 4-7: Non-logic preparation patches
Patch 8: Preparation patch changing a bit of logic
Patch 9-12: Treewide changes to handler function signature
Patch 13-14: Adaption of the sysctl core implementation
Patch 15: Adaption of the sysctl core interface
Patch 16: New entry for checkpatch
Patch 17-18: Constification of existing "struct ctl_table"s

Tested by booting and with the sysctl selftests on x86.

Note:

This is intentionally sent only to a small number of people as I'd like
to get some more sysctl core-maintainer feedback before sending this to
essentially everybody.

[0] 43a7206b0963 ("driver core: class: make class_register() take a const *")
[1] https://lore.kernel.org/lkml/[email protected]/

---
Changes in v2:
- Migrate all handlers.
- Remove intermediate "proc_handler_new" step (Thanks Joel).
- Drop RFC status.
- Prepare other parts of the tree.
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Thomas Weißschuh (18):
watchdog/core: remove sysctl handlers from public header
sysctl: delete unused define SYSCTL_PERM_EMPTY_DIR
sysctl: drop sysctl_is_perm_empty_ctl_table
cgroup: bpf: constify ctl_table arguments and fields
seccomp: constify ctl_table arguments of utility functions
hugetlb: constify ctl_table arguments of utility functions
utsname: constify ctl_table arguments of utility function
stackleak: don't modify ctl_table argument
sysctl: treewide: constify ctl_table_root::set_ownership
sysctl: treewide: constify ctl_table_root::permissions
sysctl: treewide: constify ctl_table_header::ctl_table_arg
sysctl: treewide: constify the ctl_table argument of handlers
sysctl: move sysctl type to ctl_table_header
sysctl: move internal interfaces to const struct ctl_table
sysctl: allow registration of const struct ctl_table
const_structs.checkpatch: add ctl_table
sysctl: make ctl_table sysctl_mount_point const
sysctl: constify standard sysctl tables

arch/arm64/kernel/armv8_deprecated.c | 2 +-
arch/arm64/kernel/fpsimd.c | 2 +-
arch/s390/appldata/appldata_base.c | 8 +--
arch/s390/kernel/debug.c | 2 +-
arch/s390/kernel/topology.c | 2 +-
arch/s390/mm/cmm.c | 6 +-
arch/x86/kernel/itmt.c | 2 +-
drivers/cdrom/cdrom.c | 4 +-
drivers/char/random.c | 4 +-
drivers/macintosh/mac_hid.c | 2 +-
drivers/net/vrf.c | 4 +-
drivers/parport/procfs.c | 12 ++--
fs/coredump.c | 2 +-
fs/dcache.c | 4 +-
fs/drop_caches.c | 2 +-
fs/exec.c | 4 +-
fs/file_table.c | 2 +-
fs/fs-writeback.c | 2 +-
fs/inode.c | 4 +-
fs/pipe.c | 2 +-
fs/proc/internal.h | 2 +-
fs/proc/proc_sysctl.c | 102 +++++++++++++++---------------
fs/quota/dquot.c | 2 +-
fs/xfs/xfs_sysctl.c | 6 +-
include/linux/bpf-cgroup.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/ftrace.h | 4 +-
include/linux/mm.h | 8 +--
include/linux/nmi.h | 7 --
include/linux/perf_event.h | 6 +-
include/linux/security.h | 2 +-
include/linux/sysctl.h | 78 +++++++++++------------
include/linux/vmstat.h | 6 +-
include/linux/writeback.h | 2 +-
include/net/ndisc.h | 2 +-
include/net/neighbour.h | 6 +-
include/net/netfilter/nf_hooks_lwtunnel.h | 2 +-
ipc/ipc_sysctl.c | 12 ++--
ipc/mq_sysctl.c | 2 +-
kernel/bpf/cgroup.c | 2 +-
kernel/bpf/syscall.c | 4 +-
kernel/delayacct.c | 4 +-
kernel/events/callchain.c | 2 +-
kernel/events/core.c | 4 +-
kernel/fork.c | 2 +-
kernel/hung_task.c | 4 +-
kernel/kexec_core.c | 2 +-
kernel/kprobes.c | 2 +-
kernel/latencytop.c | 4 +-
kernel/pid_namespace.c | 2 +-
kernel/pid_sysctl.h | 2 +-
kernel/printk/internal.h | 2 +-
kernel/printk/printk.c | 2 +-
kernel/printk/sysctl.c | 5 +-
kernel/sched/core.c | 8 +--
kernel/sched/rt.c | 12 ++--
kernel/sched/topology.c | 2 +-
kernel/seccomp.c | 8 +--
kernel/stackleak.c | 9 +--
kernel/sysctl.c | 84 ++++++++++++------------
kernel/time/timer.c | 2 +-
kernel/trace/ftrace.c | 2 +-
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events_user.c | 2 +-
kernel/trace/trace_stack.c | 2 +-
kernel/ucount.c | 4 +-
kernel/umh.c | 2 +-
kernel/utsname_sysctl.c | 4 +-
kernel/watchdog.c | 15 +++--
mm/compaction.c | 8 +--
mm/hugetlb.c | 10 +--
mm/page-writeback.c | 18 +++---
mm/page_alloc.c | 22 +++----
mm/util.c | 12 ++--
mm/vmstat.c | 4 +-
net/ax25/sysctl_net_ax25.c | 2 +-
net/bridge/br_netfilter_hooks.c | 6 +-
net/core/neighbour.c | 24 +++----
net/core/sysctl_net_core.c | 22 +++----
net/ieee802154/6lowpan/reassembly.c | 2 +-
net/ipv4/devinet.c | 8 +--
net/ipv4/ip_fragment.c | 2 +-
net/ipv4/route.c | 4 +-
net/ipv4/sysctl_net_ipv4.c | 35 +++++-----
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/addrconf.c | 29 +++++----
net/ipv6/ndisc.c | 4 +-
net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +-
net/ipv6/reassembly.c | 2 +-
net/ipv6/route.c | 2 +-
net/ipv6/sysctl_net_ipv6.c | 10 +--
net/ipv6/xfrm6_policy.c | 2 +-
net/mpls/af_mpls.c | 8 +--
net/mptcp/ctrl.c | 2 +-
net/netfilter/ipvs/ip_vs_ctl.c | 16 ++---
net/netfilter/nf_conntrack_standalone.c | 4 +-
net/netfilter/nf_hooks_lwtunnel.c | 2 +-
net/netfilter/nf_log.c | 4 +-
net/phonet/sysctl.c | 2 +-
net/rds/tcp.c | 4 +-
net/sctp/sysctl.c | 30 ++++-----
net/smc/smc_sysctl.c | 2 +-
net/sunrpc/sysctl.c | 6 +-
net/sunrpc/xprtrdma/svc_rdma.c | 2 +-
net/sysctl_net.c | 4 +-
net/unix/sysctl_net_unix.c | 2 +-
net/xfrm/xfrm_sysctl.c | 2 +-
scripts/const_structs.checkpatch | 1 +
security/apparmor/lsm.c | 2 +-
security/min_addr.c | 2 +-
security/yama/yama_lsm.c | 2 +-
111 files changed, 427 insertions(+), 428 deletions(-)
---
base-commit: 33cc938e65a98f1d29d0a18403dbbee050dcad9a
change-id: 20231116-const-sysctl-e14624f1295c

Best regards,
--
Thomas Weißschuh <[email protected]>


2023-12-04 07:53:25

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 08/18] stackleak: don't modify ctl_table argument

In a future commit the proc_handlers will change to
"const struct ctl_table".
As a preparation for that adapt the logic to work with a temporary
variable, similar to how it is done in other parts of the kernel.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
kernel/stackleak.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/kernel/stackleak.c b/kernel/stackleak.c
index 34c9d81eea94..b292e5ca0b7d 100644
--- a/kernel/stackleak.c
+++ b/kernel/stackleak.c
@@ -27,10 +27,11 @@ static int stack_erasing_sysctl(struct ctl_table *table, int write,
int ret = 0;
int state = !static_branch_unlikely(&stack_erasing_bypass);
int prev_state = state;
+ struct ctl_table tmp = *table;

- table->data = &state;
- table->maxlen = sizeof(int);
- ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ tmp.data = &state;
+ tmp.maxlen = sizeof(int);
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
state = !!state;
if (ret || !write || state == prev_state)
return ret;

--
2.43.0

2023-12-04 07:53:25

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 10/18] sysctl: treewide: constify ctl_table_root::permissions

In a future commit the sysctl core will only use
"const struct ctl_table". As a preparation for that adapt the
permission callbacks.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
include/linux/sysctl.h | 2 +-
ipc/ipc_sysctl.c | 2 +-
kernel/ucount.c | 2 +-
net/sysctl_net.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 800154e1ff88..92c1d0114cdc 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -207,7 +207,7 @@ struct ctl_table_root {
void (*set_ownership)(struct ctl_table_header *head,
const struct ctl_table *table,
kuid_t *uid, kgid_t *gid);
- int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
+ int (*permissions)(struct ctl_table_header *head, const struct ctl_table *table);
};

/* struct ctl_path describes where in the hierarchy a table is added */
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 8c62e443f78b..b087787f608f 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -190,7 +190,7 @@ static int set_is_seen(struct ctl_table_set *set)
return &current->nsproxy->ipc_ns->ipc_set == set;
}

-static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
+static int ipc_permissions(struct ctl_table_header *head, const struct ctl_table *table)
{
int mode = table->mode;

diff --git a/kernel/ucount.c b/kernel/ucount.c
index 4aa6166cb856..90300840256b 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -38,7 +38,7 @@ static int set_is_seen(struct ctl_table_set *set)
}

static int set_permissions(struct ctl_table_header *head,
- struct ctl_table *table)
+ const struct ctl_table *table)
{
struct user_namespace *user_ns =
container_of(head->set, struct user_namespace, set);
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 1310ef8f0958..2873a4fed47d 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -40,7 +40,7 @@ static int is_seen(struct ctl_table_set *set)

/* Return standard mode bits for table entry. */
static int net_ctl_permissions(struct ctl_table_header *head,
- struct ctl_table *table)
+ const struct ctl_table *table)
{
struct net *net = container_of(head->set, struct net, sysctls);


--
2.43.0

2023-12-04 07:53:31

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 18/18] sysctl: constify standard sysctl tables

Recent changes in the sysctl allow sysctl tables to be put into .rodata.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
kernel/sysctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d60daa4e36fc..e48a60887c7e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1615,7 +1615,7 @@ int proc_do_static_key(const struct ctl_table *table, int write,
return ret;
}

-static struct ctl_table kern_table[] = {
+static const struct ctl_table kern_table[] = {
{
.procname = "panic",
.data = &panic_timeout,

--
2.43.0

2023-12-04 07:53:36

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 05/18] seccomp: constify ctl_table arguments of utility functions

In a future commit the proc_handlers themselves will change to
"const struct ctl_table". As a preparation for that adapt the internal
helpers.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
kernel/seccomp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 255999ba9190..a23672674ff6 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -2334,7 +2334,7 @@ static bool seccomp_actions_logged_from_names(u32 *actions_logged, char *names)
return true;
}

-static int read_actions_logged(struct ctl_table *ro_table, void *buffer,
+static int read_actions_logged(const struct ctl_table *ro_table, void *buffer,
size_t *lenp, loff_t *ppos)
{
char names[sizeof(seccomp_actions_avail)];
@@ -2352,7 +2352,7 @@ static int read_actions_logged(struct ctl_table *ro_table, void *buffer,
return proc_dostring(&table, 0, buffer, lenp, ppos);
}

-static int write_actions_logged(struct ctl_table *ro_table, void *buffer,
+static int write_actions_logged(const struct ctl_table *ro_table, void *buffer,
size_t *lenp, loff_t *ppos, u32 *actions_logged)
{
char names[sizeof(seccomp_actions_avail)];

--
2.43.0

2023-12-04 07:53:55

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 17/18] sysctl: make ctl_table sysctl_mount_point const

This is a first example on how to use const struct ctl_table.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
fs/proc/proc_sysctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index d09107a5b43f..f2b663e0be33 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -30,7 +30,7 @@ static const struct file_operations proc_sys_dir_file_operations;
static const struct inode_operations proc_sys_dir_operations;

/* Support for permanently empty directories */
-static struct ctl_table sysctl_mount_point[] = {
+static const struct ctl_table sysctl_mount_point[] = {
{ }
};


--
2.43.0

2023-12-04 07:54:02

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers

In a future commit the sysctl core will only use
"const struct ctl_table". As a preparation for that adapt all the proc
handlers.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
arch/arm64/kernel/armv8_deprecated.c | 2 +-
arch/arm64/kernel/fpsimd.c | 2 +-
arch/s390/appldata/appldata_base.c | 8 +--
arch/s390/kernel/debug.c | 2 +-
arch/s390/kernel/topology.c | 2 +-
arch/s390/mm/cmm.c | 6 +--
arch/x86/kernel/itmt.c | 2 +-
drivers/cdrom/cdrom.c | 4 +-
drivers/char/random.c | 4 +-
drivers/macintosh/mac_hid.c | 2 +-
drivers/net/vrf.c | 2 +-
drivers/parport/procfs.c | 12 ++---
fs/coredump.c | 2 +-
fs/dcache.c | 4 +-
fs/drop_caches.c | 2 +-
fs/exec.c | 4 +-
fs/file_table.c | 2 +-
fs/fs-writeback.c | 2 +-
fs/inode.c | 4 +-
fs/pipe.c | 2 +-
fs/quota/dquot.c | 2 +-
fs/xfs/xfs_sysctl.c | 6 +--
include/linux/ftrace.h | 4 +-
include/linux/mm.h | 8 +--
include/linux/perf_event.h | 6 +--
include/linux/security.h | 2 +-
include/linux/sysctl.h | 36 +++++++-------
include/linux/vmstat.h | 6 +--
include/linux/writeback.h | 2 +-
include/net/ndisc.h | 2 +-
include/net/neighbour.h | 6 +--
include/net/netfilter/nf_hooks_lwtunnel.h | 2 +-
ipc/ipc_sysctl.c | 8 +--
kernel/bpf/syscall.c | 4 +-
kernel/delayacct.c | 4 +-
kernel/events/callchain.c | 2 +-
kernel/events/core.c | 4 +-
kernel/fork.c | 2 +-
kernel/hung_task.c | 4 +-
kernel/kexec_core.c | 2 +-
kernel/kprobes.c | 2 +-
kernel/latencytop.c | 4 +-
kernel/pid_namespace.c | 2 +-
kernel/pid_sysctl.h | 2 +-
kernel/printk/internal.h | 2 +-
kernel/printk/printk.c | 2 +-
kernel/printk/sysctl.c | 5 +-
kernel/sched/core.c | 8 +--
kernel/sched/rt.c | 12 ++---
kernel/sched/topology.c | 2 +-
kernel/seccomp.c | 4 +-
kernel/stackleak.c | 2 +-
kernel/sysctl.c | 82 +++++++++++++++----------------
kernel/time/timer.c | 2 +-
kernel/trace/ftrace.c | 2 +-
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events_user.c | 2 +-
kernel/trace/trace_stack.c | 2 +-
kernel/umh.c | 2 +-
kernel/utsname_sysctl.c | 2 +-
kernel/watchdog.c | 15 +++---
mm/compaction.c | 8 +--
mm/hugetlb.c | 6 +--
mm/page-writeback.c | 18 +++----
mm/page_alloc.c | 22 ++++-----
mm/util.c | 12 ++---
mm/vmstat.c | 4 +-
net/bridge/br_netfilter_hooks.c | 2 +-
net/core/neighbour.c | 24 ++++-----
net/core/sysctl_net_core.c | 20 ++++----
net/ipv4/devinet.c | 6 +--
net/ipv4/route.c | 2 +-
net/ipv4/sysctl_net_ipv4.c | 33 +++++++------
net/ipv6/addrconf.c | 27 +++++-----
net/ipv6/ndisc.c | 4 +-
net/ipv6/route.c | 2 +-
net/ipv6/sysctl_net_ipv6.c | 4 +-
net/mpls/af_mpls.c | 4 +-
net/netfilter/ipvs/ip_vs_ctl.c | 16 +++---
net/netfilter/nf_conntrack_standalone.c | 2 +-
net/netfilter/nf_hooks_lwtunnel.c | 2 +-
net/netfilter/nf_log.c | 2 +-
net/phonet/sysctl.c | 2 +-
net/rds/tcp.c | 4 +-
net/sctp/sysctl.c | 28 +++++------
net/sunrpc/sysctl.c | 6 +--
net/sunrpc/xprtrdma/svc_rdma.c | 2 +-
security/apparmor/lsm.c | 2 +-
security/min_addr.c | 2 +-
security/yama/yama_lsm.c | 2 +-
90 files changed, 306 insertions(+), 302 deletions(-)

diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index dd6ce86d4332..a3085cb68852 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -504,7 +504,7 @@ static int update_insn_emulation_mode(struct insn_emulation *insn,
return ret;
}

-static int emulation_proc_handler(struct ctl_table *table, int write,
+static int emulation_proc_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 1559c706d32d..2b947031cd0e 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -555,7 +555,7 @@ static unsigned int find_supported_vector_length(enum vec_type type,

#if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL)

-static int vec_proc_do_default_vl(struct ctl_table *table, int write,
+static int vec_proc_do_default_vl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct vl_info *info = table->extra1;
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index c2978cb03b36..2bd253623be1 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -46,9 +46,9 @@
* /proc entries (sysctl)
*/
static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";
-static int appldata_timer_handler(struct ctl_table *ctl, int write,
+static int appldata_timer_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-static int appldata_interval_handler(struct ctl_table *ctl, int write,
+static int appldata_interval_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);

static struct ctl_table_header *appldata_sysctl_header;
@@ -199,7 +199,7 @@ static void __appldata_vtimer_setup(int cmd)
* Start/Stop timer, show status of timer (0 = not active, 1 = active)
*/
static int
-appldata_timer_handler(struct ctl_table *ctl, int write,
+appldata_timer_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int timer_active = appldata_timer_active;
@@ -232,7 +232,7 @@ appldata_timer_handler(struct ctl_table *ctl, int write,
* current timer interval.
*/
static int
-appldata_interval_handler(struct ctl_table *ctl, int write,
+appldata_interval_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int interval = appldata_interval;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 85328a0ef3b6..bce50ca75ea7 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -954,7 +954,7 @@ static int debug_active = 1;
* always allow read, allow write only if debug_stoppable is set or
* if debug_active is already off
*/
-static int s390dbf_procactive(struct ctl_table *table, int write,
+static int s390dbf_procactive(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (!write || debug_stoppable || !debug_active)
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 89e91b8ce842..1df3dc118696 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -600,7 +600,7 @@ static int __init topology_setup(char *str)
}
early_param("topology", topology_setup);

-static int topology_ctl_handler(struct ctl_table *ctl, int write,
+static int topology_ctl_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int enabled = topology_is_enabled();
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f8b13f247646..1d6749e095f7 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -243,7 +243,7 @@ static int cmm_skip_blanks(char *cp, char **endp)
return str != cp;
}

-static int cmm_pages_handler(struct ctl_table *ctl, int write,
+static int cmm_pages_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
long nr = cmm_get_pages();
@@ -262,7 +262,7 @@ static int cmm_pages_handler(struct ctl_table *ctl, int write,
return 0;
}

-static int cmm_timed_pages_handler(struct ctl_table *ctl, int write,
+static int cmm_timed_pages_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -282,7 +282,7 @@ static int cmm_timed_pages_handler(struct ctl_table *ctl, int write,
return 0;
}

-static int cmm_timeout_handler(struct ctl_table *ctl, int write,
+static int cmm_timeout_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
char buf[64], *p;
diff --git a/arch/x86/kernel/itmt.c b/arch/x86/kernel/itmt.c
index 9a7c03d47861..51b805c727fc 100644
--- a/arch/x86/kernel/itmt.c
+++ b/arch/x86/kernel/itmt.c
@@ -38,7 +38,7 @@ static bool __read_mostly sched_itmt_capable;
*/
unsigned int __read_mostly sysctl_sched_itmt_enabled;

-static int sched_itmt_update_handler(struct ctl_table *table, int write,
+static int sched_itmt_update_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
unsigned int old_sysctl;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index a5e07270e0d4..d0bd64129d43 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3473,7 +3473,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
return 0;
}

-static int cdrom_sysctl_info(struct ctl_table *ctl, int write,
+static int cdrom_sysctl_info(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int pos;
@@ -3586,7 +3586,7 @@ static void cdrom_update_settings(void)
mutex_unlock(&cdrom_mutex);
}

-static int cdrom_sysctl_handler(struct ctl_table *ctl, int write,
+static int cdrom_sysctl_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4a9c79391dee..04b224bffbdd 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1606,7 +1606,7 @@ static u8 sysctl_bootid[UUID_SIZE];
* UUID. The difference is in whether table->data is NULL; if it is,
* then a new UUID is generated and returned to the user.
*/
-static int proc_do_uuid(struct ctl_table *table, int write, void *buf,
+static int proc_do_uuid(const struct ctl_table *table, int write, void *buf,
size_t *lenp, loff_t *ppos)
{
u8 tmp_uuid[UUID_SIZE], *uuid;
@@ -1637,7 +1637,7 @@ static int proc_do_uuid(struct ctl_table *table, int write, void *buf,
}

/* The same as proc_dointvec, but writes don't change anything. */
-static int proc_do_rointvec(struct ctl_table *table, int write, void *buf,
+static int proc_do_rointvec(const struct ctl_table *table, int write, void *buf,
size_t *lenp, loff_t *ppos)
{
return write ? 0 : proc_dointvec(table, 0, buf, lenp, ppos);
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 1ae3539beff5..891047c8a110 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -182,7 +182,7 @@ static void mac_hid_stop_emulation(void)
mac_hid_destroy_emumouse();
}

-static int mac_hid_toggle_emumouse(struct ctl_table *table, int write,
+static int mac_hid_toggle_emumouse(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = table->data;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 66f8542f3b18..14c5efd234ad 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1908,7 +1908,7 @@ static int vrf_strict_mode_change(struct vrf_map *vmap, bool new_mode)
return res;
}

-static int vrf_shared_table_handler(struct ctl_table *table, int write,
+static int vrf_shared_table_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = (struct net *)table->extra1;
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index bd388560ed59..efa7c90e4234 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -33,7 +33,7 @@
#define PARPORT_MIN_SPINTIME_VALUE 1
#define PARPORT_MAX_SPINTIME_VALUE 1000

-static int do_active_device(struct ctl_table *table, int write,
+static int do_active_device(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport *port = (struct parport *)table->extra1;
@@ -70,7 +70,7 @@ static int do_active_device(struct ctl_table *table, int write,
}

#ifdef CONFIG_PARPORT_1284
-static int do_autoprobe(struct ctl_table *table, int write,
+static int do_autoprobe(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport_device_info *info = table->extra2;
@@ -113,7 +113,7 @@ static int do_autoprobe(struct ctl_table *table, int write,
}
#endif /* IEEE1284.3 support. */

-static int do_hardware_base_addr(struct ctl_table *table, int write,
+static int do_hardware_base_addr(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport *port = (struct parport *)table->extra1;
@@ -140,7 +140,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write,
return 0;
}

-static int do_hardware_irq(struct ctl_table *table, int write,
+static int do_hardware_irq(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport *port = (struct parport *)table->extra1;
@@ -167,7 +167,7 @@ static int do_hardware_irq(struct ctl_table *table, int write,
return 0;
}

-static int do_hardware_dma(struct ctl_table *table, int write,
+static int do_hardware_dma(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport *port = (struct parport *)table->extra1;
@@ -194,7 +194,7 @@ static int do_hardware_dma(struct ctl_table *table, int write,
return 0;
}

-static int do_hardware_modes(struct ctl_table *table, int write,
+static int do_hardware_modes(const struct ctl_table *table, int write,
void *result, size_t *lenp, loff_t *ppos)
{
struct parport *port = (struct parport *)table->extra1;
diff --git a/fs/coredump.c b/fs/coredump.c
index 9d235fa14ab9..51283a671921 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -949,7 +949,7 @@ void validate_coredump_safety(void)
}
}

-static int proc_dostring_coredump(struct ctl_table *table, int write,
+static int proc_dostring_coredump(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int error = proc_dostring(table, write, buffer, lenp, ppos);
diff --git a/fs/dcache.c b/fs/dcache.c
index c82ae731df9a..0ea86ad6cedf 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -174,8 +174,8 @@ static long get_nr_dentry_negative(void)
return sum < 0 ? 0 : sum;
}

-static int proc_nr_dentry(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int proc_nr_dentry(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
dentry_stat.nr_dentry = get_nr_dentry();
dentry_stat.nr_unused = get_nr_dentry_unused();
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index b9575957a7c2..d45ef541d848 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -48,7 +48,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
iput(toput_inode);
}

-int drop_caches_sysctl_handler(struct ctl_table *table, int write,
+int drop_caches_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
int ret;
diff --git a/fs/exec.c b/fs/exec.c
index 4aa19b24f281..e3d124206020 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2145,8 +2145,8 @@ COMPAT_SYSCALL_DEFINE5(execveat, int, fd,

#ifdef CONFIG_SYSCTL

-static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int proc_dointvec_minmax_coredump(const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
{
int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);

diff --git a/fs/file_table.c b/fs/file_table.c
index de4a2915bfd4..bab68d672e33 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -109,7 +109,7 @@ EXPORT_SYMBOL_GPL(get_max_files);
/*
* Handle nr_files sysctl
*/
-static int proc_nr_files(struct ctl_table *table, int write, void *buffer,
+static int proc_nr_files(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
files_stat.nr_files = get_nr_files();
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1767493dffda..a66c9d0556dc 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2379,7 +2379,7 @@ static int __init start_dirtytime_writeback(void)
}
__initcall(start_dirtytime_writeback);

-int dirtytime_interval_handler(struct ctl_table *table, int write,
+int dirtytime_interval_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/fs/inode.c b/fs/inode.c
index f238d987dec9..76cf31ef25c8 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -106,8 +106,8 @@ long get_nr_dirty_inodes(void)
*/
static struct inodes_stat_t inodes_stat;

-static int proc_nr_inodes(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int proc_nr_inodes(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
inodes_stat.nr_inodes = get_nr_inodes();
inodes_stat.nr_unused = get_nr_inodes_unused();
diff --git a/fs/pipe.c b/fs/pipe.c
index 804a7d789452..1dc57b4a283a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1468,7 +1468,7 @@ static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
return 0;
}

-static int proc_dopipe_max_size(struct ctl_table *table, int write,
+static int proc_dopipe_max_size(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_douintvec(table, write, buffer, lenp, ppos,
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 58b5de081b57..d1a6511e48dc 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2887,7 +2887,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
};
EXPORT_SYMBOL(dquot_quotactl_sysfile_ops);

-static int do_proc_dqstats(struct ctl_table *table, int write,
+static int do_proc_dqstats(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
unsigned int type = (unsigned long *)table->data - dqstats.stat;
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index fade33735393..2c5adc88a830 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -11,7 +11,7 @@ static struct ctl_table_header *xfs_table_header;
#ifdef CONFIG_PROC_FS
STATIC int
xfs_stats_clear_proc_handler(
- struct ctl_table *ctl,
+ const struct ctl_table *ctl,
int write,
void *buffer,
size_t *lenp,
@@ -31,7 +31,7 @@ xfs_stats_clear_proc_handler(

STATIC int
xfs_panic_mask_proc_handler(
- struct ctl_table *ctl,
+ const struct ctl_table *ctl,
int write,
void *buffer,
size_t *lenp,
@@ -52,7 +52,7 @@ xfs_panic_mask_proc_handler(

STATIC int
xfs_deprecated_dointvec_minmax(
- struct ctl_table *ctl,
+ const struct ctl_table *ctl,
int write,
void *buffer,
size_t *lenp,
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e8921871ef9a..3e10fe61c2bf 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -470,7 +470,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs,

extern int stack_tracer_enabled;

-int stack_trace_sysctl(struct ctl_table *table, int write, void *buffer,
+int stack_trace_sysctl(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);

/* DO NOT MODIFY THIS VARIABLE DIRECTLY! */
@@ -1157,7 +1157,7 @@ extern int tracepoint_printk;
extern void disable_trace_on_warning(void);
extern int __disable_trace_on_warning;

-int tracepoint_printk_sysctl(struct ctl_table *table, int write,
+int tracepoint_printk_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);

#else /* CONFIG_TRACING */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 418d26608ece..e95efc7bdc85 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -202,11 +202,11 @@ extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern unsigned long sysctl_overcommit_kbytes;

-int overcommit_ratio_handler(struct ctl_table *, int, void *, size_t *,
+int overcommit_ratio_handler(const struct ctl_table *, int, void *, size_t *,
loff_t *);
-int overcommit_kbytes_handler(struct ctl_table *, int, void *, size_t *,
+int overcommit_kbytes_handler(const struct ctl_table *, int, void *, size_t *,
loff_t *);
-int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *,
+int overcommit_policy_handler(const struct ctl_table *, int, void *, size_t *,
loff_t *);

#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
@@ -3805,7 +3805,7 @@ extern bool process_shares_mm(struct task_struct *p, struct mm_struct *mm);

#ifdef CONFIG_SYSCTL
extern int sysctl_drop_caches;
-int drop_caches_sysctl_handler(struct ctl_table *, int, void *, size_t *,
+int drop_caches_sysctl_handler(const struct ctl_table *, int, void *, size_t *,
loff_t *);
#endif

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 5547ba68e6e4..a48c183cfbe0 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1578,11 +1578,11 @@ extern int sysctl_perf_cpu_time_max_percent;

extern void perf_sample_event_took(u64 sample_len_ns);

-int perf_event_max_sample_rate_handler(struct ctl_table *table, int write,
+int perf_event_max_sample_rate_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
+int perf_cpu_time_max_percent_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-int perf_event_max_stack_handler(struct ctl_table *table, int write,
+int perf_event_max_stack_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);

/* Access to perf_event_open(2) syscall. */
diff --git a/include/linux/security.h b/include/linux/security.h
index 1d1df326c881..d5aca07d5e1d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -223,7 +223,7 @@ struct request_sock;
#define LSM_UNSAFE_NO_NEW_PRIVS 4

#ifdef CONFIG_MMU
-extern int mmap_min_addr_handler(struct ctl_table *table, int write,
+extern int mmap_min_addr_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
#endif

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 56b89e5294e9..ada36ef8cecb 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -61,31 +61,31 @@ extern const int sysctl_vals[];

extern const unsigned long sysctl_long_vals[];

-typedef int proc_handler(struct ctl_table *ctl, int write, void *buffer,
+typedef int proc_handler(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);

-int proc_dostring(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_dobool(struct ctl_table *table, int write, void *buffer,
+int proc_dostring(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_dobool(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-int proc_dointvec(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_douintvec(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_dointvec_minmax(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_douintvec_minmax(struct ctl_table *table, int write, void *buffer,
+int proc_dointvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_douintvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_dointvec_minmax(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_douintvec_minmax(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-int proc_dou8vec_minmax(struct ctl_table *table, int write, void *buffer,
+int proc_dou8vec_minmax(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-int proc_dointvec_jiffies(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_dointvec_ms_jiffies_minmax(struct ctl_table *table, int write,
+int proc_dointvec_jiffies(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-int proc_dointvec_userhz_jiffies(struct ctl_table *, int, void *, size_t *,
+int proc_dointvec_userhz_jiffies(const struct ctl_table *, int, void *, size_t *,
loff_t *);
-int proc_dointvec_ms_jiffies(struct ctl_table *, int, void *, size_t *,
+int proc_dointvec_ms_jiffies(const struct ctl_table *, int, void *, size_t *,
loff_t *);
-int proc_doulongvec_minmax(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int, void *,
+int proc_doulongvec_minmax(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int, void *,
size_t *, loff_t *);
-int proc_do_large_bitmap(struct ctl_table *, int, void *, size_t *, loff_t *);
-int proc_do_static_key(struct ctl_table *table, int write, void *buffer,
+int proc_do_large_bitmap(const struct ctl_table *, int, void *, size_t *, loff_t *);
+int proc_do_static_key(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);

/*
@@ -243,7 +243,7 @@ extern struct ctl_table_header *register_sysctl_mount_point(const char *path);

void do_sysctl_args(void);
bool sysctl_is_alias(char *param);
-int do_proc_douintvec(struct ctl_table *table, int write,
+int do_proc_douintvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp,
unsigned int *valp,
@@ -293,7 +293,7 @@ static inline bool sysctl_is_alias(char *param)
}
#endif /* CONFIG_SYSCTL */

-int sysctl_max_threads(struct ctl_table *table, int write, void *buffer,
+int sysctl_max_threads(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);

#endif /* _LINUX_SYSCTL_H */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index fed855bae6d8..267b56b7c56a 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -17,7 +17,7 @@ extern int sysctl_stat_interval;
#define DISABLE_NUMA_STAT 0
extern int sysctl_vm_numa_stat;
DECLARE_STATIC_KEY_TRUE(vm_numa_stat_key);
-int sysctl_vm_numa_stat_handler(struct ctl_table *table, int write,
+int sysctl_vm_numa_stat_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos);
#endif

@@ -301,8 +301,8 @@ void cpu_vm_stats_fold(int cpu);
void refresh_zone_stat_thresholds(void);

struct ctl_table;
-int vmstat_refresh(struct ctl_table *, int write, void *buffer, size_t *lenp,
- loff_t *ppos);
+int vmstat_refresh(const struct ctl_table *, int write, void *buffer,
+ size_t *lenp, loff_t *ppos);

void drain_zonestat(struct zone *zone, struct per_cpu_zonestat *);

diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 083387c00f0c..8dc4d16bb7c3 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -344,7 +344,7 @@ extern unsigned int dirty_expire_interval;
extern unsigned int dirtytime_expire_interval;
extern int laptop_mode;

-int dirtytime_interval_handler(struct ctl_table *table, int write,
+int dirtytime_interval_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);

void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 9bbdf6eaa942..7a533d5b1d59 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -486,7 +486,7 @@ void igmp6_event_report(struct sk_buff *skb);


#ifdef CONFIG_SYSCTL
-int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
+int ndisc_ifinfo_sysctl_change(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
#endif

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 0d28172193fa..a44f262a7384 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -412,12 +412,12 @@ void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *,
void *neigh_seq_next(struct seq_file *, void *, loff_t *);
void neigh_seq_stop(struct seq_file *, void *);

-int neigh_proc_dointvec(struct ctl_table *ctl, int write,
+int neigh_proc_dointvec(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
+int neigh_proc_dointvec_jiffies(const struct ctl_table *ctl, int write,
void *buffer,
size_t *lenp, loff_t *ppos);
-int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
+int neigh_proc_dointvec_ms_jiffies(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);

int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
diff --git a/include/net/netfilter/nf_hooks_lwtunnel.h b/include/net/netfilter/nf_hooks_lwtunnel.h
index 52e27920f829..cef7a4eb8f97 100644
--- a/include/net/netfilter/nf_hooks_lwtunnel.h
+++ b/include/net/netfilter/nf_hooks_lwtunnel.h
@@ -2,6 +2,6 @@
#include <linux/types.h>

#ifdef CONFIG_SYSCTL
-int nf_hooks_lwtunnel_sysctl_handler(struct ctl_table *table, int write,
+int nf_hooks_lwtunnel_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
#endif
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 55d6b9f1e508..d876f96f5992 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -16,8 +16,8 @@
#include <linux/slab.h>
#include "util.h"

-static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int proc_ipc_dointvec_minmax_orphans(const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
{
struct ipc_namespace *ns =
container_of(table->data, struct ipc_namespace, shm_rmid_forced);
@@ -32,7 +32,7 @@ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
return err;
}

-static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
+static int proc_ipc_auto_msgmni(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table ipc_table;
@@ -47,7 +47,7 @@ static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
}

-static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
+static int proc_ipc_sem_dointvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ipc_namespace *ns =
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0ed286b8a0f0..f13daa0916bf 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5652,7 +5652,7 @@ const struct bpf_prog_ops bpf_syscall_prog_ops = {
};

#ifdef CONFIG_SYSCTL
-static int bpf_stats_handler(struct ctl_table *table, int write,
+static int bpf_stats_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct static_key *key = (struct static_key *)table->data;
@@ -5687,7 +5687,7 @@ void __weak unpriv_ebpf_notify(int new_state)
{
}

-static int bpf_unpriv_handler(struct ctl_table *table, int write,
+static int bpf_unpriv_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret, unpriv_enable = *(int *)table->data;
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 6f0c358e73d8..939c57c30a79 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -44,8 +44,8 @@ void delayacct_init(void)
}

#ifdef CONFIG_PROC_SYSCTL
-static int sysctl_delayacct(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int sysctl_delayacct(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int state = delayacct_on;
struct ctl_table t;
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index 1273be84392c..bd5699f869c3 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -229,7 +229,7 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
* Used for sysctl_perf_event_max_stack and
* sysctl_perf_event_max_contexts_per_stack.
*/
-int perf_event_max_stack_handler(struct ctl_table *table, int write,
+int perf_event_max_stack_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *value = table->data;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index b704d83a28b2..cbf0f4dfa4af 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -450,7 +450,7 @@ static void update_perf_cpu_limits(void)

static bool perf_rotate_context(struct perf_cpu_pmu_context *cpc);

-int perf_event_max_sample_rate_handler(struct ctl_table *table, int write,
+int perf_event_max_sample_rate_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
@@ -474,7 +474,7 @@ int perf_event_max_sample_rate_handler(struct ctl_table *table, int write,

int sysctl_perf_cpu_time_max_percent __read_mostly = DEFAULT_CPU_TIME_MAX_PERCENT;

-int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
+int perf_cpu_time_max_percent_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
diff --git a/kernel/fork.c b/kernel/fork.c
index 10917c3e1f03..ce4b220e6ae2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -3528,7 +3528,7 @@ int unshare_files(void)
return 0;
}

-int sysctl_max_threads(struct ctl_table *table, int write,
+int sysctl_max_threads(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 9a24574988d2..b310a500b7b2 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -238,8 +238,8 @@ static long hung_timeout_jiffies(unsigned long last_checked,
/*
* Process updating of timeout sysctl
*/
-static int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
- void *buffer,
+static int proc_dohung_task_timeout_secs(const struct ctl_table *table,
+ int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index be5642a4ec49..7bb9bf85f058 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -928,7 +928,7 @@ struct kimage *kexec_crash_image;
static int kexec_load_disabled;

#ifdef CONFIG_SYSCTL
-static int kexec_limit_handler(struct ctl_table *table, int write,
+static int kexec_limit_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct kexec_load_limit *limit = table->data;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d5a0ee40bf66..9e160dd23e61 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -939,7 +939,7 @@ static void unoptimize_all_kprobes(void)

static DEFINE_MUTEX(kprobe_sysctl_mutex);
static int sysctl_kprobes_optimization;
-static int proc_kprobes_optimization_handler(struct ctl_table *table,
+static int proc_kprobes_optimization_handler(const struct ctl_table *table,
int write, void *buffer,
size_t *length, loff_t *ppos)
{
diff --git a/kernel/latencytop.c b/kernel/latencytop.c
index 781249098cb6..e09b935b822c 100644
--- a/kernel/latencytop.c
+++ b/kernel/latencytop.c
@@ -65,8 +65,8 @@ static struct latency_record latency_record[MAXLR];
int latencytop_enabled;

#ifdef CONFIG_SYSCTL
-static int sysctl_latencytop(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int sysctl_latencytop(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int err;

diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 3028b2218aa4..a1926cf01cfb 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -276,7 +276,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
}

#ifdef CONFIG_CHECKPOINT_RESTORE
-static int pid_ns_ctl_handler(struct ctl_table *table, int write,
+static int pid_ns_ctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct pid_namespace *pid_ns = task_active_pid_ns(current);
diff --git a/kernel/pid_sysctl.h b/kernel/pid_sysctl.h
index 2ee41a3a1dfd..a1b47ad10ebc 100644
--- a/kernel/pid_sysctl.h
+++ b/kernel/pid_sysctl.h
@@ -5,7 +5,7 @@
#include <linux/pid_namespace.h>

#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE)
-static int pid_mfd_noexec_dointvec_minmax(struct ctl_table *table,
+static int pid_mfd_noexec_dointvec_minmax(const struct ctl_table *table,
int write, void *buf, size_t *lenp, loff_t *ppos)
{
struct pid_namespace *ns = task_active_pid_ns(current);
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 6c2afee5ef62..19dcc5832651 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -8,7 +8,7 @@

#if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)
void __init printk_sysctl_init(void);
-int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
+int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
#else
#define printk_sysctl_init() do { } while (0)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index f2444b581e16..964f0614767b 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -197,7 +197,7 @@ __setup("printk.devkmsg=", control_devkmsg);

char devkmsg_log_str[DEVKMSG_STR_MAX_SIZE] = "ratelimit";
#if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)
-int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
+int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
char old_str[DEVKMSG_STR_MAX_SIZE];
diff --git a/kernel/printk/sysctl.c b/kernel/printk/sysctl.c
index c228343eeb97..187b27981111 100644
--- a/kernel/printk/sysctl.c
+++ b/kernel/printk/sysctl.c
@@ -11,8 +11,9 @@

static const int ten_thousand = 10000;

-static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int proc_dointvec_minmax_sysadmin(const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp,
+ loff_t *ppos)
{
if (write && !capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a708d225c28e..a36419645a62 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1813,7 +1813,7 @@ static void uclamp_sync_util_min_rt_default(void)
uclamp_update_util_min_rt_default(p);
}

-static int sysctl_sched_uclamp_handler(struct ctl_table *table, int write,
+static int sysctl_sched_uclamp_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
bool update_root_tg = false;
@@ -4570,7 +4570,7 @@ static void reset_memory_tiering(void)
}
}

-static int sysctl_numa_balancing(struct ctl_table *table, int write,
+static int sysctl_numa_balancing(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
@@ -4639,8 +4639,8 @@ static int __init setup_schedstats(char *str)
__setup("schedstats=", setup_schedstats);

#ifdef CONFIG_PROC_SYSCTL
-static int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int sysctl_schedstats(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
int err;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 6aaf0a3d6081..a972c9601a39 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -26,9 +26,9 @@ int sysctl_sched_rt_runtime = 950000;

#ifdef CONFIG_SYSCTL
static int sysctl_sched_rr_timeslice = (MSEC_PER_SEC * RR_TIMESLICE) / HZ;
-static int sched_rt_handler(struct ctl_table *table, int write, void *buffer,
+static int sched_rt_handler(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-static int sched_rr_handler(struct ctl_table *table, int write, void *buffer,
+static int sched_rr_handler(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
static struct ctl_table sched_rt_sysctls[] = {
{
@@ -2962,8 +2962,8 @@ static void sched_rt_do_global(void)
raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
}

-static int sched_rt_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int sched_rt_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int old_period, old_runtime;
static DEFINE_MUTEX(mutex);
@@ -3001,8 +3001,8 @@ static int sched_rt_handler(struct ctl_table *table, int write, void *buffer,
return ret;
}

-static int sched_rr_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int sched_rr_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
static DEFINE_MUTEX(mutex);
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 10d1391e7416..3e3b69314e30 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -285,7 +285,7 @@ void rebuild_sched_domains_energy(void)
}

#ifdef CONFIG_PROC_SYSCTL
-static int sched_energy_aware_handler(struct ctl_table *table, int write,
+static int sched_energy_aware_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret, state;
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index a23672674ff6..95aba3cf6b84 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -2413,8 +2413,8 @@ static void audit_actions_logged(u32 actions_logged, u32 old_actions_logged,
return audit_seccomp_actions_logged(new, old, !ret);
}

-static int seccomp_actions_logged_handler(struct ctl_table *ro_table, int write,
- void *buffer, size_t *lenp,
+static int seccomp_actions_logged_handler(const struct ctl_table *ro_table,
+ int write, void *buffer, size_t *lenp,
loff_t *ppos)
{
int ret;
diff --git a/kernel/stackleak.c b/kernel/stackleak.c
index b292e5ca0b7d..95e4a9332599 100644
--- a/kernel/stackleak.c
+++ b/kernel/stackleak.c
@@ -21,7 +21,7 @@
static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass);

#ifdef CONFIG_SYSCTL
-static int stack_erasing_sysctl(struct ctl_table *table, int write,
+static int stack_erasing_sysctl(const struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int ret = 0;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 157f7ce2942d..d60daa4e36fc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -205,7 +205,7 @@ static int _proc_do_string(char *data, int maxlen, int write,
return 0;
}

-static void warn_sysctl_write(struct ctl_table *table)
+static void warn_sysctl_write(const struct ctl_table *table)
{
pr_warn_once("%s wrote to %s when file position was not 0!\n"
"This will not be supported in the future. To silence this\n"
@@ -223,7 +223,7 @@ static void warn_sysctl_write(struct ctl_table *table)
* handlers can ignore the return value.
*/
static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
- struct ctl_table *table)
+ const struct ctl_table *table)
{
if (!*ppos)
return false;
@@ -256,7 +256,7 @@ static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
*
* Returns 0 on success.
*/
-int proc_dostring(struct ctl_table *table, int write,
+int proc_dostring(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (write)
@@ -468,7 +468,7 @@ static int do_proc_douintvec_conv(unsigned long *lvalp,

static const char proc_wspace_sep[] = { ' ', '\t', '\n' };

-static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
+static int __do_proc_dointvec(void *tbl_data, const struct ctl_table *table,
int write, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
@@ -541,7 +541,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
return err;
}

-static int do_proc_dointvec(struct ctl_table *table, int write,
+static int do_proc_dointvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
int write, void *data),
@@ -552,7 +552,7 @@ static int do_proc_dointvec(struct ctl_table *table, int write,
}

static int do_proc_douintvec_w(unsigned int *tbl_data,
- struct ctl_table *table,
+ const struct ctl_table *table,
void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp,
@@ -639,7 +639,7 @@ static int do_proc_douintvec_r(unsigned int *tbl_data, void *buffer,
return err;
}

-static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
+static int __do_proc_douintvec(void *tbl_data, const struct ctl_table *table,
int write, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp,
@@ -675,7 +675,7 @@ static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
}

-int do_proc_douintvec(struct ctl_table *table, int write,
+int do_proc_douintvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp,
unsigned int *valp,
@@ -702,7 +702,7 @@ int do_proc_douintvec(struct ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_dobool(struct ctl_table *table, int write, void *buffer,
+int proc_dobool(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct ctl_table tmp;
@@ -739,7 +739,7 @@ int proc_dobool(struct ctl_table *table, int write, void *buffer,
*
* Returns 0 on success.
*/
-int proc_dointvec(struct ctl_table *table, int write, void *buffer,
+int proc_dointvec(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
@@ -758,7 +758,7 @@ int proc_dointvec(struct ctl_table *table, int write, void *buffer,
*
* Returns 0 on success.
*/
-int proc_douintvec(struct ctl_table *table, int write, void *buffer,
+int proc_douintvec(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
return do_proc_douintvec(table, write, buffer, lenp, ppos,
@@ -769,7 +769,7 @@ int proc_douintvec(struct ctl_table *table, int write, void *buffer,
* Taint values can only be increased
* This means we can safely use a temporary.
*/
-static int proc_taint(struct ctl_table *table, int write,
+static int proc_taint(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
@@ -864,7 +864,7 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
*
* Returns 0 on success or -EINVAL on write when the range check fails.
*/
-int proc_dointvec_minmax(struct ctl_table *table, int write,
+int proc_dointvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct do_proc_dointvec_minmax_conv_param param = {
@@ -933,7 +933,7 @@ static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
*
* Returns 0 on success or -ERANGE on write when the range check fails.
*/
-int proc_douintvec_minmax(struct ctl_table *table, int write,
+int proc_douintvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct do_proc_douintvec_minmax_conv_param param = {
@@ -961,7 +961,7 @@ int proc_douintvec_minmax(struct ctl_table *table, int write,
*
* Returns 0 on success or an error on write when the range check fails.
*/
-int proc_dou8vec_minmax(struct ctl_table *table, int write,
+int proc_dou8vec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table tmp;
@@ -1004,7 +1004,7 @@ int proc_dou8vec_minmax(struct ctl_table *table, int write,
EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);

#ifdef CONFIG_MAGIC_SYSRQ
-static int sysrq_sysctl_handler(struct ctl_table *table, int write,
+static int sysrq_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int tmp, ret;
@@ -1023,7 +1023,7 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write,
}
#endif

-static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
+static int __do_proc_doulongvec_minmax(void *data, const struct ctl_table *table,
int write, void *buffer, size_t *lenp, loff_t *ppos,
unsigned long convmul, unsigned long convdiv)
{
@@ -1096,7 +1096,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
return err;
}

-static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
+static int do_proc_doulongvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul,
unsigned long convdiv)
{
@@ -1120,7 +1120,7 @@ static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_doulongvec_minmax(struct ctl_table *table, int write,
+int proc_doulongvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
@@ -1143,7 +1143,7 @@ int proc_doulongvec_minmax(struct ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
+int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_doulongvec_minmax(table, write, buffer,
@@ -1264,14 +1264,14 @@ static int do_proc_dointvec_ms_jiffies_minmax_conv(bool *negp, unsigned long *lv
*
* Returns 0 on success.
*/
-int proc_dointvec_jiffies(struct ctl_table *table, int write,
+int proc_dointvec_jiffies(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table,write,buffer,lenp,ppos,
do_proc_dointvec_jiffies_conv,NULL);
}

-int proc_dointvec_ms_jiffies_minmax(struct ctl_table *table, int write,
+int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct do_proc_dointvec_minmax_conv_param param = {
@@ -1297,7 +1297,7 @@ int proc_dointvec_ms_jiffies_minmax(struct ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
+int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, write, buffer, lenp, ppos,
@@ -1320,14 +1320,14 @@ int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
*
* Returns 0 on success.
*/
-int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, void *buffer,
+int proc_dointvec_ms_jiffies(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, write, buffer, lenp, ppos,
do_proc_dointvec_ms_jiffies_conv, NULL);
}

-static int proc_do_cad_pid(struct ctl_table *table, int write, void *buffer,
+static int proc_do_cad_pid(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct pid *new_pid;
@@ -1366,7 +1366,7 @@ static int proc_do_cad_pid(struct ctl_table *table, int write, void *buffer,
*
* Returns 0 on success.
*/
-int proc_do_large_bitmap(struct ctl_table *table, int write,
+int proc_do_large_bitmap(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int err = 0;
@@ -1498,85 +1498,85 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,

#else /* CONFIG_PROC_SYSCTL */

-int proc_dostring(struct ctl_table *table, int write,
+int proc_dostring(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dobool(struct ctl_table *table, int write,
+int proc_dobool(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec(struct ctl_table *table, int write,
+int proc_dointvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_douintvec(struct ctl_table *table, int write,
+int proc_douintvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec_minmax(struct ctl_table *table, int write,
+int proc_dointvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_douintvec_minmax(struct ctl_table *table, int write,
+int proc_douintvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dou8vec_minmax(struct ctl_table *table, int write,
+int proc_dou8vec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec_jiffies(struct ctl_table *table, int write,
+int proc_dointvec_jiffies(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec_ms_jiffies_minmax(struct ctl_table *table, int write,
+int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
+int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
+int proc_dointvec_ms_jiffies(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_doulongvec_minmax(struct ctl_table *table, int write,
+int proc_doulongvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
+int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}

-int proc_do_large_bitmap(struct ctl_table *table, int write,
+int proc_do_large_bitmap(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
@@ -1585,7 +1585,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
#endif /* CONFIG_PROC_SYSCTL */

#if defined(CONFIG_SYSCTL)
-int proc_do_static_key(struct ctl_table *table, int write,
+int proc_do_static_key(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct static_key *key = (struct static_key *)table->data;
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 63a8ce7177dd..cb8b93fec895 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -237,7 +237,7 @@ static void timers_update_migration(void)
}

#ifdef CONFIG_SYSCTL
-static int timer_migration_handler(struct ctl_table *table, int write,
+static int timer_migration_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8de8bec5f366..6334a2268acf 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -8213,7 +8213,7 @@ static bool is_permanent_ops_registered(void)
}

static int
-ftrace_enable_sysctl(struct ctl_table *table, int write,
+ftrace_enable_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret = -ENODEV;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9aebf904ff97..380b9cb7210a 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2972,7 +2972,7 @@ static void output_printk(struct trace_event_buffer *fbuffer)
raw_spin_unlock_irqrestore(&tracepoint_iter_lock, flags);
}

-int tracepoint_printk_sysctl(struct ctl_table *table, int write,
+int tracepoint_printk_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index 9365ce407426..4331d3bcae61 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -2724,7 +2724,7 @@ static int create_user_tracefs(void)
return -ENODEV;
}

-static int set_max_user_events_sysctl(struct ctl_table *table, int write,
+static int set_max_user_events_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 5a48dba912ea..7f9572a37333 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -514,7 +514,7 @@ static const struct file_operations stack_trace_filter_fops = {
#endif /* CONFIG_DYNAMIC_FTRACE */

int
-stack_trace_sysctl(struct ctl_table *table, int write, void *buffer,
+stack_trace_sysctl(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
int was_enabled;
diff --git a/kernel/umh.c b/kernel/umh.c
index 1b13c5d34624..112d3fea3869 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -495,7 +495,7 @@ int call_usermodehelper(const char *path, char **argv, char **envp, int wait)
EXPORT_SYMBOL(call_usermodehelper);

#if defined(CONFIG_SYSCTL)
-static int proc_cap_handler(struct ctl_table *table, int write,
+static int proc_cap_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index 46590d4addc8..f074a92eae78 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -30,7 +30,7 @@ static void *get_uts(const struct ctl_table *table)
* Special case of dostring for the UTS structure. This has locks
* to observe. Should this be in kernel/sys.c ????
*/
-static int proc_do_uts_string(struct ctl_table *table, int write,
+static int proc_do_uts_string(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table uts_table;
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 0fe72e89627d..4c48f543bcd2 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -745,8 +745,9 @@ static void proc_watchdog_update(void)
* -------------------|----------------------------------|-------------------------------
* proc_soft_watchdog | watchdog_softlockup_user_enabled | WATCHDOG_SOFTOCKUP_ENABLED
*/
-static int proc_watchdog_common(int which, struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int proc_watchdog_common(int which, const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp,
+ loff_t *ppos)
{
int err, old, *param = table->data;

@@ -772,7 +773,7 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
/*
* /proc/sys/kernel/watchdog
*/
-static int proc_watchdog(struct ctl_table *table, int write,
+static int proc_watchdog(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return proc_watchdog_common(WATCHDOG_HARDLOCKUP_ENABLED |
@@ -783,7 +784,7 @@ static int proc_watchdog(struct ctl_table *table, int write,
/*
* /proc/sys/kernel/nmi_watchdog
*/
-static int proc_nmi_watchdog(struct ctl_table *table, int write,
+static int proc_nmi_watchdog(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (!watchdog_hardlockup_available && write)
@@ -795,7 +796,7 @@ static int proc_nmi_watchdog(struct ctl_table *table, int write,
/*
* /proc/sys/kernel/soft_watchdog
*/
-static int proc_soft_watchdog(struct ctl_table *table, int write,
+static int proc_soft_watchdog(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
return proc_watchdog_common(WATCHDOG_SOFTOCKUP_ENABLED,
@@ -805,7 +806,7 @@ static int proc_soft_watchdog(struct ctl_table *table, int write,
/*
* /proc/sys/kernel/watchdog_thresh
*/
-static int proc_watchdog_thresh(struct ctl_table *table, int write,
+static int proc_watchdog_thresh(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int err, old;
@@ -828,7 +829,7 @@ static int proc_watchdog_thresh(struct ctl_table *table, int write,
* user to specify a mask that will include cpus that have not yet
* been brought online, if desired.
*/
-static int proc_watchdog_cpumask(struct ctl_table *table, int write,
+static int proc_watchdog_cpumask(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int err;
diff --git a/mm/compaction.c b/mm/compaction.c
index 01ba298739dd..87fe40cc76a8 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -2842,8 +2842,8 @@ static void compact_nodes(void)
compact_node(nid);
}

-static int compaction_proactiveness_sysctl_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int compaction_proactiveness_sysctl_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
int rc, nid;

@@ -2872,7 +2872,7 @@ static int compaction_proactiveness_sysctl_handler(struct ctl_table *table, int
* This is the entry point for compacting all nodes via
* /proc/sys/vm/compact_memory
*/
-static int sysctl_compaction_handler(struct ctl_table *table, int write,
+static int sysctl_compaction_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
int ret;
@@ -3183,7 +3183,7 @@ static int kcompactd_cpu_online(unsigned int cpu)
return 0;
}

-static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
+static int proc_dointvec_minmax_warn_RT_change(const struct ctl_table *table,
int write, void *buffer, size_t *lenp, loff_t *ppos)
{
int ret, old;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 2df21a295359..babb70d990aa 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -4874,7 +4874,7 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
return ret;
}

-static int hugetlb_sysctl_handler(struct ctl_table *table, int write,
+static int hugetlb_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{

@@ -4883,7 +4883,7 @@ static int hugetlb_sysctl_handler(struct ctl_table *table, int write,
}

#ifdef CONFIG_NUMA
-static int hugetlb_mempolicy_sysctl_handler(struct ctl_table *table, int write,
+static int hugetlb_mempolicy_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
return hugetlb_sysctl_handler_common(true, table, write,
@@ -4891,7 +4891,7 @@ static int hugetlb_mempolicy_sysctl_handler(struct ctl_table *table, int write,
}
#endif /* CONFIG_NUMA */

-static int hugetlb_overcommit_handler(struct ctl_table *table, int write,
+static int hugetlb_overcommit_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
struct hstate *h = &default_hstate;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index ee2fd6a6af40..52f28e6f7a33 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -493,8 +493,8 @@ bool node_dirty_ok(struct pglist_data *pgdat)
}

#ifdef CONFIG_SYSCTL
-static int dirty_background_ratio_handler(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int dirty_background_ratio_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;

@@ -504,8 +504,8 @@ static int dirty_background_ratio_handler(struct ctl_table *table, int write,
return ret;
}

-static int dirty_background_bytes_handler(struct ctl_table *table, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int dirty_background_bytes_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;

@@ -515,8 +515,8 @@ static int dirty_background_bytes_handler(struct ctl_table *table, int write,
return ret;
}

-static int dirty_ratio_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+static int dirty_ratio_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int old_ratio = vm_dirty_ratio;
int ret;
@@ -529,7 +529,7 @@ static int dirty_ratio_handler(struct ctl_table *table, int write, void *buffer,
return ret;
}

-static int dirty_bytes_handler(struct ctl_table *table, int write,
+static int dirty_bytes_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
unsigned long old_bytes = vm_dirty_bytes;
@@ -2132,8 +2132,8 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb)
/*
* sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
*/
-static int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int dirty_writeback_centisecs_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
unsigned int old_interval = dirty_writeback_interval;
int ret;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 733732e7e0ba..5eb29269d39e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4985,7 +4985,7 @@ static char numa_zonelist_order[] = "Node";
/*
* sysctl handler for numa_zonelist_order
*/
-static int numa_zonelist_order_handler(struct ctl_table *table, int write,
+static int numa_zonelist_order_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
if (write)
@@ -5978,8 +5978,8 @@ postcore_initcall(init_per_zone_wmark_min)
* that we can call two helper functions whenever min_free_kbytes
* changes.
*/
-static int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int min_free_kbytes_sysctl_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
int rc;

@@ -5994,8 +5994,8 @@ static int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
return 0;
}

-static int watermark_scale_factor_sysctl_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int watermark_scale_factor_sysctl_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
int rc;

@@ -6024,8 +6024,8 @@ static void setup_min_unmapped_ratio(void)
}


-static int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int sysctl_min_unmapped_ratio_sysctl_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
int rc;

@@ -6051,8 +6051,8 @@ static void setup_min_slab_ratio(void)
sysctl_min_slab_ratio) / 100;
}

-static int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *table, int write,
- void *buffer, size_t *length, loff_t *ppos)
+static int sysctl_min_slab_ratio_sysctl_handler(const struct ctl_table *table,
+ int write, void *buffer, size_t *length, loff_t *ppos)
{
int rc;

@@ -6075,7 +6075,7 @@ static int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *table, int wri
* minimum watermarks. The lowmem reserve ratio can only make sense
* if in function of the boot time zone sizes.
*/
-static int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table,
+static int lowmem_reserve_ratio_sysctl_handler(const struct ctl_table *table,
int write, void *buffer, size_t *length, loff_t *ppos)
{
int i;
@@ -6096,7 +6096,7 @@ static int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table,
* cpu. It is the fraction of total pages in each zone that a hot per cpu
* pagelist can have before it gets flushed back to buddy allocator.
*/
-static int percpu_pagelist_high_fraction_sysctl_handler(struct ctl_table *table,
+static int percpu_pagelist_high_fraction_sysctl_handler(const struct ctl_table *table,
int write, void *buffer, size_t *length, loff_t *ppos)
{
struct zone *zone;
diff --git a/mm/util.c b/mm/util.c
index 744b4d7e3fae..98338ab35b68 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -818,8 +818,8 @@ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */

-int overcommit_ratio_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+int overcommit_ratio_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;

@@ -834,8 +834,8 @@ static void sync_overcommit_as(struct work_struct *dummy)
percpu_counter_sync(&vm_committed_as);
}

-int overcommit_policy_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+int overcommit_policy_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
int new_policy = -1;
@@ -870,8 +870,8 @@ int overcommit_policy_handler(struct ctl_table *table, int write, void *buffer,
return ret;
}

-int overcommit_kbytes_handler(struct ctl_table *table, int write, void *buffer,
- size_t *lenp, loff_t *ppos)
+int overcommit_kbytes_handler(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;

diff --git a/mm/vmstat.c b/mm/vmstat.c
index 359460deb377..a65316426012 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -74,7 +74,7 @@ static void invalid_numa_statistics(void)

static DEFINE_MUTEX(vm_numa_stat_lock);

-int sysctl_vm_numa_stat_handler(struct ctl_table *table, int write,
+int sysctl_vm_numa_stat_handler(const struct ctl_table *table, int write,
void *buffer, size_t *length, loff_t *ppos)
{
int ret, oldval;
@@ -1883,7 +1883,7 @@ static void refresh_vm_stats(struct work_struct *work)
refresh_cpu_vm_stats(true);
}

-int vmstat_refresh(struct ctl_table *table, int write,
+int vmstat_refresh(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
long val;
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 74056b563b95..c284bd9c2d7a 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -1048,7 +1048,7 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,

#ifdef CONFIG_SYSCTL
static
-int brnf_sysctl_call_tables(struct ctl_table *ctl, int write,
+int brnf_sysctl_call_tables(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index df81c1f0a570..8d13979c0c38 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -3531,7 +3531,7 @@ EXPORT_SYMBOL(neigh_app_ns);
#ifdef CONFIG_SYSCTL
static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);

-static int proc_unres_qlen(struct ctl_table *ctl, int write,
+static int proc_unres_qlen(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int size, ret;
@@ -3566,7 +3566,7 @@ static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
rcu_read_unlock();
}

-static void neigh_proc_update(struct ctl_table *ctl, int write)
+static void neigh_proc_update(const struct ctl_table *ctl, int write)
{
struct net_device *dev = ctl->extra1;
struct neigh_parms *p = ctl->extra2;
@@ -3583,9 +3583,9 @@ static void neigh_proc_update(struct ctl_table *ctl, int write)
neigh_copy_dflt_parms(net, p, index);
}

-static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
- void *buffer, size_t *lenp,
- loff_t *ppos)
+static int neigh_proc_dointvec_zero_intmax(const struct ctl_table *ctl,
+ int write, void *buffer,
+ size_t *lenp, loff_t *ppos)
{
struct ctl_table tmp = *ctl;
int ret;
@@ -3598,7 +3598,7 @@ static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
return ret;
}

-static int neigh_proc_dointvec_ms_jiffies_positive(struct ctl_table *ctl, int write,
+static int neigh_proc_dointvec_ms_jiffies_positive(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table tmp = *ctl;
@@ -3614,7 +3614,7 @@ static int neigh_proc_dointvec_ms_jiffies_positive(struct ctl_table *ctl, int wr
return ret;
}

-int neigh_proc_dointvec(struct ctl_table *ctl, int write, void *buffer,
+int neigh_proc_dointvec(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
@@ -3624,7 +3624,7 @@ int neigh_proc_dointvec(struct ctl_table *ctl, int write, void *buffer,
}
EXPORT_SYMBOL(neigh_proc_dointvec);

-int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write, void *buffer,
+int neigh_proc_dointvec_jiffies(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
@@ -3634,7 +3634,7 @@ int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write, void *buffer,
}
EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);

-static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
+static int neigh_proc_dointvec_userhz_jiffies(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -3644,7 +3644,7 @@ static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
return ret;
}

-int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
+int neigh_proc_dointvec_ms_jiffies(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
@@ -3654,7 +3654,7 @@ int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
}
EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);

-static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
+static int neigh_proc_dointvec_unres_qlen(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -3664,7 +3664,7 @@ static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
return ret;
}

-static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
+static int neigh_proc_base_reachable_time(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 08a01b31be99..b5093796f196 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -91,7 +91,7 @@ static struct cpumask *rps_default_mask_cow_alloc(struct net *net)
return rps_default_mask;
}

-static int rps_default_mask_sysctl(struct ctl_table *table, int write,
+static int rps_default_mask_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = (struct net *)table->data;
@@ -122,7 +122,7 @@ static int rps_default_mask_sysctl(struct ctl_table *table, int write,
return err;
}

-static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
+static int rps_sock_flow_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
unsigned int orig_size, size;
@@ -191,7 +191,7 @@ static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
#ifdef CONFIG_NET_FLOW_LIMIT
static DEFINE_MUTEX(flow_limit_update_mutex);

-static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
+static int flow_limit_cpu_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct sd_flow_limit *cur;
@@ -248,7 +248,7 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
return ret;
}

-static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
+static int flow_limit_table_len_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
unsigned int old, *ptr;
@@ -270,7 +270,7 @@ static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
#endif /* CONFIG_NET_FLOW_LIMIT */

#ifdef CONFIG_NET_SCHED
-static int set_default_qdisc(struct ctl_table *table, int write,
+static int set_default_qdisc(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
char id[IFNAMSIZ];
@@ -289,7 +289,7 @@ static int set_default_qdisc(struct ctl_table *table, int write,
}
#endif

-static int proc_do_dev_weight(struct ctl_table *table, int write,
+static int proc_do_dev_weight(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
static DEFINE_MUTEX(dev_weight_mutex);
@@ -307,7 +307,7 @@ static int proc_do_dev_weight(struct ctl_table *table, int write,
return ret;
}

-static int proc_do_rss_key(struct ctl_table *table, int write,
+static int proc_do_rss_key(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table fake_table;
@@ -320,7 +320,7 @@ static int proc_do_rss_key(struct ctl_table *table, int write,
}

#ifdef CONFIG_BPF_JIT
-static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_bpf_enable(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -353,7 +353,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,

# ifdef CONFIG_HAVE_EBPF_JIT
static int
-proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
+proc_dointvec_minmax_bpf_restricted(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (!capable(CAP_SYS_ADMIN))
@@ -364,7 +364,7 @@ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
# endif /* CONFIG_HAVE_EBPF_JIT */

static int
-proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write,
+proc_dolongvec_minmax_bpf_restricted(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (!capable(CAP_SYS_ADMIN))
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index f8a56fe95801..bf53518cfef8 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2395,7 +2395,7 @@ static int devinet_conf_ifindex(struct net *net, struct ipv4_devconf *cnf)
}
}

-static int devinet_conf_proc(struct ctl_table *ctl, int write,
+static int devinet_conf_proc(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int old_value = *(int *)ctl->data;
@@ -2447,7 +2447,7 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write,
return ret;
}

-static int devinet_sysctl_forward(struct ctl_table *ctl, int write,
+static int devinet_sysctl_forward(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
@@ -2494,7 +2494,7 @@ static int devinet_sysctl_forward(struct ctl_table *ctl, int write,
return ret;
}

-static int ipv4_doint_and_flush(struct ctl_table *ctl, int write,
+static int ipv4_doint_and_flush(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 7c7884110a58..adabe2aa3d8b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3408,7 +3408,7 @@ static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
static int ip_rt_gc_elasticity __read_mostly = 8;
static int ip_min_valid_pmtu __read_mostly = IPV4_MIN_MTU;

-static int ipv4_sysctl_rtcache_flush(struct ctl_table *__ctl, int write,
+static int ipv4_sysctl_rtcache_flush(const struct ctl_table *__ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = (struct net *)__ctl->extra1;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 599244f9ad65..eef0082233e1 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -65,7 +65,7 @@ static void set_local_port_range(struct net *net, int range[2])
}

/* Validate changes from /proc interface. */
-static int ipv4_local_port_range(struct ctl_table *table, int write,
+static int ipv4_local_port_range(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net =
@@ -100,7 +100,7 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
}

/* Validate changes from /proc interface. */
-static int ipv4_privileged_ports(struct ctl_table *table, int write,
+static int ipv4_privileged_ports(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = container_of(table->data, struct net,
@@ -134,7 +134,8 @@ static int ipv4_privileged_ports(struct ctl_table *table, int write,
return ret;
}

-static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)
+static void inet_get_ping_group_range_table(const struct ctl_table *table, kgid_t *low,
+ kgid_t *high)
{
kgid_t *data = table->data;
struct net *net =
@@ -149,7 +150,7 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low
}

/* Update system visible IP port range */
-static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
+static void set_ping_group_range(const struct ctl_table *table, kgid_t low, kgid_t high)
{
kgid_t *data = table->data;
struct net *net =
@@ -161,7 +162,7 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig
}

/* Validate changes from /proc interface. */
-static int ipv4_ping_group_range(struct ctl_table *table, int write,
+static int ipv4_ping_group_range(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct user_namespace *user_ns = current_user_ns();
@@ -196,7 +197,7 @@ static int ipv4_ping_group_range(struct ctl_table *table, int write,
return ret;
}

-static int ipv4_fwd_update_priority(struct ctl_table *table, int write,
+static int ipv4_fwd_update_priority(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net;
@@ -212,7 +213,7 @@ static int ipv4_fwd_update_priority(struct ctl_table *table, int write,
return ret;
}

-static int proc_tcp_congestion_control(struct ctl_table *ctl, int write,
+static int proc_tcp_congestion_control(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = container_of(ctl->data, struct net,
@@ -232,7 +233,7 @@ static int proc_tcp_congestion_control(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_tcp_available_congestion_control(struct ctl_table *ctl,
+static int proc_tcp_available_congestion_control(const struct ctl_table *ctl,
int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
@@ -248,7 +249,7 @@ static int proc_tcp_available_congestion_control(struct ctl_table *ctl,
return ret;
}

-static int proc_allowed_congestion_control(struct ctl_table *ctl,
+static int proc_allowed_congestion_control(const struct ctl_table *ctl,
int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
@@ -285,7 +286,7 @@ static int sscanf_key(char *buf, __le32 *key)
return ret;
}

-static int proc_tcp_fastopen_key(struct ctl_table *table, int write,
+static int proc_tcp_fastopen_key(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = container_of(table->data, struct net,
@@ -356,7 +357,7 @@ static int proc_tcp_fastopen_key(struct ctl_table *table, int write,
return ret;
}

-static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table,
+static int proc_tfo_blackhole_detect_timeout(const struct ctl_table *table,
int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
@@ -371,7 +372,7 @@ static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table,
return ret;
}

-static int proc_tcp_available_ulp(struct ctl_table *ctl,
+static int proc_tcp_available_ulp(const struct ctl_table *ctl,
int write, void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -388,7 +389,7 @@ static int proc_tcp_available_ulp(struct ctl_table *ctl,
return ret;
}

-static int proc_tcp_ehash_entries(struct ctl_table *table, int write,
+static int proc_tcp_ehash_entries(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = container_of(table->data, struct net,
@@ -412,7 +413,7 @@ static int proc_tcp_ehash_entries(struct ctl_table *table, int write,
return proc_dointvec(&tbl, write, buffer, lenp, ppos);
}

-static int proc_udp_hash_entries(struct ctl_table *table, int write,
+static int proc_udp_hash_entries(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = container_of(table->data, struct net,
@@ -436,7 +437,7 @@ static int proc_udp_hash_entries(struct ctl_table *table, int write,
}

#ifdef CONFIG_IP_ROUTE_MULTIPATH
-static int proc_fib_multipath_hash_policy(struct ctl_table *table, int write,
+static int proc_fib_multipath_hash_policy(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -451,7 +452,7 @@ static int proc_fib_multipath_hash_policy(struct ctl_table *table, int write,
return ret;
}

-static int proc_fib_multipath_hash_fields(struct ctl_table *table, int write,
+static int proc_fib_multipath_hash_fields(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index aa5654d29334..6732ee1bb901 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -859,7 +859,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
}
}

-static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
+static int addrconf_fixup_forwarding(const struct ctl_table *table, int *p, int newf)
{
struct net *net;
int old;
@@ -927,7 +927,7 @@ static void addrconf_linkdown_change(struct net *net, __s32 newf)
}
}

-static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf)
+static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int newf)
{
struct net *net;
int old;
@@ -6258,7 +6258,7 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)

#ifdef CONFIG_SYSCTL

-static int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_forward(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
@@ -6283,7 +6283,7 @@ static int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
return ret;
}

-static int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_mtu(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct inet6_dev *idev = ctl->extra1;
@@ -6327,7 +6327,7 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
}
}

-static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
+static int addrconf_disable_ipv6(const struct ctl_table *table, int *p, int newf)
{
struct net *net;
int old;
@@ -6354,7 +6354,7 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
return 0;
}

-static int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_disable(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
@@ -6379,7 +6379,7 @@ static int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
return ret;
}

-static int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = ctl->data;
@@ -6420,7 +6420,7 @@ static int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
return ret;
}

-static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -6482,7 +6482,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
return ret;
}

-static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
+static int addrconf_sysctl_stable_secret(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp,
loff_t *ppos)
{
@@ -6549,7 +6549,7 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
}

static
-int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
+int addrconf_sysctl_ignore_routes_with_linkdown(const struct ctl_table *ctl,
int write, void *buffer,
size_t *lenp,
loff_t *ppos)
@@ -6617,7 +6617,7 @@ void addrconf_disable_policy_idev(struct inet6_dev *idev, int val)
}

static
-int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
+int addrconf_disable_policy(const struct ctl_table *ctl, int *valp, int val)
{
struct inet6_dev *idev;
struct net *net;
@@ -6650,8 +6650,9 @@ int addrconf_disable_policy(struct ctl_table *ctl, int *valp, int val)
return 0;
}

-static int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write,
- void *buffer, size_t *lenp, loff_t *ppos)
+static int addrconf_sysctl_disable_policy(const struct ctl_table *ctl,
+ int write, void *buffer, size_t *lenp,
+ loff_t *ppos)
{
int *valp = ctl->data;
int val = *valp;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a19999b30bc0..e423b4fe0836 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1922,7 +1922,7 @@ static struct notifier_block ndisc_netdev_notifier = {
};

#ifdef CONFIG_SYSCTL
-static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
+static void ndisc_warn_deprecated_sysctl(const struct ctl_table *ctl,
const char *func, const char *dev_name)
{
static char warncomm[TASK_COMM_LEN];
@@ -1937,7 +1937,7 @@ static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
}
}

-int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void *buffer,
+int ndisc_ifinfo_sysctl_change(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct net_device *dev = ctl->extra1;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b132feae3393..a318fba122b3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -6325,7 +6325,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v)

#ifdef CONFIG_SYSCTL

-static int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,
+static int ipv6_sysctl_rtcache_flush(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net;
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 75de55f907b0..e5a4cbc3e8c3 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -30,7 +30,7 @@ static u32 rt6_multipath_hash_fields_all_mask =
static u32 ioam6_id_max = IOAM6_DEFAULT_ID;
static u64 ioam6_id_wide_max = IOAM6_DEFAULT_ID_WIDE;

-static int proc_rt6_multipath_hash_policy(struct ctl_table *table, int write,
+static int proc_rt6_multipath_hash_policy(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net;
@@ -46,7 +46,7 @@ static int proc_rt6_multipath_hash_policy(struct ctl_table *table, int write,
}

static int
-proc_rt6_multipath_hash_fields(struct ctl_table *table, int write, void *buffer,
+proc_rt6_multipath_hash_fields(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct net *net;
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 832b63bb5646..c107de0b4e49 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1363,7 +1363,7 @@ static int mpls_netconf_dump_devconf(struct sk_buff *skb,
#define MPLS_PERDEV_SYSCTL_OFFSET(field) \
(&((struct mpls_dev *)0)->field)

-static int mpls_conf_proc(struct ctl_table *ctl, int write,
+static int mpls_conf_proc(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int oval = *(int *)ctl->data;
@@ -2615,7 +2615,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
return -ENOMEM;
}

-static int mpls_platform_labels(struct ctl_table *table, int write,
+static int mpls_platform_labels(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = table->data;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 143a341bbc0a..8b7720925699 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1846,7 +1846,7 @@ static int ip_vs_zero_all(struct netns_ipvs *ipvs)
#ifdef CONFIG_SYSCTL

static int
-proc_do_defense_mode(struct ctl_table *table, int write,
+proc_do_defense_mode(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct netns_ipvs *ipvs = table->extra2;
@@ -1873,7 +1873,7 @@ proc_do_defense_mode(struct ctl_table *table, int write,
}

static int
-proc_do_sync_threshold(struct ctl_table *table, int write,
+proc_do_sync_threshold(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct netns_ipvs *ipvs = table->extra2;
@@ -1901,7 +1901,7 @@ proc_do_sync_threshold(struct ctl_table *table, int write,
}

static int
-proc_do_sync_ports(struct ctl_table *table, int write,
+proc_do_sync_ports(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = table->data;
@@ -1924,7 +1924,7 @@ proc_do_sync_ports(struct ctl_table *table, int write,
return rc;
}

-static int ipvs_proc_est_cpumask_set(struct ctl_table *table, void *buffer)
+static int ipvs_proc_est_cpumask_set(const struct ctl_table *table, void *buffer)
{
struct netns_ipvs *ipvs = table->extra2;
cpumask_var_t *valp = table->data;
@@ -1962,7 +1962,7 @@ static int ipvs_proc_est_cpumask_set(struct ctl_table *table, void *buffer)
return ret;
}

-static int ipvs_proc_est_cpumask_get(struct ctl_table *table, void *buffer,
+static int ipvs_proc_est_cpumask_get(const struct ctl_table *table, void *buffer,
size_t size)
{
struct netns_ipvs *ipvs = table->extra2;
@@ -1983,7 +1983,7 @@ static int ipvs_proc_est_cpumask_get(struct ctl_table *table, void *buffer,
return ret;
}

-static int ipvs_proc_est_cpulist(struct ctl_table *table, int write,
+static int ipvs_proc_est_cpulist(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
@@ -2010,7 +2010,7 @@ static int ipvs_proc_est_cpulist(struct ctl_table *table, int write,
return ret;
}

-static int ipvs_proc_est_nice(struct ctl_table *table, int write,
+static int ipvs_proc_est_nice(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct netns_ipvs *ipvs = table->extra2;
@@ -2040,7 +2040,7 @@ static int ipvs_proc_est_nice(struct ctl_table *table, int write,
return ret;
}

-static int ipvs_proc_run_estimation(struct ctl_table *table, int write,
+static int ipvs_proc_run_estimation(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct netns_ipvs *ipvs = table->extra2;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index bb9dea676ec1..3d5284639ca8 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -527,7 +527,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_count);
static unsigned int nf_conntrack_htable_size_user __read_mostly;

static int
-nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
+nf_conntrack_hash_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/net/netfilter/nf_hooks_lwtunnel.c b/net/netfilter/nf_hooks_lwtunnel.c
index 00e89ffd78f6..3d237f9cc8ee 100644
--- a/net/netfilter/nf_hooks_lwtunnel.c
+++ b/net/netfilter/nf_hooks_lwtunnel.c
@@ -25,7 +25,7 @@ static inline int nf_hooks_lwtunnel_set(int enable)
}

#ifdef CONFIG_SYSCTL
-int nf_hooks_lwtunnel_sysctl_handler(struct ctl_table *table, int write,
+int nf_hooks_lwtunnel_sysctl_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int proc_nf_hooks_lwtunnel_enabled = 0;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 2e897a9f0689..9432a6c6c140 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -403,7 +403,7 @@ static struct ctl_table nf_log_sysctl_ftable[] = {
{ }
};

-static int nf_log_proc_dostring(struct ctl_table *table, int write,
+static int nf_log_proc_dostring(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
const struct nf_logger *logger;
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c
index 0d0bf41381c2..e59d16e67376 100644
--- a/net/phonet/sysctl.c
+++ b/net/phonet/sysctl.c
@@ -48,7 +48,7 @@ void phonet_get_local_port_range(int *min, int *max)
} while (read_seqretry(&local_port_range_lock, seq));
}

-static int proc_local_port_range(struct ctl_table *table, int write,
+static int proc_local_port_range(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 2dba7505b414..d23ea8c11902 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -61,7 +61,7 @@ static atomic_t rds_tcp_unloading = ATOMIC_INIT(0);

static struct kmem_cache *rds_tcp_conn_slab;

-static int rds_tcp_skbuf_handler(struct ctl_table *ctl, int write,
+static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *fpos);

static int rds_tcp_min_sndbuf = SOCK_MIN_SNDBUF;
@@ -683,7 +683,7 @@ static void rds_tcp_sysctl_reset(struct net *net)
spin_unlock_irq(&rds_tcp_conn_lock);
}

-static int rds_tcp_skbuf_handler(struct ctl_table *ctl, int write,
+static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *fpos)
{
struct net *net = current->nsproxy->net_ns;
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 25bdf17c7262..8317421d1b83 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -43,19 +43,19 @@ static unsigned long max_autoclose_max =
(MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ;

-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, void *buffer,
+static int proc_sctp_do_rto_max(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, void *buffer,
+static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
+static int proc_sctp_do_alpha_beta(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
+static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
-static int proc_sctp_do_probe_interval(struct ctl_table *ctl, int write,
+static int proc_sctp_do_probe_interval(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);

static struct ctl_table sctp_table[] = {
@@ -388,7 +388,7 @@ static struct ctl_table sctp_net_table[] = {
{ /* sentinel */ }
};

-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
@@ -433,7 +433,7 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
@@ -461,7 +461,7 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
+static int proc_sctp_do_rto_max(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
@@ -489,7 +489,7 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
+static int proc_sctp_do_alpha_beta(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (write)
@@ -499,7 +499,7 @@ static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
}

-static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
+static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
@@ -528,7 +528,7 @@ static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
+static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
@@ -569,7 +569,7 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
return ret;
}

-static int proc_sctp_do_probe_interval(struct ctl_table *ctl, int write,
+static int proc_sctp_do_probe_interval(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 93941ab12549..672067efacef 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -40,7 +40,7 @@ EXPORT_SYMBOL_GPL(nlm_debug);

#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)

-static int proc_do_xprt(struct ctl_table *table, int write,
+static int proc_do_xprt(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
char tmpbuf[256];
@@ -62,8 +62,8 @@ static int proc_do_xprt(struct ctl_table *table, int write,
}

static int
-proc_dodebug(struct ctl_table *table, int write, void *buffer, size_t *lenp,
- loff_t *ppos)
+proc_dodebug(const struct ctl_table *table, int write, void *buffer,
+ size_t *lenp, loff_t *ppos)
{
char tmpbuf[20], *s = NULL;
char *p;
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index f0d5eeed4c88..fb1d5432080e 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -74,7 +74,7 @@ enum {
SVCRDMA_COUNTER_BUFSIZ = sizeof(unsigned long long),
};

-static int svcrdma_counter_handler(struct ctl_table *table, int write,
+static int svcrdma_counter_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct percpu_counter *stat = (struct percpu_counter *)table->data;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 4981bdf02993..2828aadcd732 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1980,7 +1980,7 @@ static int __init alloc_buffers(void)
}

#ifdef CONFIG_SYSCTL
-static int apparmor_dointvec(struct ctl_table *table, int write,
+static int apparmor_dointvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
if (!aa_current_policy_admin_capable(NULL))
diff --git a/security/min_addr.c b/security/min_addr.c
index 88c9a6a21f47..0ce267c041ab 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -29,7 +29,7 @@ static void update_mmap_min_addr(void)
* sysctl handler which just sets dac_mmap_min_addr = the new value and then
* calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
*/
-int mmap_min_addr_handler(struct ctl_table *table, int write,
+int mmap_min_addr_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 2503cf153d4a..9cb8e7cded56 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -429,7 +429,7 @@ static struct security_hook_list yama_hooks[] __ro_after_init = {
};

#ifdef CONFIG_SYSCTL
-static int yama_dointvec_minmax(struct ctl_table *table, int write,
+static int yama_dointvec_minmax(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table table_copy;

--
2.43.0

2023-12-04 07:54:09

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

In a future commit the sysctl core will only use
"const struct ctl_table". As a preparation for that move this mutable
field from "struct ctl_table" to "struct ctl_table_header".

This is also more correct in general as this is in fact a property of
the header and not the table itself.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
fs/proc/proc_sysctl.c | 11 ++++++-----
include/linux/sysctl.h | 22 +++++++++++-----------
2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 689a30196d0c..a398cc77637f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -31,7 +31,7 @@ static const struct inode_operations proc_sys_dir_operations;

/* Support for permanently empty directories */
static struct ctl_table sysctl_mount_point[] = {
- {.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
+ { }
};

/**
@@ -49,11 +49,11 @@ struct ctl_table_header *register_sysctl_mount_point(const char *path)
EXPORT_SYMBOL(register_sysctl_mount_point);

#define sysctl_is_perm_empty_ctl_header(hptr) \
- (hptr->ctl_table[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
+ (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
#define sysctl_set_perm_empty_ctl_header(hptr) \
- (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
+ (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
#define sysctl_clear_perm_empty_ctl_header(hptr) \
- (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
+ (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)

void proc_sys_poll_notify(struct ctl_table_poll *poll)
{
@@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
return -EROFS;

/* Am I creating a permanently empty directory? */
- if (sysctl_is_perm_empty_ctl_header(header)) {
+ if (header->ctl_table == sysctl_mount_point ||
+ sysctl_is_perm_empty_ctl_header(header)) {
if (!RB_EMPTY_ROOT(&dir->root))
return -EINVAL;
sysctl_set_perm_empty_ctl_header(dir_h);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index ada36ef8cecb..061ea65104be 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -137,17 +137,6 @@ struct ctl_table {
void *data;
int maxlen;
umode_t mode;
- /**
- * enum type - Enumeration to differentiate between ctl target types
- * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
- * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
- * empty directory target to serve
- * as mount point.
- */
- enum {
- SYSCTL_TABLE_TYPE_DEFAULT,
- SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
- } type;
proc_handler *proc_handler; /* Callback for text formatting */
struct ctl_table_poll *poll;
void *extra1;
@@ -188,6 +177,17 @@ struct ctl_table_header {
struct ctl_dir *parent;
struct ctl_node *node;
struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
+ /**
+ * enum type - Enumeration to differentiate between ctl target types
+ * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
+ * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
+ * empty directory target to serve
+ * as mount point.
+ */
+ enum {
+ SYSCTL_TABLE_TYPE_DEFAULT,
+ SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
+ } type;
};

struct ctl_dir {

--
2.43.0

2023-12-04 07:54:11

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 15/18] sysctl: allow registration of const struct ctl_table

This allows sysctl table to be put into read-only data.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
fs/proc/proc_sysctl.c | 6 +++---
include/linux/sysctl.h | 10 +++++-----
2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index e7fd1680d479..d09107a5b43f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1356,7 +1356,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
*/
struct ctl_table_header *__register_sysctl_table(
struct ctl_table_set *set,
- const char *path, struct ctl_table *table, size_t table_size)
+ const char *path, const struct ctl_table *table, size_t table_size)
{
struct ctl_table_root *root = set->dir.header.root;
struct ctl_table_header *header;
@@ -1417,7 +1417,7 @@ struct ctl_table_header *__register_sysctl_table(
*
* See __register_sysctl_table for more details.
*/
-struct ctl_table_header *register_sysctl_sz(const char *path, struct ctl_table *table,
+struct ctl_table_header *register_sysctl_sz(const char *path, const struct ctl_table *table,
size_t table_size)
{
return __register_sysctl_table(&sysctl_table_root.default_set,
@@ -1446,7 +1446,7 @@ EXPORT_SYMBOL(register_sysctl_sz);
*
* Context: if your base directory does not exist it will be created for you.
*/
-void __init __register_sysctl_init(const char *path, struct ctl_table *table,
+void __init __register_sysctl_init(const char *path, const struct ctl_table *table,
const char *table_name, size_t table_size)
{
struct ctl_table_header *hdr = register_sysctl_sz(path, table, table_size);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 2f4d577f2e93..7c96d5abafc7 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -229,13 +229,13 @@ extern void retire_sysctl_set(struct ctl_table_set *set);

struct ctl_table_header *__register_sysctl_table(
struct ctl_table_set *set,
- const char *path, struct ctl_table *table, size_t table_size);
-struct ctl_table_header *register_sysctl_sz(const char *path, struct ctl_table *table,
+ const char *path, const struct ctl_table *table, size_t table_size);
+struct ctl_table_header *register_sysctl_sz(const char *path, const struct ctl_table *table,
size_t table_size);
void unregister_sysctl_table(struct ctl_table_header * table);

extern int sysctl_init_bases(void);
-extern void __register_sysctl_init(const char *path, struct ctl_table *table,
+extern void __register_sysctl_init(const char *path, const struct ctl_table *table,
const char *table_name, size_t table_size);
#define register_sysctl_init(path, table) \
__register_sysctl_init(path, table, #table, ARRAY_SIZE(table))
@@ -257,7 +257,7 @@ extern int no_unaligned_warning;

#else /* CONFIG_SYSCTL */

-static inline void register_sysctl_init(const char *path, struct ctl_table *table)
+static inline void register_sysctl_init(const char *path, const struct ctl_table *table)
{
}

@@ -267,7 +267,7 @@ static inline struct ctl_table_header *register_sysctl_mount_point(const char *p
}

static inline struct ctl_table_header *register_sysctl_sz(const char *path,
- struct ctl_table *table,
+ const struct ctl_table *table,
size_t table_size)
{
return NULL;

--
2.43.0

2023-12-04 07:54:20

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 11/18] sysctl: treewide: constify ctl_table_header::ctl_table_arg

In a future commit the sysctl core will only use
"const struct ctl_table". As a preparation for that adapt the
ctl_table_arg member.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
drivers/net/vrf.c | 2 +-
include/linux/sysctl.h | 2 +-
ipc/ipc_sysctl.c | 2 +-
ipc/mq_sysctl.c | 2 +-
kernel/ucount.c | 2 +-
net/ax25/sysctl_net_ax25.c | 2 +-
net/bridge/br_netfilter_hooks.c | 4 +++-
net/core/sysctl_net_core.c | 2 +-
net/ieee802154/6lowpan/reassembly.c | 2 +-
net/ipv4/devinet.c | 2 +-
net/ipv4/ip_fragment.c | 2 +-
net/ipv4/route.c | 2 +-
net/ipv4/sysctl_net_ipv4.c | 2 +-
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/addrconf.c | 2 +-
net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +-
net/ipv6/reassembly.c | 2 +-
net/ipv6/sysctl_net_ipv6.c | 6 +++---
net/ipv6/xfrm6_policy.c | 2 +-
net/mpls/af_mpls.c | 4 ++--
net/mptcp/ctrl.c | 2 +-
net/netfilter/nf_conntrack_standalone.c | 2 +-
net/netfilter/nf_log.c | 2 +-
net/sctp/sysctl.c | 2 +-
net/smc/smc_sysctl.c | 2 +-
net/unix/sysctl_net_unix.c | 2 +-
net/xfrm/xfrm_sysctl.c | 2 +-
27 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index bb95ce43cd97..66f8542f3b18 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1971,7 +1971,7 @@ static int vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf)
static void vrf_netns_exit_sysctl(struct net *net)
{
struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
- struct ctl_table *table;
+ const struct ctl_table *table;

table = nn_vrf->ctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(nn_vrf->ctl_hdr);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 92c1d0114cdc..56b89e5294e9 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -182,7 +182,7 @@ struct ctl_table_header {
struct rcu_head rcu;
};
struct completion *unregistering;
- struct ctl_table *ctl_table_arg;
+ const struct ctl_table *ctl_table_arg;
struct ctl_table_root *root;
struct ctl_table_set *set;
struct ctl_dir *parent;
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index b087787f608f..55d6b9f1e508 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -274,7 +274,7 @@ bool setup_ipc_sysctls(struct ipc_namespace *ns)

void retire_ipc_sysctls(struct ipc_namespace *ns)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = ns->ipc_sysctls->ctl_table_arg;
unregister_sysctl_table(ns->ipc_sysctls);
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index ebb5ed81c151..2a2ba6ded037 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -124,7 +124,7 @@ bool setup_mq_sysctls(struct ipc_namespace *ns)

void retire_mq_sysctls(struct ipc_namespace *ns)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = ns->mq_sysctls->ctl_table_arg;
unregister_sysctl_table(ns->mq_sysctls);
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 90300840256b..366a2c1971f5 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -119,7 +119,7 @@ bool setup_userns_sysctls(struct user_namespace *ns)
void retire_userns_sysctls(struct user_namespace *ns)
{
#ifdef CONFIG_SYSCTL
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = ns->sysctls->ctl_table_arg;
unregister_sysctl_table(ns->sysctls);
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index db66e11e7fe8..e0128dc9def3 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -171,7 +171,7 @@ int ax25_register_dev_sysctl(ax25_dev *ax25_dev)
void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev)
{
struct ctl_table_header *header = ax25_dev->sysheader;
- struct ctl_table *table;
+ const struct ctl_table *table;

if (header) {
ax25_dev->sysheader = NULL;
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 6adcb45bca75..74056b563b95 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -1146,7 +1146,9 @@ static int br_netfilter_sysctl_init_net(struct net *net)
static void br_netfilter_sysctl_exit_net(struct net *net,
struct brnf_net *brnet)
{
- struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg;
+ const struct ctl_table *table;
+
+ table = brnet->ctl_hdr->ctl_table_arg;

unregister_net_sysctl_table(brnet->ctl_hdr);
if (!net_eq(net, &init_net))
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 03f1edb948d7..08a01b31be99 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -728,7 +728,7 @@ static __net_init int sysctl_core_net_init(struct net *net)

static __net_exit void sysctl_core_net_exit(struct net *net)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = net->core.sysctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->core.sysctl_hdr);
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index 6dd960ec558c..2a983cf450da 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -399,7 +399,7 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)

static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
struct netns_ieee802154_lowpan *ieee802154_lowpan =
net_ieee802154_lowpan(net);

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index ca0ff15dc8fa..f8a56fe95801 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2767,7 +2767,7 @@ static __net_init int devinet_init_net(struct net *net)
static __net_exit void devinet_exit_net(struct net *net)
{
#ifdef CONFIG_SYSCTL
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = net->ipv4.forw_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.forw_hdr);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a4941f53b523..6b9285fd6f06 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -632,7 +632,7 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net)

static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->ipv4.frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.frags_hdr);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 16615d107cf0..7c7884110a58 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3590,7 +3590,7 @@ static __net_init int sysctl_route_net_init(struct net *net)

static __net_exit void sysctl_route_net_exit(struct net *net)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;

tbl = net->ipv4.route_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.route_hdr);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index f63a545a7374..599244f9ad65 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -1558,7 +1558,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)

static __net_exit void ipv4_sysctl_exit_net(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

kfree(net->ipv4.sysctl_local_reserved_ports);
table = net->ipv4.ipv4_hdr->ctl_table_arg;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index c33bca2c3841..1dda59e0aeab 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -186,7 +186,7 @@ static __net_init int xfrm4_net_sysctl_init(struct net *net)

static __net_exit void xfrm4_net_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

if (!net->ipv4.xfrm4_hdr)
return;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3aaea56b5166..aa5654d29334 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7180,7 +7180,7 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
static void __addrconf_sysctl_unregister(struct net *net,
struct ipv6_devconf *p, int ifindex)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

if (!p->sysctl_header)
return;
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index b2dd48911c8d..1d6f6deb2562 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -105,7 +105,7 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
{
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
- struct ctl_table *table;
+ const struct ctl_table *table;

table = nf_frag->nf_frag_frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 5ebc47da1000..0746dc1f1e61 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -487,7 +487,7 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net)

static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->ipv6.sysctl.frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr);
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 888676163e90..75de55f907b0 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -313,9 +313,9 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)

static void __net_exit ipv6_sysctl_net_exit(struct net *net)
{
- struct ctl_table *ipv6_table;
- struct ctl_table *ipv6_route_table;
- struct ctl_table *ipv6_icmp_table;
+ const struct ctl_table *ipv6_table;
+ const struct ctl_table *ipv6_route_table;
+ const struct ctl_table *ipv6_icmp_table;

ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 42fb6996b077..4891012b692f 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -218,7 +218,7 @@ static int __net_init xfrm6_net_sysctl_init(struct net *net)

static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

if (!net->ipv6.sysctl.xfrm6_hdr)
return;
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 1af29af65388..832b63bb5646 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1438,7 +1438,7 @@ static void mpls_dev_sysctl_unregister(struct net_device *dev,
struct mpls_dev *mdev)
{
struct net *net = dev_net(dev);
- struct ctl_table *table;
+ const struct ctl_table *table;

if (!mdev->sysctl)
return;
@@ -2704,7 +2704,7 @@ static void mpls_net_exit(struct net *net)
{
struct mpls_route __rcu **platform_label;
size_t platform_labels;
- struct ctl_table *table;
+ const struct ctl_table *table;
unsigned int index;

table = net->mpls.ctl->ctl_table_arg;
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 13fe0748dde8..8d661156ab8c 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -198,7 +198,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)

static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
{
- struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
+ const struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;

unregister_net_sysctl_table(pernet->ctl_table_hdr);

diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 0ee98ce5b816..bb9dea676ec1 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -1122,7 +1122,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
static void nf_conntrack_standalone_fini_sysctl(struct net *net)
{
struct nf_conntrack_net *cnet = nf_ct_pernet(net);
- struct ctl_table *table;
+ const struct ctl_table *table;

table = cnet->sysctl_header->ctl_table_arg;
unregister_net_sysctl_table(cnet->sysctl_header);
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 8cc52d2bd31b..2e897a9f0689 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -508,7 +508,7 @@ static int netfilter_log_sysctl_init(struct net *net)

static void netfilter_log_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->nf.nf_log_dir_header->ctl_table_arg;
unregister_net_sysctl_table(net->nf.nf_log_dir_header);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index f65d6f92afcb..25bdf17c7262 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -624,7 +624,7 @@ int sctp_sysctl_net_register(struct net *net)

void sctp_sysctl_net_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->sctp.sysctl_header->ctl_table_arg;
unregister_net_sysctl_table(net->sctp.sysctl_header);
diff --git a/net/smc/smc_sysctl.c b/net/smc/smc_sysctl.c
index 5cbc18c6e62b..c632df62ff90 100644
--- a/net/smc/smc_sysctl.c
+++ b/net/smc/smc_sysctl.c
@@ -109,7 +109,7 @@ int __net_init smc_sysctl_net_init(struct net *net)

void __net_exit smc_sysctl_net_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->smc.smc_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->smc.smc_hdr);
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 3e84b31c355a..44996af61999 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -52,7 +52,7 @@ int __net_init unix_sysctl_register(struct net *net)

void unix_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->unx.ctl->ctl_table_arg;
unregister_net_sysctl_table(net->unx.ctl);
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 7fdeafc838a7..e972930c292b 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -76,7 +76,7 @@ int __net_init xfrm_sysctl_init(struct net *net)

void __net_exit xfrm_sysctl_fini(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;

table = net->xfrm.sysctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->xfrm.sysctl_hdr);

--
2.43.0

2023-12-04 07:54:27

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 14/18] sysctl: move internal interfaces to const struct ctl_table

As a preparation to make all the sysctl code work with
const struct ctl_table switch over the internal function to use the
const variant.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
fs/proc/internal.h | 2 +-
fs/proc/proc_sysctl.c | 81 +++++++++++++++++++++++++-------------------------
include/linux/sysctl.h | 2 +-
3 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 9a8f32f21ff5..36d6bf581688 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -101,7 +101,7 @@ struct proc_inode {
union proc_op op;
struct proc_dir_entry *pde;
struct ctl_table_header *sysctl;
- struct ctl_table *sysctl_entry;
+ const struct ctl_table *sysctl_entry;
struct hlist_node sibling_inodes;
const struct proc_ns_operations *ns_ops;
struct inode vfs_inode;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a398cc77637f..e7fd1680d479 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -86,7 +86,7 @@ static DEFINE_SPINLOCK(sysctl_lock);

static void drop_sysctl_table(struct ctl_table_header *header);
static int sysctl_follow_link(struct ctl_table_header **phead,
- struct ctl_table **pentry);
+ const struct ctl_table **pentry);
static int insert_links(struct ctl_table_header *head);
static void put_links(struct ctl_table_header *header);

@@ -108,11 +108,11 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
}

/* Called under sysctl_lock */
-static struct ctl_table *find_entry(struct ctl_table_header **phead,
+static const struct ctl_table *find_entry(struct ctl_table_header **phead,
struct ctl_dir *dir, const char *name, int namelen)
{
struct ctl_table_header *head;
- struct ctl_table *entry;
+ const struct ctl_table *entry;
struct rb_node *node = dir->root.rb_node;

while (node)
@@ -139,7 +139,7 @@ static struct ctl_table *find_entry(struct ctl_table_header **phead,
return NULL;
}

-static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
+static int insert_entry(struct ctl_table_header *head, const struct ctl_table *entry)
{
struct rb_node *node = &head->node[entry - head->ctl_table].node;
struct rb_node **p = &head->parent->root.rb_node;
@@ -149,7 +149,7 @@ static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)

while (*p) {
struct ctl_table_header *parent_head;
- struct ctl_table *parent_entry;
+ const struct ctl_table *parent_entry;
struct ctl_node *parent_node;
const char *parent_name;
int cmp;
@@ -178,7 +178,7 @@ static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
return 0;
}

-static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
+static void erase_entry(struct ctl_table_header *head, const struct ctl_table *entry)
{
struct rb_node *node = &head->node[entry - head->ctl_table].node;

@@ -187,7 +187,7 @@ static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)

static void init_header(struct ctl_table_header *head,
struct ctl_table_root *root, struct ctl_table_set *set,
- struct ctl_node *node, struct ctl_table *table, size_t table_size)
+ struct ctl_node *node, const struct ctl_table *table, size_t table_size)
{
head->ctl_table = table;
head->ctl_table_size = table_size;
@@ -202,7 +202,7 @@ static void init_header(struct ctl_table_header *head,
head->node = node;
INIT_HLIST_HEAD(&head->inodes);
if (node) {
- struct ctl_table *entry;
+ const struct ctl_table *entry;

list_for_each_table_entry(entry, head) {
node->header = head;
@@ -213,7 +213,7 @@ static void init_header(struct ctl_table_header *head,

static void erase_header(struct ctl_table_header *head)
{
- struct ctl_table *entry;
+ const struct ctl_table *entry;

list_for_each_table_entry(entry, head)
erase_entry(head, entry);
@@ -221,7 +221,7 @@ static void erase_header(struct ctl_table_header *head)

static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
{
- struct ctl_table *entry;
+ const struct ctl_table *entry;
struct ctl_table_header *dir_h = &dir->header;
int err;

@@ -341,12 +341,12 @@ lookup_header_set(struct ctl_table_root *root)
return set;
}

-static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
- struct ctl_dir *dir,
- const char *name, int namelen)
+static const struct ctl_table *lookup_entry(struct ctl_table_header **phead,
+ struct ctl_dir *dir,
+ const char *name, int namelen)
{
struct ctl_table_header *head;
- struct ctl_table *entry;
+ const struct ctl_table *entry;

spin_lock(&sysctl_lock);
entry = find_entry(&head, dir, name, namelen);
@@ -371,10 +371,10 @@ static struct ctl_node *first_usable_entry(struct rb_node *node)
}

static void first_entry(struct ctl_dir *dir,
- struct ctl_table_header **phead, struct ctl_table **pentry)
+ struct ctl_table_header **phead, const struct ctl_table **pentry)
{
struct ctl_table_header *head = NULL;
- struct ctl_table *entry = NULL;
+ const struct ctl_table *entry = NULL;
struct ctl_node *ctl_node;

spin_lock(&sysctl_lock);
@@ -388,10 +388,10 @@ static void first_entry(struct ctl_dir *dir,
*pentry = entry;
}

-static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
+static void next_entry(struct ctl_table_header **phead, const struct ctl_table **pentry)
{
struct ctl_table_header *head = *phead;
- struct ctl_table *entry = *pentry;
+ const struct ctl_table *entry = *pentry;
struct ctl_node *ctl_node = &head->node[entry - head->ctl_table];

spin_lock(&sysctl_lock);
@@ -424,7 +424,7 @@ static int test_perm(int mode, int op)
return -EACCES;
}

-static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
+static int sysctl_perm(struct ctl_table_header *head, const struct ctl_table *table, int op)
{
struct ctl_table_root *root = head->root;
int mode;
@@ -438,7 +438,7 @@ static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, i
}

static struct inode *proc_sys_make_inode(struct super_block *sb,
- struct ctl_table_header *head, struct ctl_table *table)
+ struct ctl_table_header *head, const struct ctl_table *table)
{
struct ctl_table_root *root = head->root;
struct inode *inode;
@@ -511,7 +511,7 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
struct ctl_table_header *head = grab_header(dir);
struct ctl_table_header *h = NULL;
const struct qstr *name = &dentry->d_name;
- struct ctl_table *p;
+ const struct ctl_table *p;
struct inode *inode;
struct dentry *err = ERR_PTR(-ENOENT);
struct ctl_dir *ctl_dir;
@@ -554,7 +554,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
{
struct inode *inode = file_inode(iocb->ki_filp);
struct ctl_table_header *head = grab_header(inode);
- struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+ const struct ctl_table *table = PROC_I(inode)->sysctl_entry;
size_t count = iov_iter_count(iter);
char *kbuf;
ssize_t error;
@@ -628,7 +628,7 @@ static ssize_t proc_sys_write(struct kiocb *iocb, struct iov_iter *iter)
static int proc_sys_open(struct inode *inode, struct file *filp)
{
struct ctl_table_header *head = grab_header(inode);
- struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+ const struct ctl_table *table = PROC_I(inode)->sysctl_entry;

/* sysctl was unregistered */
if (IS_ERR(head))
@@ -646,7 +646,7 @@ static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
{
struct inode *inode = file_inode(filp);
struct ctl_table_header *head = grab_header(inode);
- struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+ const struct ctl_table *table = PROC_I(inode)->sysctl_entry;
__poll_t ret = DEFAULT_POLLMASK;
unsigned long event;

@@ -677,7 +677,7 @@ static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
static bool proc_sys_fill_cache(struct file *file,
struct dir_context *ctx,
struct ctl_table_header *head,
- struct ctl_table *table)
+ const struct ctl_table *table)
{
struct dentry *child, *dir = file->f_path.dentry;
struct inode *inode;
@@ -726,7 +726,7 @@ static bool proc_sys_fill_cache(struct file *file,
static bool proc_sys_link_fill_cache(struct file *file,
struct dir_context *ctx,
struct ctl_table_header *head,
- struct ctl_table *table)
+ const struct ctl_table *table)
{
bool ret = true;

@@ -744,7 +744,7 @@ static bool proc_sys_link_fill_cache(struct file *file,
return ret;
}

-static int scan(struct ctl_table_header *head, struct ctl_table *table,
+static int scan(struct ctl_table_header *head, const struct ctl_table *table,
unsigned long *pos, struct file *file,
struct dir_context *ctx)
{
@@ -768,7 +768,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
{
struct ctl_table_header *head = grab_header(file_inode(file));
struct ctl_table_header *h = NULL;
- struct ctl_table *entry;
+ const struct ctl_table *entry;
struct ctl_dir *ctl_dir;
unsigned long pos;

@@ -801,7 +801,7 @@ static int proc_sys_permission(struct mnt_idmap *idmap,
* are _NOT_ writeable, capabilities or not.
*/
struct ctl_table_header *head;
- struct ctl_table *table;
+ const struct ctl_table *table;
int error;

/* Executable files are not allowed under /proc/sys/ */
@@ -845,7 +845,7 @@ static int proc_sys_getattr(struct mnt_idmap *idmap,
{
struct inode *inode = d_inode(path->dentry);
struct ctl_table_header *head = grab_header(inode);
- struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+ const struct ctl_table *table = PROC_I(inode)->sysctl_entry;

if (IS_ERR(head))
return PTR_ERR(head);
@@ -944,7 +944,7 @@ static struct ctl_dir *find_subdir(struct ctl_dir *dir,
const char *name, int namelen)
{
struct ctl_table_header *head;
- struct ctl_table *entry;
+ const struct ctl_table *entry;

entry = find_entry(&head, dir, name, namelen);
if (!entry)
@@ -1055,12 +1055,12 @@ static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
}

static int sysctl_follow_link(struct ctl_table_header **phead,
- struct ctl_table **pentry)
+ const struct ctl_table **pentry)
{
struct ctl_table_header *head;
+ const struct ctl_table *entry;
struct ctl_table_root *root;
struct ctl_table_set *set;
- struct ctl_table *entry;
struct ctl_dir *dir;
int ret;

@@ -1087,7 +1087,7 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
return ret;
}

-static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
+static int sysctl_err(const char *path, const struct ctl_table *table, char *fmt, ...)
{
struct va_format vaf;
va_list args;
@@ -1103,7 +1103,7 @@ static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
return -EINVAL;
}

-static int sysctl_check_table_array(const char *path, struct ctl_table *table)
+static int sysctl_check_table_array(const char *path, const struct ctl_table *table)
{
int err = 0;

@@ -1128,7 +1128,7 @@ static int sysctl_check_table_array(const char *path, struct ctl_table *table)

static int sysctl_check_table(const char *path, struct ctl_table_header *header)
{
- struct ctl_table *entry;
+ const struct ctl_table *entry;
int err = 0;
list_for_each_table_entry(entry, header) {
if ((entry->proc_handler == proc_dostring) ||
@@ -1162,8 +1162,9 @@ static int sysctl_check_table(const char *path, struct ctl_table_header *header)

static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table_header *head)
{
- struct ctl_table *link_table, *entry, *link;
+ struct ctl_table *link_table, *link;
struct ctl_table_header *links;
+ const struct ctl_table *entry;
struct ctl_node *node;
char *link_name;
int nr_entries, name_bytes;
@@ -1210,7 +1211,7 @@ static bool get_links(struct ctl_dir *dir,
struct ctl_table_root *link_root)
{
struct ctl_table_header *tmp_head;
- struct ctl_table *entry, *link;
+ const struct ctl_table *entry, *link;

/* Are there links available for every entry in table? */
list_for_each_table_entry(entry, header) {
@@ -1463,7 +1464,7 @@ static void put_links(struct ctl_table_header *header)
struct ctl_table_root *root = header->root;
struct ctl_dir *parent = header->parent;
struct ctl_dir *core_parent;
- struct ctl_table *entry;
+ const struct ctl_table *entry;

if (header->set == root_set)
return;
@@ -1474,7 +1475,7 @@ static void put_links(struct ctl_table_header *header)

list_for_each_table_entry(entry, header) {
struct ctl_table_header *link_head;
- struct ctl_table *link;
+ const struct ctl_table *link;
const char *name = entry->procname;

link = find_entry(&link_head, core_parent, name, strlen(name));
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 061ea65104be..2f4d577f2e93 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -162,7 +162,7 @@ struct ctl_node {
struct ctl_table_header {
union {
struct {
- struct ctl_table *ctl_table;
+ const struct ctl_table *ctl_table;
int ctl_table_size;
int used;
int count;

--
2.43.0

2023-12-04 08:08:54

by Thomas Weißschuh

[permalink] [raw]
Subject: [PATCH v2 16/18] const_structs.checkpatch: add ctl_table

Now that the sysctl core can handle "const struct ctl_table", make
sure that new usages of the struct already enter the tree as const.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
scripts/const_structs.checkpatch | 1 +
1 file changed, 1 insertion(+)

diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch
index 188412aa2757..0621c2d652bb 100644
--- a/scripts/const_structs.checkpatch
+++ b/scripts/const_structs.checkpatch
@@ -5,6 +5,7 @@ block_device_operations
clk_ops
comedi_lrange
component_ops
+ctl_table
dentry_operations
dev_pm_ops
dma_map_ops

--
2.43.0

2023-12-04 22:12:55

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 05/18] seccomp: constify ctl_table arguments of utility functions

On Mon, Dec 04, 2023 at 08:52:18AM +0100, Thomas Wei?schuh wrote:
> In a future commit the proc_handlers themselves will change to
> "const struct ctl_table". As a preparation for that adapt the internal
> helpers.
>
> Signed-off-by: Thomas Wei?schuh <[email protected]>

Acked-by: Kees Cook <[email protected]>

--
Kees Cook

2023-12-04 22:15:03

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 08/18] stackleak: don't modify ctl_table argument

On Mon, Dec 04, 2023 at 08:52:21AM +0100, Thomas Wei?schuh wrote:
> In a future commit the proc_handlers will change to
> "const struct ctl_table".
> As a preparation for that adapt the logic to work with a temporary
> variable, similar to how it is done in other parts of the kernel.
>
> Signed-off-by: Thomas Wei?schuh <[email protected]>

Looks good -- thanks for catching the table-modification cases.

Acked-by: Kees Cook <[email protected]>

--
Kees Cook

2023-12-04 22:17:33

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers

On Mon, Dec 04, 2023 at 08:52:25AM +0100, Thomas Wei?schuh wrote:
> In a future commit the sysctl core will only use
> "const struct ctl_table". As a preparation for that adapt all the proc
> handlers.
>
> Signed-off-by: Thomas Wei?schuh <[email protected]>

Reviewed-by: Kees Cook <[email protected]> # security/*

--
Kees Cook

2023-12-05 05:50:27

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> Tested by booting and with the sysctl selftests on x86.

Can I trouble you to rebase on sysctl-next?

https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next

Luis

2023-12-05 08:04:28

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Weißschuh wrote:
> > Tested by booting and with the sysctl selftests on x86.
>
> Can I trouble you to rebase on sysctl-next?
>
> https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next

Will do.

Note:

I noticed that patch "sysctl: move sysctl type to ctl_table_header" from
this series seems to be the better alternative to
commit fd696ee2395755a ("sysctl: Fix out of bounds access for empty sysctl registers")
which is currently on sysctl-next.

The patch from the series should only depend on
"sysctl: drop sysctl_is_perm_empty_ctl_table" from my series.

Thomas

2023-12-05 09:51:20

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers

Hi Thomas,

kernel test robot noticed the following build errors:

[auto build test ERROR on netfilter-nf/main]
[also build test ERROR on akpm-mm/mm-everything linus/master v6.7-rc4]
[cannot apply to nf-next/master next-20231205]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Wei-schuh/sysctl-delete-unused-define-SYSCTL_PERM_EMPTY_DIR/20231204-165306
base: git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git main
patch link: https://lore.kernel.org/r/20231204-const-sysctl-v2-12-7a5060b11447%40weissschuh.net
patch subject: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers
config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20231205/[email protected]/config)
compiler: s390-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231205/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

arch/s390/appldata/appldata_base.c: In function 'appldata_register_ops':
>> arch/s390/appldata/appldata_base.c:363:40: error: assignment to 'int (*)(const struct ctl_table *, int, void *, size_t *, loff_t *)' {aka 'int (*)(const struct ctl_table *, int, void *, long unsigned int *, long long int *)'} from incompatible pointer type 'int (*)(struct ctl_table *, int, void *, size_t *, loff_t *)' {aka 'int (*)(struct ctl_table *, int, void *, long unsigned int *, long long int *)'} [-Werror=incompatible-pointer-types]
363 | ops->ctl_table[0].proc_handler = appldata_generic_handler;
| ^
cc1: some warnings being treated as errors


vim +363 arch/s390/appldata/appldata_base.c

^1da177e4c3f41 Linus Torvalds 2005-04-16 340
^1da177e4c3f41 Linus Torvalds 2005-04-16 341
^1da177e4c3f41 Linus Torvalds 2005-04-16 342 /************************* module-ops management *****************************/
^1da177e4c3f41 Linus Torvalds 2005-04-16 343 /*
^1da177e4c3f41 Linus Torvalds 2005-04-16 344 * appldata_register_ops()
^1da177e4c3f41 Linus Torvalds 2005-04-16 345 *
^1da177e4c3f41 Linus Torvalds 2005-04-16 346 * update ops list, register /proc/sys entries
^1da177e4c3f41 Linus Torvalds 2005-04-16 347 */
^1da177e4c3f41 Linus Torvalds 2005-04-16 348 int appldata_register_ops(struct appldata_ops *ops)
^1da177e4c3f41 Linus Torvalds 2005-04-16 349 {
13f8b7c5e6fa13 Roel Kluin 2008-10-28 350 if (ops->size > APPLDATA_MAX_REC_SIZE)
37e3a6ac5a3046 Heiko Carstens 2007-11-20 351 return -EINVAL;
^1da177e4c3f41 Linus Torvalds 2005-04-16 352
fdd9da76e2dec0 Joel Granados 2023-10-02 353 ops->ctl_table = kcalloc(1, sizeof(struct ctl_table), GFP_KERNEL);
37e3a6ac5a3046 Heiko Carstens 2007-11-20 354 if (!ops->ctl_table)
^1da177e4c3f41 Linus Torvalds 2005-04-16 355 return -ENOMEM;
^1da177e4c3f41 Linus Torvalds 2005-04-16 356
b1ad171efa089a Gerald Schaefer 2009-04-23 357 mutex_lock(&appldata_ops_mutex);
^1da177e4c3f41 Linus Torvalds 2005-04-16 358 list_add(&ops->list, &appldata_ops_list);
b1ad171efa089a Gerald Schaefer 2009-04-23 359 mutex_unlock(&appldata_ops_mutex);
^1da177e4c3f41 Linus Torvalds 2005-04-16 360
7db12246306ea6 Luis Chamberlain 2023-03-10 361 ops->ctl_table[0].procname = ops->name;
7db12246306ea6 Luis Chamberlain 2023-03-10 362 ops->ctl_table[0].mode = S_IRUGO | S_IWUSR;
7db12246306ea6 Luis Chamberlain 2023-03-10 @363 ops->ctl_table[0].proc_handler = appldata_generic_handler;
7db12246306ea6 Luis Chamberlain 2023-03-10 364 ops->ctl_table[0].data = ops;
^1da177e4c3f41 Linus Torvalds 2005-04-16 365
9edbfe92a0a135 Joel Granados 2023-08-09 366 ops->sysctl_header = register_sysctl_sz(appldata_proc_name, ops->ctl_table, 1);
37e3a6ac5a3046 Heiko Carstens 2007-11-20 367 if (!ops->sysctl_header)
37e3a6ac5a3046 Heiko Carstens 2007-11-20 368 goto out;
^1da177e4c3f41 Linus Torvalds 2005-04-16 369 return 0;
37e3a6ac5a3046 Heiko Carstens 2007-11-20 370 out:
b1ad171efa089a Gerald Schaefer 2009-04-23 371 mutex_lock(&appldata_ops_mutex);
37e3a6ac5a3046 Heiko Carstens 2007-11-20 372 list_del(&ops->list);
b1ad171efa089a Gerald Schaefer 2009-04-23 373 mutex_unlock(&appldata_ops_mutex);
37e3a6ac5a3046 Heiko Carstens 2007-11-20 374 kfree(ops->ctl_table);
37e3a6ac5a3046 Heiko Carstens 2007-11-20 375 return -ENOMEM;
^1da177e4c3f41 Linus Torvalds 2005-04-16 376 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 377

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-12-05 16:07:06

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers

Hi Thomas,

kernel test robot noticed the following build errors:

[auto build test ERROR on netfilter-nf/main]
[also build test ERROR on akpm-mm/mm-everything linus/master v6.7-rc4]
[cannot apply to nf-next/master next-20231205]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Wei-schuh/sysctl-delete-unused-define-SYSCTL_PERM_EMPTY_DIR/20231204-165306
base: git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git main
patch link: https://lore.kernel.org/r/20231204-const-sysctl-v2-12-7a5060b11447%40weissschuh.net
patch subject: [PATCH v2 12/18] sysctl: treewide: constify the ctl_table argument of handlers
config: arm64-defconfig (https://download.01.org/0day-ci/archive/20231205/[email protected]/config)
compiler: aarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231205/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

| ^~~~~~
drivers/perf/arm_pmuv3.c:144:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD'
144 | [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:122:65: warning: initialized field overwritten [-Woverride-init]
122 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x0041
| ^~~~~~
drivers/perf/arm_pmuv3.c:145:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR'
145 | [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:122:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[0][1][0]')
122 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x0041
| ^~~~~~
drivers/perf/arm_pmuv3.c:145:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR'
145 | [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:124:65: warning: initialized field overwritten [-Woverride-init]
124 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x0043
| ^~~~~~
drivers/perf/arm_pmuv3.c:146:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR'
146 | [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:124:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[0][1][1]')
124 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x0043
| ^~~~~~
drivers/perf/arm_pmuv3.c:146:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR'
146 | [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:133:65: warning: initialized field overwritten [-Woverride-init]
133 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x004E
| ^~~~~~
drivers/perf/arm_pmuv3.c:148:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD'
148 | [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:133:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][0][0]')
133 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x004E
| ^~~~~~
drivers/perf/arm_pmuv3.c:148:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD'
148 | [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:134:65: warning: initialized field overwritten [-Woverride-init]
134 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x004F
| ^~~~~~
drivers/perf/arm_pmuv3.c:149:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR'
149 | [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:134:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][1][0]')
134 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x004F
| ^~~~~~
drivers/perf/arm_pmuv3.c:149:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR'
149 | [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:131:65: warning: initialized field overwritten [-Woverride-init]
131 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x004C
| ^~~~~~
drivers/perf/arm_pmuv3.c:150:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD'
150 | [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:131:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][0][1]')
131 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x004C
| ^~~~~~
drivers/perf/arm_pmuv3.c:150:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD'
150 | [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:132:65: warning: initialized field overwritten [-Woverride-init]
132 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x004D
| ^~~~~~
drivers/perf/arm_pmuv3.c:151:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR'
151 | [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:132:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][1][1]')
132 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x004D
| ^~~~~~
drivers/perf/arm_pmuv3.c:151:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR'
151 | [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:148:65: warning: initialized field overwritten [-Woverride-init]
148 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x0060
| ^~~~~~
drivers/perf/arm_pmuv3.c:153:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD'
153 | [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:148:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[6][0][0]')
148 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x0060
| ^~~~~~
drivers/perf/arm_pmuv3.c:153:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD'
153 | [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:149:65: warning: initialized field overwritten [-Woverride-init]
149 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x0061
| ^~~~~~
drivers/perf/arm_pmuv3.c:154:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR'
154 | [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/perf/arm_pmuv3.h:149:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[6][1][0]')
149 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x0061
| ^~~~~~
drivers/perf/arm_pmuv3.c:154:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR'
154 | [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/perf/arm_pmuv3.c:1174:35: error: initialization of 'int (*)(const struct ctl_table *, int, void *, size_t *, loff_t *)' {aka 'int (*)(const struct ctl_table *, int, void *, long unsigned int *, long long int *)'} from incompatible pointer type 'int (*)(struct ctl_table *, int, void *, size_t *, loff_t *)' {aka 'int (*)(struct ctl_table *, int, void *, long unsigned int *, long long int *)'} [-Werror=incompatible-pointer-types]
1174 | .proc_handler = armv8pmu_proc_user_access_handler,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/perf/arm_pmuv3.c:1174:35: note: (near initialization for 'armv8_pmu_sysctl_table[0].proc_handler')
cc1: some warnings being treated as errors


vim +1174 drivers/perf/arm_pmuv3.c

83a7a4d643d33a arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1167
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1168 static struct ctl_table armv8_pmu_sysctl_table[] = {
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1169 {
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1170 .procname = "perf_user_access",
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1171 .data = &sysctl_perf_user_access,
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1172 .maxlen = sizeof(unsigned int),
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1173 .mode = 0644,
83a7a4d643d33a arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 @1174 .proc_handler = armv8pmu_proc_user_access_handler,
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1175 .extra1 = SYSCTL_ZERO,
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1176 .extra2 = SYSCTL_ONE,
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1177 },
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1178 };
e2012600810c9d arch/arm64/kernel/perf_event.c Rob Herring 2021-12-08 1179

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-12-05 17:19:23

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Hi Luis, Joel,

On 2023-12-05 09:04:08+0100, Thomas Weißschuh wrote:
> On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Weißschuh wrote:
> > > Tested by booting and with the sysctl selftests on x86.
> >
> > Can I trouble you to rebase on sysctl-next?
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
>
> Will do.

The rebased series is now available at
https://git.sr.ht/~t-8ch/linux b4/const-sysctl

Nothing much has changed in contrast to v2.
The only functional change so far is the initialization of
ctl_table_header::type in init_header().

I'll wait for Joels and maybe some more reviews before resending it.

> [..]

For the future I think it would make sense to combine the tree-wide constification
of the structs with the removal of the sentinel values.

This would reduce the impacts of the maintainers.


Thomas

2023-12-05 22:27:19

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 05, 2023 at 06:16:53PM +0100, Thomas Wei?schuh wrote:
> Hi Luis, Joel,
>
> On 2023-12-05 09:04:08+0100, Thomas Wei?schuh wrote:
> > On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> > > > Tested by booting and with the sysctl selftests on x86.
> > >
> > > Can I trouble you to rebase on sysctl-next?
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
> >
> > Will do.
>
> The rebased series is now available at
> https://git.sr.ht/~t-8ch/linux b4/const-sysctl

I've applied this to sysctl-next as this all looks very sensible to me,
except one patch which I'll chime in on, but I'm merging it to
sysctl-next now without a promise to get this in as I really would like
this to soak in on linux-next for a bit even if it does not get merged
in the next kernel release. Exposing it on linux-next will surely
iron out run time issues fast.

> Nothing much has changed in contrast to v2.
> The only functional change so far is the initialization of
> ctl_table_header::type in init_header().
>
> I'll wait for Joels and maybe some more reviews before resending it.

It all is very trivial stuff, except a few patches, but it all is making
sense, so my ask is to address feedback this week and post next week
a new set so we can have changes merged as-is for Linux in case this
really doesn't break anything.

For some reason I raccall seeing som hacky sysclts that shared and
modified an entry somewhere but the exact sysctl phases me, and I just
cannot recall.

> > [..]
>
> For the future I think it would make sense to combine the tree-wide constification
> of the structs with the removal of the sentinel values.
>
> This would reduce the impacts of the maintainers.

Indeed.

Luis

2023-12-05 22:34:04

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Wei?schuh wrote:
> @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> return -EROFS;
>
> /* Am I creating a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(header)) {
> + if (header->ctl_table == sysctl_mount_point ||
> + sysctl_is_perm_empty_ctl_header(header)) {
> if (!RB_EMPTY_ROOT(&dir->root))
> return -EINVAL;
> sysctl_set_perm_empty_ctl_header(dir_h);

While you're at it.

This just made me cringe, and curious if some other changes
could be done to make this obviously clear during patch review
that this is safe.

Luis

2023-12-05 22:41:47

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > return -EROFS;
> >
> > /* Am I creating a permanently empty directory? */
> > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > + if (header->ctl_table == sysctl_mount_point ||
> > + sysctl_is_perm_empty_ctl_header(header)) {
> > if (!RB_EMPTY_ROOT(&dir->root))
> > return -EINVAL;
> > sysctl_set_perm_empty_ctl_header(dir_h);
>
> While you're at it.

This hunk is completely gone in v3/the code that you merged.

> This just made me cringe, and curious if some other changes
> could be done to make this obviously clear during patch review
> that this is safe.

Which kind of unsafety do you envision here?

2023-12-05 22:51:06

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
>
> On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > return -EROFS;
> > >
> > > /* Am I creating a permanently empty directory? */
> > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > + if (header->ctl_table == sysctl_mount_point ||
> > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > if (!RB_EMPTY_ROOT(&dir->root))
> > > return -EINVAL;
> > > sysctl_set_perm_empty_ctl_header(dir_h);
> >
> > While you're at it.
>
> This hunk is completely gone in v3/the code that you merged.

It is worse in that it is not obvious:

+ if (table == sysctl_mount_point)
+ sysctl_set_perm_empty_ctl_header(head);

> Which kind of unsafety do you envision here?

Making the code obvious during patch review hy this is needed /
special, and if we special case this, why not remove enum, and make it
specific to only that one table. The catch is that it is not
immediately obvious that we actually call
sysctl_set_perm_empty_ctl_header() in other places, and it begs the
question if this can be cleaned up somehow.

Luis

2023-12-06 05:53:30

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> >
> > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > return -EROFS;
> > > >
> > > > /* Am I creating a permanently empty directory? */
> > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > return -EINVAL;
> > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > >
> > > While you're at it.
> >
> > This hunk is completely gone in v3/the code that you merged.
>
> It is worse in that it is not obvious:
>
> + if (table == sysctl_mount_point)
> + sysctl_set_perm_empty_ctl_header(head);
>
> > Which kind of unsafety do you envision here?
>
> Making the code obvious during patch review hy this is needed /
> special, and if we special case this, why not remove enum, and make it
> specific to only that one table. The catch is that it is not
> immediately obvious that we actually call
> sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> question if this can be cleaned up somehow.

Making it specific won't work because the flag needs to be transferred
from the leaf table to the table representing the directory.

What do you think of the aproach taken in the attached patch?
(On top of current sysctl-next, including my series)

Note: Current sysctl-next ist still based on v6.6.


Attachments:
(No filename) (1.78 kB)
0001-sysctl-simplify-handling-of-permanently-empty-direct.patch (7.50 kB)
Download all attachments

2023-12-07 10:44:48

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Hey Thomas

You have a couple of test bot issues for your 12/18 patch. Can you
please address those for your next version.

On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> Problem description:
>
> The kernel contains a lot of struct ctl_table throught the tree.
> These are very often 'static' definitions.
> It would be good to make the tables unmodifiable by marking them "const"
Here I would remove "It would be good to". Just state it: "Make the
tables unmodifiable...."

> to avoid accidental or malicious modifications.
> This is in line with a general effort to move as much data as possible
> into .rodata. (See for example[0] and [1])
If you could find more examples, it would make a better case.

>
> Unfortunately the tables can not be made const right now because the
> core registration functions expect mutable tables.
>
> This is for two main reasons:
>
> 1) sysctl_{set,clear}_perm_empty_ctl_header in the sysctl core modify
> the table.
> 2) The table is passed to the handler function as a non-const pointer.
>
> This series migrates the core and all handlers.
awesome!

>
> Structure of the series:
>
> Patch 1-3: Cleanup patches
> Patch 4-7: Non-logic preparation patches
> Patch 8: Preparation patch changing a bit of logic
> Patch 9-12: Treewide changes to handler function signature
> Patch 13-14: Adaption of the sysctl core implementation
> Patch 15: Adaption of the sysctl core interface
> Patch 16: New entry for checkpatch
> Patch 17-18: Constification of existing "struct ctl_table"s
>
> Tested by booting and with the sysctl selftests on x86.
>
> Note:
>
> This is intentionally sent only to a small number of people as I'd like
> to get some more sysctl core-maintainer feedback before sending this to
> essentially everybody.
When you do send it to the broader audience, you should chunk up your big
patches (12/18 and 11/18) and this is why:
1. To avoid mail rejections from lists:
You have to tell a lot of people about the changes in one mail. That
will make mail header too big for some lists and it will be rejected.
This happened to me with [3]
2. Avoid being rejected for the wrong reasons :)
Maintainers are busy ppl and sending them a set with so many files
may elicit a rejection on the grounds that it involves too many
subsystems at the same time.
I suggest you chunk it up with directories in mind. Something similar to
what I did for [4] where I divided stuff that when for fs/*, kernel/*,
net/*, arch/* and drivers/*. That will complicate your patch a tad
because you have to ensure that the tree can be compiled/run for every
commit. But it will pay off once you push it to the broader public.

[3] https://lore.kernel.org/all/[email protected]
[4] https://lore.kernel.org/all/[email protected]
>
> [0] 43a7206b0963 ("driver core: class: make class_register() take a const *")
> [1] https://lore.kernel.org/lkml/[email protected]/
>
> ---
> Changes in v2:
> - Migrate all handlers.
> - Remove intermediate "proc_handler_new" step (Thanks Joel).
> - Drop RFC status.
> - Prepare other parts of the tree.
> - Link to v1: https://lore.kernel.org/r/[email protected]
>
> ---
> Thomas Wei?schuh (18):
> watchdog/core: remove sysctl handlers from public header
> sysctl: delete unused define SYSCTL_PERM_EMPTY_DIR
> sysctl: drop sysctl_is_perm_empty_ctl_table
> cgroup: bpf: constify ctl_table arguments and fields
> seccomp: constify ctl_table arguments of utility functions
> hugetlb: constify ctl_table arguments of utility functions
> utsname: constify ctl_table arguments of utility function
> stackleak: don't modify ctl_table argument
> sysctl: treewide: constify ctl_table_root::set_ownership
> sysctl: treewide: constify ctl_table_root::permissions
> sysctl: treewide: constify ctl_table_header::ctl_table_arg
> sysctl: treewide: constify the ctl_table argument of handlers
> sysctl: move sysctl type to ctl_table_header
> sysctl: move internal interfaces to const struct ctl_table
> sysctl: allow registration of const struct ctl_table
> const_structs.checkpatch: add ctl_table
> sysctl: make ctl_table sysctl_mount_point const
> sysctl: constify standard sysctl tables
>
> arch/arm64/kernel/armv8_deprecated.c | 2 +-
> arch/arm64/kernel/fpsimd.c | 2 +-
> arch/s390/appldata/appldata_base.c | 8 +--
> arch/s390/kernel/debug.c | 2 +-
> arch/s390/kernel/topology.c | 2 +-
> arch/s390/mm/cmm.c | 6 +-
> arch/x86/kernel/itmt.c | 2 +-
> drivers/cdrom/cdrom.c | 4 +-
> drivers/char/random.c | 4 +-
> drivers/macintosh/mac_hid.c | 2 +-
> drivers/net/vrf.c | 4 +-
> drivers/parport/procfs.c | 12 ++--
> fs/coredump.c | 2 +-
> fs/dcache.c | 4 +-
> fs/drop_caches.c | 2 +-
> fs/exec.c | 4 +-
> fs/file_table.c | 2 +-
> fs/fs-writeback.c | 2 +-
> fs/inode.c | 4 +-
> fs/pipe.c | 2 +-
> fs/proc/internal.h | 2 +-
> fs/proc/proc_sysctl.c | 102 +++++++++++++++---------------
> fs/quota/dquot.c | 2 +-
> fs/xfs/xfs_sysctl.c | 6 +-
> include/linux/bpf-cgroup.h | 2 +-
> include/linux/filter.h | 2 +-
> include/linux/ftrace.h | 4 +-
> include/linux/mm.h | 8 +--
> include/linux/nmi.h | 7 --
> include/linux/perf_event.h | 6 +-
> include/linux/security.h | 2 +-
> include/linux/sysctl.h | 78 +++++++++++------------
> include/linux/vmstat.h | 6 +-
> include/linux/writeback.h | 2 +-
> include/net/ndisc.h | 2 +-
> include/net/neighbour.h | 6 +-
> include/net/netfilter/nf_hooks_lwtunnel.h | 2 +-
> ipc/ipc_sysctl.c | 12 ++--
> ipc/mq_sysctl.c | 2 +-
> kernel/bpf/cgroup.c | 2 +-
> kernel/bpf/syscall.c | 4 +-
> kernel/delayacct.c | 4 +-
> kernel/events/callchain.c | 2 +-
> kernel/events/core.c | 4 +-
> kernel/fork.c | 2 +-
> kernel/hung_task.c | 4 +-
> kernel/kexec_core.c | 2 +-
> kernel/kprobes.c | 2 +-
> kernel/latencytop.c | 4 +-
> kernel/pid_namespace.c | 2 +-
> kernel/pid_sysctl.h | 2 +-
> kernel/printk/internal.h | 2 +-
> kernel/printk/printk.c | 2 +-
> kernel/printk/sysctl.c | 5 +-
> kernel/sched/core.c | 8 +--
> kernel/sched/rt.c | 12 ++--
> kernel/sched/topology.c | 2 +-
> kernel/seccomp.c | 8 +--
> kernel/stackleak.c | 9 +--
> kernel/sysctl.c | 84 ++++++++++++------------
> kernel/time/timer.c | 2 +-
> kernel/trace/ftrace.c | 2 +-
> kernel/trace/trace.c | 2 +-
> kernel/trace/trace_events_user.c | 2 +-
> kernel/trace/trace_stack.c | 2 +-
> kernel/ucount.c | 4 +-
> kernel/umh.c | 2 +-
> kernel/utsname_sysctl.c | 4 +-
> kernel/watchdog.c | 15 +++--
> mm/compaction.c | 8 +--
> mm/hugetlb.c | 10 +--
> mm/page-writeback.c | 18 +++---
> mm/page_alloc.c | 22 +++----
> mm/util.c | 12 ++--
> mm/vmstat.c | 4 +-
> net/ax25/sysctl_net_ax25.c | 2 +-
> net/bridge/br_netfilter_hooks.c | 6 +-
> net/core/neighbour.c | 24 +++----
> net/core/sysctl_net_core.c | 22 +++----
> net/ieee802154/6lowpan/reassembly.c | 2 +-
> net/ipv4/devinet.c | 8 +--
> net/ipv4/ip_fragment.c | 2 +-
> net/ipv4/route.c | 4 +-
> net/ipv4/sysctl_net_ipv4.c | 35 +++++-----
> net/ipv4/xfrm4_policy.c | 2 +-
> net/ipv6/addrconf.c | 29 +++++----
> net/ipv6/ndisc.c | 4 +-
> net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +-
> net/ipv6/reassembly.c | 2 +-
> net/ipv6/route.c | 2 +-
> net/ipv6/sysctl_net_ipv6.c | 10 +--
> net/ipv6/xfrm6_policy.c | 2 +-
> net/mpls/af_mpls.c | 8 +--
> net/mptcp/ctrl.c | 2 +-
> net/netfilter/ipvs/ip_vs_ctl.c | 16 ++---
> net/netfilter/nf_conntrack_standalone.c | 4 +-
> net/netfilter/nf_hooks_lwtunnel.c | 2 +-
> net/netfilter/nf_log.c | 4 +-
> net/phonet/sysctl.c | 2 +-
> net/rds/tcp.c | 4 +-
> net/sctp/sysctl.c | 30 ++++-----
> net/smc/smc_sysctl.c | 2 +-
> net/sunrpc/sysctl.c | 6 +-
> net/sunrpc/xprtrdma/svc_rdma.c | 2 +-
> net/sysctl_net.c | 4 +-
> net/unix/sysctl_net_unix.c | 2 +-
> net/xfrm/xfrm_sysctl.c | 2 +-
> scripts/const_structs.checkpatch | 1 +
> security/apparmor/lsm.c | 2 +-
> security/min_addr.c | 2 +-
> security/yama/yama_lsm.c | 2 +-
> 111 files changed, 427 insertions(+), 428 deletions(-)
> ---
> base-commit: 33cc938e65a98f1d29d0a18403dbbee050dcad9a
> change-id: 20231116-const-sysctl-e14624f1295c
>
> Best regards,
> --
> Thomas Wei?schuh <[email protected]>
>

--

Joel Granados


Attachments:
(No filename) (10.78 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 11:05:51

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 05, 2023 at 09:04:08AM +0100, Thomas Wei?schuh wrote:
> On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> > > Tested by booting and with the sysctl selftests on x86.
> >
> > Can I trouble you to rebase on sysctl-next?
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
>
> Will do.
>
> Note:
>
> I noticed that patch "sysctl: move sysctl type to ctl_table_header" from
> this series seems to be the better alternative to
> commit fd696ee2395755a ("sysctl: Fix out of bounds access for empty sysctl registers")
> which is currently on sysctl-next.
Indeed. By taking this out of the ctl_table, we would not need to make
sure that we don't touch that (potentially non-existing) first element.

This is what I think should be done (@Luis @Kees chime in if you have any
thoughts):
1. Leave the current fix for 6.7. AFAIK, it is already queued for that
release and it is a bit late in the cycle to put anything new in.
2. I think this patch has value on its own as a better solution to the
"access invalid memory" issue. @thomas: remove this patch from your
const set and send it in a different patch series.
3. const patchset would need to go on top of the new set.

Having it on its own will allow it to go in faster and make it easier to
review without having to thinkg about the const stuff as well.

Best
>
> The patch from the series should only depend on
> "sysctl: drop sysctl_is_perm_empty_ctl_table" from my series.
>
> Thomas

--

Joel Granados


Attachments:
(No filename) (1.60 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 11:20:10

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 05, 2023 at 06:16:53PM +0100, Thomas Wei?schuh wrote:
> Hi Luis, Joel,
>
> On 2023-12-05 09:04:08+0100, Thomas Wei?schuh wrote:
> > On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> > > > Tested by booting and with the sysctl selftests on x86.
> > >
> > > Can I trouble you to rebase on sysctl-next?
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
> >
> > Will do.
>
> The rebased series is now available at
> https://git.sr.ht/~t-8ch/linux b4/const-sysctl
>
> Nothing much has changed in contrast to v2.
> The only functional change so far is the initialization of
> ctl_table_header::type in init_header().
>
> I'll wait for Joels and maybe some more reviews before resending it.
>
> > [..]
>
> For the future I think it would make sense to combine the tree-wide constification
> of the structs with the removal of the sentinel values.
I don't see how these two would fit. And this is why:
1. The "remove sentinel" stuff is almost done. With the sets going into
6.7 we would only be missing everything under net/*. So you would not
be able to combine them (except for the net stuff)
2. The motivation for the two sets is differnt. This would confuse
rather than simplify the process.
3. In order to introduce the const stuff we would have to go through
another round of "convincing" which can potentially derail the
"remove sentinel" stuff.

I would *not* like to combine them. I think the const set can stand on
its own.
>
> This would reduce the impacts of the maintainers.
>
>
> Thomas

--

Joel Granados


Attachments:
(No filename) (1.68 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 11:23:46

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 05, 2023 at 02:27:04PM -0800, Luis Chamberlain wrote:
> On Tue, Dec 05, 2023 at 06:16:53PM +0100, Thomas Wei?schuh wrote:
> > Hi Luis, Joel,
> >
> > On 2023-12-05 09:04:08+0100, Thomas Wei?schuh wrote:
> > > On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > > > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> > > > > Tested by booting and with the sysctl selftests on x86.
> > > >
> > > > Can I trouble you to rebase on sysctl-next?
> > > >
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
> > >
> > > Will do.
> >
> > The rebased series is now available at
> > https://git.sr.ht/~t-8ch/linux b4/const-sysctl
>
> I've applied this to sysctl-next as this all looks very sensible to me,
> except one patch which I'll chime in on, but I'm merging it to
That is the "move sysctl type to ctl_table_header" right?

> sysctl-next now without a promise to get this in as I really would like
> this to soak in on linux-next for a bit even if it does not get merged
> in the next kernel release. Exposing it on linux-next will surely
> iron out run time issues fast.
+1 for soaking it :)

>
> > Nothing much has changed in contrast to v2.
> > The only functional change so far is the initialization of
> > ctl_table_header::type in init_header().
> >
> > I'll wait for Joels and maybe some more reviews before resending it.
>
> It all is very trivial stuff, except a few patches, but it all is making
> sense, so my ask is to address feedback this week and post next week
> a new set so we can have changes merged as-is for Linux in case this
> really doesn't break anything.
Any thoughts on the size of the tree-wide patches?

>
> For some reason I raccall seeing som hacky sysclts that shared and
> modified an entry somewhere but the exact sysctl phases me, and I just
> cannot recall.
Its probably in net/*. There is were they are really taking advantage of
ctl_table.

>
> > > [..]
> >
> > For the future I think it would make sense to combine the tree-wide constification
> > of the structs with the removal of the sentinel values.
> >
> > This would reduce the impacts of the maintainers.
>
> Indeed.
>
> Luis

--

Joel Granados


Attachments:
(No filename) (2.24 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 11:31:39

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

This is the patch that I said could be on its own to facilitate review

On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Wei?schuh wrote:
> In a future commit the sysctl core will only use
> "const struct ctl_table". As a preparation for that move this mutable
> field from "struct ctl_table" to "struct ctl_table_header".
>
> This is also more correct in general as this is in fact a property of
> the header and not the table itself.
>
> Signed-off-by: Thomas Wei?schuh <[email protected]>
> ---
> fs/proc/proc_sysctl.c | 11 ++++++-----
> include/linux/sysctl.h | 22 +++++++++++-----------
> 2 files changed, 17 insertions(+), 16 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index 689a30196d0c..a398cc77637f 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -31,7 +31,7 @@ static const struct inode_operations proc_sys_dir_operations;
>
> /* Support for permanently empty directories */
> static struct ctl_table sysctl_mount_point[] = {
> - {.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
> + { }
> };
>
> /**
> @@ -49,11 +49,11 @@ struct ctl_table_header *register_sysctl_mount_point(const char *path)
> EXPORT_SYMBOL(register_sysctl_mount_point);
>
> #define sysctl_is_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> + (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> #define sysctl_set_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> + (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> #define sysctl_clear_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
> + (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
>
> void proc_sys_poll_notify(struct ctl_table_poll *poll)
> {
> @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> return -EROFS;
>
> /* Am I creating a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(header)) {
> + if (header->ctl_table == sysctl_mount_point ||
> + sysctl_is_perm_empty_ctl_header(header)) {
Why do you have to check that it is equal to sysctl_mount_point? It
should be enough to make sure that the type of PERMANENTLY_EMPTY. no?

> if (!RB_EMPTY_ROOT(&dir->root))
> return -EINVAL;
> sysctl_set_perm_empty_ctl_header(dir_h);
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index ada36ef8cecb..061ea65104be 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -137,17 +137,6 @@ struct ctl_table {
> void *data;
> int maxlen;
> umode_t mode;
> - /**
> - * enum type - Enumeration to differentiate between ctl target types
> - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> - * empty directory target to serve
> - * as mount point.
> - */
> - enum {
> - SYSCTL_TABLE_TYPE_DEFAULT,
> - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> - } type;
> proc_handler *proc_handler; /* Callback for text formatting */
> struct ctl_table_poll *poll;
> void *extra1;
> @@ -188,6 +177,17 @@ struct ctl_table_header {
> struct ctl_dir *parent;
> struct ctl_node *node;
> struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
> + /**
> + * enum type - Enumeration to differentiate between ctl target types
> + * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> + * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> + * empty directory target to serve
> + * as mount point.
> + */
> + enum {
> + SYSCTL_TABLE_TYPE_DEFAULT,
> + SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> + } type;
> };
>
> struct ctl_dir {
>
> --
> 2.43.0
>

--

Joel Granados


Attachments:
(No filename) (3.97 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 12:06:23

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On Tue, Dec 05, 2023 at 02:50:01PM -0800, Luis Chamberlain wrote:
> On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> >
> > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > return -EROFS;
> > > >
> > > > /* Am I creating a permanently empty directory? */
> > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > return -EINVAL;
> > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > >
> > > While you're at it.
> >
> > This hunk is completely gone in v3/the code that you merged.
>
> It is worse in that it is not obvious:
>
> + if (table == sysctl_mount_point)
> + sysctl_set_perm_empty_ctl_header(head);
Notice that the test is done on the header and the set is done on the
dir_h.

I mention this because here you wrote:
"sysctl_set_perm_empty_ctl_header(head)"
instead of
"sysctl_set_perm_empty_ctl_header(dir_h)"

dir_h and head are different.

Was this your concern? or did I miss your point?
>
> > Which kind of unsafety do you envision here?
>
> Making the code obvious during patch review hy this is needed /
> special, and if we special case this, why not remove enum, and make it
> specific to only that one table. The catch is that it is not
> immediately obvious that we actually call
> sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> question if this can be cleaned up somehow.
>
> Luis

--

Joel Granados


Attachments:
(No filename) (1.83 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 12:15:09

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On Wed, Dec 06, 2023 at 06:53:10AM +0100, Thomas Weißschuh wrote:
> On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> > On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> > >
> > > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > > return -EROFS;
> > > > >
> > > > > /* Am I creating a permanently empty directory? */
> > > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > > return -EINVAL;
> > > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > > >
> > > > While you're at it.
> > >
> > > This hunk is completely gone in v3/the code that you merged.
> >
> > It is worse in that it is not obvious:
> >
> > + if (table == sysctl_mount_point)
> > + sysctl_set_perm_empty_ctl_header(head);
> >
> > > Which kind of unsafety do you envision here?
> >
> > Making the code obvious during patch review hy this is needed /
> > special, and if we special case this, why not remove enum, and make it
> > specific to only that one table. The catch is that it is not
> > immediately obvious that we actually call
> > sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> > question if this can be cleaned up somehow.
>
> Making it specific won't work because the flag needs to be transferred
> from the leaf table to the table representing the directory.
>
> What do you think of the aproach taken in the attached patch?
> (On top of current sysctl-next, including my series)
What would this new patch be fixing again? I could not follow ?

Additionally, this might be another reason to set this patch aside :)

>
> Note: Current sysctl-next ist still based on v6.6.

> From 2fb9887fb2a5024c2620f2d694bc6dcc32afde67 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> Date: Wed, 6 Dec 2023 06:17:22 +0100
> Subject: [PATCH] sysctl: simplify handling of permanently empty directories
>
> ---
> fs/proc/proc_sysctl.c | 76 +++++++++++++++++++-----------------------
> include/linux/sysctl.h | 13 ++------
> 2 files changed, 36 insertions(+), 53 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index c92e9b972ada..c4d6d09b0e68 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -17,6 +17,7 @@
> #include <linux/bpf-cgroup.h>
> #include <linux/mount.h>
> #include <linux/kmemleak.h>
> +#include <linux/cleanup.h>
> #include "internal.h"
>
> #define list_for_each_table_entry(entry, header) \
> @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> static const struct file_operations proc_sys_dir_file_operations;
> static const struct inode_operations proc_sys_dir_operations;
>
> -/* Support for permanently empty directories */
> -static const struct ctl_table sysctl_mount_point[] = {
> - { }
> -};
> -
> -/**
> - * register_sysctl_mount_point() - registers a sysctl mount point
> - * @path: path for the mount point
> - *
> - * Used to create a permanently empty directory to serve as mount point.
> - * There are some subtle but important permission checks this allows in the
> - * case of unprivileged mounts.
> - */
> -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> -{
> - return register_sysctl(path, sysctl_mount_point);
> -}
> -EXPORT_SYMBOL(register_sysctl_mount_point);
> -
> -#define sysctl_is_perm_empty_ctl_header(hptr) \
> - (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_set_perm_empty_ctl_header(hptr) \
> - (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> - (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
> -
> void proc_sys_poll_notify(struct ctl_table_poll *poll)
> {
> if (!poll)
> @@ -199,8 +174,6 @@ static void init_header(struct ctl_table_header *head,
> head->set = set;
> head->parent = NULL;
> head->node = node;
> - if (table == sysctl_mount_point)
> - sysctl_set_perm_empty_ctl_header(head);
> INIT_HLIST_HEAD(&head->inodes);
> if (node) {
> const struct ctl_table *entry;
> @@ -228,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
>
>
> /* Is this a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(dir_h))
> + if (dir->permanently_empty)
> return -EROFS;
>
> - /* Am I creating a permanently empty directory? */
> - if (header->ctl_table_size > 0 &&
> - sysctl_is_perm_empty_ctl_header(header)) {
> - if (!RB_EMPTY_ROOT(&dir->root))
> - return -EINVAL;
> - sysctl_set_perm_empty_ctl_header(dir_h);
> - }
> -
> dir_h->nreg++;
> header->parent = dir;
> err = insert_links(header);
> @@ -254,8 +219,6 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> erase_header(header);
> put_links(header);
> fail_links:
> - if (header->ctl_table == sysctl_mount_point)
> - sysctl_clear_perm_empty_ctl_header(dir_h);
> header->parent = NULL;
> drop_sysctl_table(dir_h);
> return err;
> @@ -442,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> struct ctl_table_header *head, const struct ctl_table *table)
> {
> struct ctl_table_root *root = head->root;
> + struct ctl_dir *ctl_dir;
> struct inode *inode;
> struct proc_inode *ei;
>
> @@ -475,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> inode->i_mode |= S_IFDIR;
> inode->i_op = &proc_sys_dir_operations;
> inode->i_fop = &proc_sys_dir_file_operations;
> - if (sysctl_is_perm_empty_ctl_header(head))
> +
> + ctl_dir = container_of(head, struct ctl_dir, header);
> + if (ctl_dir->permanently_empty)
> make_empty_dir_inode(inode);
> }
>
> @@ -1214,8 +1180,7 @@ static bool get_links(struct ctl_dir *dir,
> struct ctl_table_header *tmp_head;
> const struct ctl_table *entry, *link;
>
> - if (header->ctl_table_size == 0 ||
> - sysctl_is_perm_empty_ctl_header(header))
> + if (header->ctl_table_size == 0 || dir->permanently_empty)
> return true;
>
> /* Are there links available for every entry in table? */
> @@ -1536,6 +1501,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> }
> EXPORT_SYMBOL(unregister_sysctl_table);
>
> +/**
> + * register_sysctl_mount_point() - registers a sysctl mount point
> + * @path: path for the mount point
> + *
> + * Used to create a permanently empty directory to serve as mount point.
> + * There are some subtle but important permission checks this allows in the
> + * case of unprivileged mounts.
> + */
> +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> +{
> + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);
> +
> + if (IS_ERR(dir))
> + return NULL;
> +
> + guard(spinlock)(&sysctl_lock);
> +
> + if (!RB_EMPTY_ROOT(&dir->root)) {
> + drop_sysctl_table(&dir->header);
> + return NULL;
> + }
> +
> + dir->permanently_empty = true;
> + return &dir->header;
> +}
> +EXPORT_SYMBOL(register_sysctl_mount_point);
> +
> void setup_sysctl_set(struct ctl_table_set *set,
> struct ctl_table_root *root,
> int (*is_seen)(struct ctl_table_set *))
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index 7c96d5abafc7..329e68d484ed 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -177,23 +177,14 @@ struct ctl_table_header {
> struct ctl_dir *parent;
> struct ctl_node *node;
> struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
> - /**
> - * enum type - Enumeration to differentiate between ctl target types
> - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> - * empty directory target to serve
> - * as mount point.
> - */
> - enum {
> - SYSCTL_TABLE_TYPE_DEFAULT,
> - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> - } type;
> };
>
> struct ctl_dir {
> /* Header must be at the start of ctl_dir */
> struct ctl_table_header header;
> struct rb_root root;
> + /* Permanently empty directory target to serve as mount point. */
> + bool permanently_empty;
> };
>
> struct ctl_table_set {
>
> base-commit: a6fd07f80ab7bd94edb4d56c35e61117ffb9957e
> prerequisite-patch-id: 0000000000000000000000000000000000000000
> prerequisite-patch-id: 13932e9add940cb65c71e04b5efdfcd3622fd27e
> prerequisite-patch-id: 2e4d88f7b8aaa805598f0e87a3ea726825bb4264
> prerequisite-patch-id: 674a680d9cb138cd34cfd0e1a4ec3a5d1c220078
> prerequisite-patch-id: e27c92582aa20b1dfb122c172b336dbaf9d6508a
> prerequisite-patch-id: 9b409a34ab6a4d8d8c5225ba9a72db3116e3c8b3
> prerequisite-patch-id: 86ff15a81d850ebda16bb707491251f4b705e4fd
> prerequisite-patch-id: b7ab65512ac9acfb2dd482b0271b399467afc56d
> prerequisite-patch-id: 0354922fbf2508a89f3e9d9a4e274fc98deb2e93
> prerequisite-patch-id: b71389e82026ffc19cbb717bba1a014ad6cab6da
> prerequisite-patch-id: fbb0201f89bf6c41d0585af867bdeec8d51649b2
> prerequisite-patch-id: e3b4b5b69b4eadf87ed97beb8c03a471e7628cb9
> prerequisite-patch-id: 3fbc9745cf3f28872b3e63f6d1f6e2fd7598be8a
> prerequisite-patch-id: ba2b190c2e54cfb505a282e688c2222712f0acd7
> prerequisite-patch-id: 47e5ca730748bb7bf9248a9e711045d8c1028199
> prerequisite-patch-id: dcd9f87f00290d2f9be83e404f8883eb90c5fb1c
> prerequisite-patch-id: d4629be1a61585ab821da2d2850f246761f72f25
> prerequisite-patch-id: f740190f4b94e57cbf3659f220d94483713341a1
> prerequisite-patch-id: 301c2e530e2af4568267e19247d4a49ac2a9871d
> --
> 2.43.0
>


--

Joel Granados


Attachments:
(No filename) (10.00 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-07 19:20:02

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-07 11:43:57+0100, Joel Granados wrote:
> Hey Thomas
>
> You have a couple of test bot issues for your 12/18 patch. Can you
> please address those for your next version.

I have these fixed locally, I assumed Luis would also pick them up
directly until I have a proper v2, properly should have communicated
that.

> On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Weißschuh wrote:
> > Problem description:
> >
> > The kernel contains a lot of struct ctl_table throught the tree.
> > These are very often 'static' definitions.
> > It would be good to make the tables unmodifiable by marking them "const"
> Here I would remove "It would be good to". Just state it: "Make the
> tables unmodifiable...."

Ack.

>
> > to avoid accidental or malicious modifications.
> > This is in line with a general effort to move as much data as possible
> > into .rodata. (See for example[0] and [1])

> If you could find more examples, it would make a better case.

I'll look for some. So far my constifications went in without them :-)

> >
> > Unfortunately the tables can not be made const right now because the
> > core registration functions expect mutable tables.
> >
> > This is for two main reasons:
> >
> > 1) sysctl_{set,clear}_perm_empty_ctl_header in the sysctl core modify
> > the table.
> > 2) The table is passed to the handler function as a non-const pointer.
> >
> > This series migrates the core and all handlers.

> awesome!
>
> >
> > Structure of the series:
> >
> > Patch 1-3: Cleanup patches
> > Patch 4-7: Non-logic preparation patches
> > Patch 8: Preparation patch changing a bit of logic
> > Patch 9-12: Treewide changes to handler function signature
> > Patch 13-14: Adaption of the sysctl core implementation
> > Patch 15: Adaption of the sysctl core interface
> > Patch 16: New entry for checkpatch
> > Patch 17-18: Constification of existing "struct ctl_table"s
> >
> > Tested by booting and with the sysctl selftests on x86.
> >
> > Note:
> >
> > This is intentionally sent only to a small number of people as I'd like
> > to get some more sysctl core-maintainer feedback before sending this to
> > essentially everybody.

> When you do send it to the broader audience, you should chunk up your big
> patches (12/18 and 11/18) and this is why:
> 1. To avoid mail rejections from lists:
> You have to tell a lot of people about the changes in one mail. That
> will make mail header too big for some lists and it will be rejected.
> This happened to me with [3]
> 2. Avoid being rejected for the wrong reasons :)
> Maintainers are busy ppl and sending them a set with so many files
> may elicit a rejection on the grounds that it involves too many
> subsystems at the same time.
> I suggest you chunk it up with directories in mind. Something similar to
> what I did for [4] where I divided stuff that when for fs/*, kernel/*,
> net/*, arch/* and drivers/*. That will complicate your patch a tad
> because you have to ensure that the tree can be compiled/run for every
> commit. But it will pay off once you push it to the broader public.

This will break bisections. All function signatures need to be switched
in one step. I would strongly like to avoid introducing broken commits.

The fact that these big commits have no functional changes at all makes
me hope it can work.

2023-12-07 19:23:42

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-07 12:19:57+0100, Joel Granados wrote:
> On Tue, Dec 05, 2023 at 06:16:53PM +0100, Thomas Weißschuh wrote:
> > Hi Luis, Joel,
> >
> > On 2023-12-05 09:04:08+0100, Thomas Weißschuh wrote:
> > > On 2023-12-04 21:50:14-0800, Luis Chamberlain wrote:
> > > > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Weißschuh wrote:
> > > > > Tested by booting and with the sysctl selftests on x86.
> > > >
> > > > Can I trouble you to rebase on sysctl-next?
> > > >
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=sysctl-next
> > >
> > > Will do.
> >
> > The rebased series is now available at
> > https://git.sr.ht/~t-8ch/linux b4/const-sysctl
> >
> > Nothing much has changed in contrast to v2.
> > The only functional change so far is the initialization of
> > ctl_table_header::type in init_header().
> >
> > I'll wait for Joels and maybe some more reviews before resending it.
> >
> > > [..]
> >
> > For the future I think it would make sense to combine the tree-wide constification
> > of the structs with the removal of the sentinel values.

> I don't see how these two would fit. And this is why:
> 1. The "remove sentinel" stuff is almost done. With the sets going into
> 6.7 we would only be missing everything under net/*. So you would not
> be able to combine them (except for the net stuff)
> 2. The motivation for the two sets is differnt. This would confuse
> rather than simplify the process.
> 3. In order to introduce the const stuff we would have to go through
> another round of "convincing" which can potentially derail the
> "remove sentinel" stuff.

Good reasons, especially 1).

> I would *not* like to combine them. I think the const set can stand on
> its own.

It was more about a process optimization. If somebody has to touch each
sysctl table anyway and test the changes, doing so for both series would
be easier for the sysctl and subsystem maintainers.

But alas, it seems I have to do it myself and can't heap it onto your
pile :-)

> >
> > This would reduce the impacts of the maintainers.

2023-12-07 19:29:30

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On 2023-12-07 13:14:37+0100, Joel Granados wrote:
> On Wed, Dec 06, 2023 at 06:53:10AM +0100, Thomas Weißschuh wrote:
> > On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> > > On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> > > >
> > > > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > > > return -EROFS;
> > > > > >
> > > > > > /* Am I creating a permanently empty directory? */
> > > > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > > > return -EINVAL;
> > > > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > > > >
> > > > > While you're at it.
> > > >
> > > > This hunk is completely gone in v3/the code that you merged.
> > >
> > > It is worse in that it is not obvious:
> > >
> > > + if (table == sysctl_mount_point)
> > > + sysctl_set_perm_empty_ctl_header(head);
> > >
> > > > Which kind of unsafety do you envision here?
> > >
> > > Making the code obvious during patch review hy this is needed /
> > > special, and if we special case this, why not remove enum, and make it
> > > specific to only that one table. The catch is that it is not
> > > immediately obvious that we actually call
> > > sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> > > question if this can be cleaned up somehow.
> >
> > Making it specific won't work because the flag needs to be transferred
> > from the leaf table to the table representing the directory.
> >
> > What do you think of the aproach taken in the attached patch?
> > (On top of current sysctl-next, including my series)

> What would this new patch be fixing again? I could not follow ?

This patch improves upon and replaces the patch you asked to submit on
its own: "sysctl: move sysctl type to ctl_table_header".

The current code and my original patch have to work around the fact that
the "empty" flag is first registered on a *leaf* ctl_table and from
there has to be transferred to the *directory* ctl_table somehow.
Which is confusing, at least it was for me and evidently also Luis.

The new code just directly sets the flag on the directory ctl_table and
gets rid of some now-dead code.
I should have written a proper changelog...

> Additionally, this might be another reason to set this patch aside :)

I hope we get this one in, it seems cleaner now.
If you agree I can send it as a proper standalone preparation patch.

> >
> > Note: Current sysctl-next ist still based on v6.6.
>
> > From 2fb9887fb2a5024c2620f2d694bc6dcc32afde67 Mon Sep 17 00:00:00 2001
> > From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> > Date: Wed, 6 Dec 2023 06:17:22 +0100
> > Subject: [PATCH] sysctl: simplify handling of permanently empty directories
> >
> > ---
> > fs/proc/proc_sysctl.c | 76 +++++++++++++++++++-----------------------
> > include/linux/sysctl.h | 13 ++------
> > 2 files changed, 36 insertions(+), 53 deletions(-)

> [..]

2023-12-11 08:34:48

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Thu, Dec 07, 2023 at 08:19:43PM +0100, Thomas Wei?schuh wrote:
> On 2023-12-07 11:43:57+0100, Joel Granados wrote:
> > Hey Thomas
> >
> > You have a couple of test bot issues for your 12/18 patch. Can you
> > please address those for your next version.
>
> I have these fixed locally, I assumed Luis would also pick them up
> directly until I have a proper v2, properly should have communicated
> that.
>
> > On Mon, Dec 04, 2023 at 08:52:13AM +0100, Thomas Wei?schuh wrote:
> > > Problem description:
> > >
> > > The kernel contains a lot of struct ctl_table throught the tree.
> > > These are very often 'static' definitions.
> > > It would be good to make the tables unmodifiable by marking them "const"
> > Here I would remove "It would be good to". Just state it: "Make the
> > tables unmodifiable...."
>
> Ack.
>
> >
> > > to avoid accidental or malicious modifications.
> > > This is in line with a general effort to move as much data as possible
> > > into .rodata. (See for example[0] and [1])
>
> > If you could find more examples, it would make a better case.
>
> I'll look for some. So far my constifications went in without them :-)
>
> > >
> > > Unfortunately the tables can not be made const right now because the
> > > core registration functions expect mutable tables.
> > >
> > > This is for two main reasons:
> > >
> > > 1) sysctl_{set,clear}_perm_empty_ctl_header in the sysctl core modify
> > > the table.
> > > 2) The table is passed to the handler function as a non-const pointer.
> > >
> > > This series migrates the core and all handlers.
>
> > awesome!
> >
> > >
> > > Structure of the series:
> > >
> > > Patch 1-3: Cleanup patches
> > > Patch 4-7: Non-logic preparation patches
> > > Patch 8: Preparation patch changing a bit of logic
> > > Patch 9-12: Treewide changes to handler function signature
> > > Patch 13-14: Adaption of the sysctl core implementation
> > > Patch 15: Adaption of the sysctl core interface
> > > Patch 16: New entry for checkpatch
> > > Patch 17-18: Constification of existing "struct ctl_table"s
> > >
> > > Tested by booting and with the sysctl selftests on x86.
> > >
> > > Note:
> > >
> > > This is intentionally sent only to a small number of people as I'd like
> > > to get some more sysctl core-maintainer feedback before sending this to
> > > essentially everybody.
>
> > When you do send it to the broader audience, you should chunk up your big
> > patches (12/18 and 11/18) and this is why:
> > 1. To avoid mail rejections from lists:
> > You have to tell a lot of people about the changes in one mail. That
> > will make mail header too big for some lists and it will be rejected.
> > This happened to me with [3]
> > 2. Avoid being rejected for the wrong reasons :)
> > Maintainers are busy ppl and sending them a set with so many files
> > may elicit a rejection on the grounds that it involves too many
> > subsystems at the same time.
> > I suggest you chunk it up with directories in mind. Something similar to
> > what I did for [4] where I divided stuff that when for fs/*, kernel/*,
> > net/*, arch/* and drivers/*. That will complicate your patch a tad
> > because you have to ensure that the tree can be compiled/run for every
> > commit. But it will pay off once you push it to the broader public.
>
> This will break bisections. All function signatures need to be switched
I was suggesting a solution without breaking bisections of course. I can
think of a couple of ways to do this in chunks but it might be
premature. You can send it and if you get push back because of this then
we can deal with chunking it down.

I'm still concerned about the header size for those mails. How does the
mail look like when you run the get maintainers script on it?

> in one step. I would strongly like to avoid introducing broken commits.
>
> The fact that these big commits have no functional changes at all makes
> me hope it can work.

--

Joel Granados


Attachments:
(No filename) (3.99 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-11 11:26:26

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-08 10:59:26+0100, Joel Granados wrote:
> On Thu, Dec 07, 2023 at 08:19:43PM +0100, Thomas Weißschuh wrote:
> > On 2023-12-07 11:43:57+0100, Joel Granados wrote:

> [..]

> > > I suggest you chunk it up with directories in mind. Something similar to
> > > what I did for [4] where I divided stuff that when for fs/*, kernel/*,
> > > net/*, arch/* and drivers/*. That will complicate your patch a tad
> > > because you have to ensure that the tree can be compiled/run for every
> > > commit. But it will pay off once you push it to the broader public.
> >
> > This will break bisections. All function signatures need to be switched

> I was suggesting a solution without breaking bisections of course. I can
> think of a couple of ways to do this in chunks but it might be
> premature. You can send it and if you get push back because of this then
> we can deal with chunking it down.

I'm curious about those ways. I don't see how to split the big commit.

> I'm still concerned about the header size for those mails. How does the
> mail look like when you run the get maintainers script on it?

The full series has 142 recipients in total,
the biggest patch itself has 124.

Before sending it I'd like to get feedback on the internal rework of the
is_empty detection from you and/or Luis.

https://git.sr.ht/~t-8ch/linux/commit/ea27507070f3c47be6febebe451bbb88f6ea707e
or the attached patch.

> [..]


Attachments:
(No filename) (1.41 kB)
ea27507070f3c47be6febebe451bbb88f6ea707e.patch (6.42 kB)
Download all attachments

2023-12-12 09:09:58

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Mon, Dec 11, 2023 at 12:25:10PM +0100, Thomas Wei?schuh wrote:
> On 2023-12-08 10:59:26+0100, Joel Granados wrote:
> > On Thu, Dec 07, 2023 at 08:19:43PM +0100, Thomas Wei?schuh wrote:
> > > On 2023-12-07 11:43:57+0100, Joel Granados wrote:
>
> > [..]
>
> > > > I suggest you chunk it up with directories in mind. Something similar to
> > > > what I did for [4] where I divided stuff that when for fs/*, kernel/*,
> > > > net/*, arch/* and drivers/*. That will complicate your patch a tad
> > > > because you have to ensure that the tree can be compiled/run for every
> > > > commit. But it will pay off once you push it to the broader public.
> > >
> > > This will break bisections. All function signatures need to be switched
>
> > I was suggesting a solution without breaking bisections of course. I can
> > think of a couple of ways to do this in chunks but it might be
> > premature. You can send it and if you get push back because of this then
> > we can deal with chunking it down.
>
> I'm curious about those ways. I don't see how to split the big commit.
My idea was to do something similar to your originl RFC, where you have
an temporary proc_handler something like proc_hdlr_const (we would need
to work on the name) and move each subsystem to the new handler while
the others stay with the non-const one. At the end, the old proc_handler
function name would disapear and would be completely replaced by the new
proc_hdlr_const.

This is of course extra work and might not be worth it if you don't get
negative feedback related to tree-wide changes. Therefore I stick to my
previous suggestion. Send the big tree-wide patches and only explore
this option if someone screams.
>
> > I'm still concerned about the header size for those mails. How does the
> > mail look like when you run the get maintainers script on it?
>
> The full series has 142 recipients in total,
> the biggest patch itself has 124.
This seems low. might just be enough to make into the lists that have
the check.

In any case it depends on the size of the header; if it is greater than
8912 you get a message back similar to this one:
"linux-raid-owne ( 22K) BOUNCE [email protected]: Header field too long (>8192)"

>
> Before sending it I'd like to get feedback on the internal rework of the
> is_empty detection from you and/or Luis.
Yep, this is still on my todo. With holidays just around the corner,
I'll be a bit slower to get to it. I'll eventually get to it if someone
else does not beat me to it :)

Thx for reminding me.
>
> https://git.sr.ht/~t-8ch/linux/commit/ea27507070f3c47be6febebe451bbb88f6ea707e
> or the attached patch.
>
> > [..]

> From ea27507070f3c47be6febebe451bbb88f6ea707e Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> Date: Sun, 3 Dec 2023 21:56:46 +0100
> Subject: [PATCH] sysctl: move permanently empty flag to ctl_dir
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> Simplify the logic by always keeping the permanently_empty flag on the
> ctl_dir.
> The previous logic kept the flag in the leaf ctl_table and from there
> transferred it to the ctl_table from the directory.
>
> This also removes the need to have a mutable ctl_table and will allow
> the constification of those structs.
>
> Signed-off-by: Thomas Wei?schuh <[email protected]>
> ---
> fs/proc/proc_sysctl.c | 74 +++++++++++++++++++-----------------------
> include/linux/sysctl.h | 13 ++------
> 2 files changed, 36 insertions(+), 51 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index 35c97ad54f34..33f41af58e9b 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -17,6 +17,7 @@
> #include <linux/bpf-cgroup.h>
> #include <linux/mount.h>
> #include <linux/kmemleak.h>
> +#include <linux/cleanup.h>
> #include "internal.h"
>
> #define list_for_each_table_entry(entry, header) \
> @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> static const struct file_operations proc_sys_dir_file_operations;
> static const struct inode_operations proc_sys_dir_operations;
>
> -/* Support for permanently empty directories */
> -static struct ctl_table sysctl_mount_point[] = {
> - {.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
> -};
> -
> -/**
> - * register_sysctl_mount_point() - registers a sysctl mount point
> - * @path: path for the mount point
> - *
> - * Used to create a permanently empty directory to serve as mount point.
> - * There are some subtle but important permission checks this allows in the
> - * case of unprivileged mounts.
> - */
> -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> -{
> - return register_sysctl(path, sysctl_mount_point);
> -}
> -EXPORT_SYMBOL(register_sysctl_mount_point);
> -
> -#define sysctl_is_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_set_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
> -
> void proc_sys_poll_notify(struct ctl_table_poll *poll)
> {
> if (!poll)
> @@ -226,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
>
>
> /* Is this a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(dir_h))
> + if (dir->permanently_empty)
> return -EROFS;
>
> - /* Am I creating a permanently empty directory? */
> - if (header->ctl_table_size > 0 &&
> - sysctl_is_perm_empty_ctl_header(header)) {
> - if (!RB_EMPTY_ROOT(&dir->root))
> - return -EINVAL;
> - sysctl_set_perm_empty_ctl_header(dir_h);
> - }
> -
> dir_h->nreg++;
> header->parent = dir;
> err = insert_links(header);
> @@ -252,8 +219,6 @@ fail:
> erase_header(header);
> put_links(header);
> fail_links:
> - if (header->ctl_table == sysctl_mount_point)
> - sysctl_clear_perm_empty_ctl_header(dir_h);
> header->parent = NULL;
> drop_sysctl_table(dir_h);
> return err;
> @@ -440,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> struct ctl_table_header *head, struct ctl_table *table)
> {
> struct ctl_table_root *root = head->root;
> + struct ctl_dir *ctl_dir;
> struct inode *inode;
> struct proc_inode *ei;
>
> @@ -473,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> inode->i_mode |= S_IFDIR;
> inode->i_op = &proc_sys_dir_operations;
> inode->i_fop = &proc_sys_dir_file_operations;
> - if (sysctl_is_perm_empty_ctl_header(head))
> +
> + ctl_dir = container_of(head, struct ctl_dir, header);
> + if (ctl_dir->permanently_empty)
> make_empty_dir_inode(inode);
> }
>
> @@ -1211,8 +1179,7 @@ static bool get_links(struct ctl_dir *dir,
> struct ctl_table_header *tmp_head;
> struct ctl_table *entry, *link;
>
> - if (header->ctl_table_size == 0 ||
> - sysctl_is_perm_empty_ctl_header(header))
> + if (header->ctl_table_size == 0 || dir->permanently_empty)
> return true;
>
> /* Are there links available for every entry in table? */
> @@ -1533,6 +1500,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> }
> EXPORT_SYMBOL(unregister_sysctl_table);
>
> +/**
> + * register_sysctl_mount_point() - registers a sysctl mount point
> + * @path: path for the mount point
> + *
> + * Used to create a permanently empty directory to serve as mount point.
> + * There are some subtle but important permission checks this allows in the
> + * case of unprivileged mounts.
> + */
> +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> +{
> + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);
> +
> + if (IS_ERR(dir))
> + return NULL;
> +
> + guard(spinlock)(&sysctl_lock);
> +
> + if (!RB_EMPTY_ROOT(&dir->root)) {
> + drop_sysctl_table(&dir->header);
> + return NULL;
> + }
> +
> + dir->permanently_empty = true;
> + return &dir->header;
> +}
> +EXPORT_SYMBOL(register_sysctl_mount_point);
> +
> void setup_sysctl_set(struct ctl_table_set *set,
> struct ctl_table_root *root,
> int (*is_seen)(struct ctl_table_set *))
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index ada36ef8cecb..57cb0060d7d7 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -137,17 +137,6 @@ struct ctl_table {
> void *data;
> int maxlen;
> umode_t mode;
> - /**
> - * enum type - Enumeration to differentiate between ctl target types
> - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> - * empty directory target to serve
> - * as mount point.
> - */
> - enum {
> - SYSCTL_TABLE_TYPE_DEFAULT,
> - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> - } type;
> proc_handler *proc_handler; /* Callback for text formatting */
> struct ctl_table_poll *poll;
> void *extra1;
> @@ -194,6 +183,8 @@ struct ctl_dir {
> /* Header must be at the start of ctl_dir */
> struct ctl_table_header header;
> struct rb_root root;
> + /* Permanently empty directory target to serve as mount point. */
> + bool permanently_empty;
> };
>
> struct ctl_table_set {
> --
> 2.38.5
>


--

Joel Granados


Attachments:
(No filename) (9.47 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-13 07:48:05

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Mon, Dec 11, 2023 at 12:25:10PM +0100, Thomas Wei?schuh wrote:
> Before sending it I'd like to get feedback on the internal rework of the
> is_empty detection from you and/or Luis.
>
> https://git.sr.ht/~t-8ch/linux/commit/ea27507070f3c47be6febebe451bbb88f6ea707e
> or the attached patch.

Please send as a new patch as RFC and please ensure on the To field is
first "Eric W. Biederman" <[email protected]> with a bit more
elaborate commit log as suggested from my review below. If there are
any hidden things me and Joel could probably miss I'm sure Eric will
be easily able to spot it.

> From ea27507070f3c47be6febebe451bbb88f6ea707e Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> Date: Sun, 3 Dec 2023 21:56:46 +0100
> Subject: [PATCH] sysctl: move permanently empty flag to ctl_dir
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> Simplify the logic by always keeping the permanently_empty flag on the
> ctl_dir.
> The previous logic kept the flag in the leaf ctl_table and from there
> transferred it to the ctl_table from the directory.
>
> This also removes the need to have a mutable ctl_table and will allow
> the constification of those structs.

Please elaborate a bit more on this here in your next RFC.

> Signed-off-by: Thomas Wei?schuh <[email protected]>
> ---
> fs/proc/proc_sysctl.c | 74 +++++++++++++++++++-----------------------
> include/linux/sysctl.h | 13 ++------
> 2 files changed, 36 insertions(+), 51 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index 35c97ad54f34..33f41af58e9b 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -17,6 +17,7 @@
> #include <linux/bpf-cgroup.h>
> #include <linux/mount.h>
> #include <linux/kmemleak.h>
> +#include <linux/cleanup.h>

> #include "internal.h"
>
> #define list_for_each_table_entry(entry, header) \
> @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> static const struct file_operations proc_sys_dir_file_operations;
> static const struct inode_operations proc_sys_dir_operations;
>
> -/* Support for permanently empty directories */
> -static struct ctl_table sysctl_mount_point[] = {
> - {.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
> -};
> -
> -/**
> - * register_sysctl_mount_point() - registers a sysctl mount point
> - * @path: path for the mount point
> - *
> - * Used to create a permanently empty directory to serve as mount point.
> - * There are some subtle but important permission checks this allows in the
> - * case of unprivileged mounts.
> - */
> -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> -{
> - return register_sysctl(path, sysctl_mount_point);
> -}
> -EXPORT_SYMBOL(register_sysctl_mount_point);
> -
> -#define sysctl_is_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_set_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> - (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
> -
> void proc_sys_poll_notify(struct ctl_table_poll *poll)
> {
> if (!poll)
> @@ -226,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
>
>
> /* Is this a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(dir_h))
> + if (dir->permanently_empty)
> return -EROFS;
>
> - /* Am I creating a permanently empty directory? */
> - if (header->ctl_table_size > 0 &&
> - sysctl_is_perm_empty_ctl_header(header)) {
> - if (!RB_EMPTY_ROOT(&dir->root))
> - return -EINVAL;
> - sysctl_set_perm_empty_ctl_header(dir_h);
> - }
> -
> dir_h->nreg++;
> header->parent = dir;
> err = insert_links(header);
> @@ -252,8 +219,6 @@ fail:
> erase_header(header);
> put_links(header);
> fail_links:
> - if (header->ctl_table == sysctl_mount_point)
> - sysctl_clear_perm_empty_ctl_header(dir_h);
> header->parent = NULL;
> drop_sysctl_table(dir_h);
> return err;
> @@ -440,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> struct ctl_table_header *head, struct ctl_table *table)
> {
> struct ctl_table_root *root = head->root;
> + struct ctl_dir *ctl_dir;
> struct inode *inode;
> struct proc_inode *ei;
>
> @@ -473,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> inode->i_mode |= S_IFDIR;
> inode->i_op = &proc_sys_dir_operations;
> inode->i_fop = &proc_sys_dir_file_operations;
> - if (sysctl_is_perm_empty_ctl_header(head))
> +
> + ctl_dir = container_of(head, struct ctl_dir, header);
> + if (ctl_dir->permanently_empty)
> make_empty_dir_inode(inode);
> }
>
> @@ -1211,8 +1179,7 @@ static bool get_links(struct ctl_dir *dir,
> struct ctl_table_header *tmp_head;
> struct ctl_table *entry, *link;
>
> - if (header->ctl_table_size == 0 ||
> - sysctl_is_perm_empty_ctl_header(header))
> + if (header->ctl_table_size == 0 || dir->permanently_empty)
> return true;

Why are we now checking the target directory whereas before it was the
header?

> /* Are there links available for every entry in table? */
> @@ -1533,6 +1500,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> }
> EXPORT_SYMBOL(unregister_sysctl_table);
>
> +/**
> + * register_sysctl_mount_point() - registers a sysctl mount point
> + * @path: path for the mount point
> + *
> + * Used to create a permanently empty directory to serve as mount point.
> + * There are some subtle but important permission checks this allows in the
> + * case of unprivileged mounts.
> + */
> +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> +{
> + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);

Even though __register_sysctl_table() did more than we needed it is not
obvious how the sysctl_table_root.default_set.dir.header.nreg++ is not
needed but I see get_subdir() also bumps it as it is called from
sysctl_mkdir_p(), so we were already bumping it at least once. I
suppose that is safe.

Wouldn't we be able to re-register the same sysctl mount point more
than once with this though?

> +
> + if (IS_ERR(dir))
> + return NULL;
> +
> + guard(spinlock)(&sysctl_lock);

For those that did not get the memo (I guess the docs could be
improved):

https://lwn.net/Articles/940117/

> +
> + if (!RB_EMPTY_ROOT(&dir->root)) {
> + drop_sysctl_table(&dir->header);
> + return NULL;
> + }

This seems to silently allow races in that the above allows
an existing sysctl mount point to already exist and here we
bail on an assumption we know we can't have.

> +
> + dir->permanently_empty = true;
> + return &dir->header;
> +}
> +EXPORT_SYMBOL(register_sysctl_mount_point);
> +
> void setup_sysctl_set(struct ctl_table_set *set,
> struct ctl_table_root *root,
> int (*is_seen)(struct ctl_table_set *))
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index ada36ef8cecb..57cb0060d7d7 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -137,17 +137,6 @@ struct ctl_table {
> void *data;
> int maxlen;
> umode_t mode;
> - /**
> - * enum type - Enumeration to differentiate between ctl target types
> - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> - * empty directory target to serve
> - * as mount point.
> - */
> - enum {
> - SYSCTL_TABLE_TYPE_DEFAULT,
> - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> - } type;
> proc_handler *proc_handler; /* Callback for text formatting */
> struct ctl_table_poll *poll;
> void *extra1;
> @@ -194,6 +183,8 @@ struct ctl_dir {
> /* Header must be at the start of ctl_dir */
> struct ctl_table_header header;
> struct rb_root root;
> + /* Permanently empty directory target to serve as mount point. */
> + bool permanently_empty;
> };
>
> struct ctl_table_set {

It's a pretty aggressive cleanup, specially with the new hipster guard()
call but I'd love Eric's eyeballs on a proper v2.

Luis

2023-12-13 07:51:50

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> My idea was to do something similar to your originl RFC, where you have
> an temporary proc_handler something like proc_hdlr_const (we would need
> to work on the name) and move each subsystem to the new handler while
> the others stay with the non-const one. At the end, the old proc_handler
> function name would disapear and would be completely replaced by the new
> proc_hdlr_const.
>
> This is of course extra work and might not be worth it if you don't get
> negative feedback related to tree-wide changes. Therefore I stick to my
> previous suggestion. Send the big tree-wide patches and only explore
> this option if someone screams.

I think we can do better, can't we just increase confidence in that we
don't *need* muttable ctl_cables with something like smatch or
coccinelle so that we can just make them const?

Seems like a noble endeavor for us to generalize.

Then we just breeze through by first fixing those that *are* using
mutable tables by having it just de-register and then re-register
new tables if they need to be changed, and then a new series is sent
once we fix all those muttable tables.

Luis

2023-12-13 18:18:23

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Luis Chamberlain <[email protected]> writes:

> On Mon, Dec 11, 2023 at 12:25:10PM +0100, Thomas Weißschuh wrote:
>> Before sending it I'd like to get feedback on the internal rework of the
>> is_empty detection from you and/or Luis.
>>
>> https://git.sr.ht/~t-8ch/linux/commit/ea27507070f3c47be6febebe451bbb88f6ea707e
>> or the attached patch.
>
> Please send as a new patch as RFC and please ensure on the To field is
> first "Eric W. Biederman" <[email protected]> with a bit more
> elaborate commit log as suggested from my review below. If there are
> any hidden things me and Joel could probably miss I'm sure Eric will
> be easily able to spot it.
>
>> From ea27507070f3c47be6febebe451bbb88f6ea707e Mon Sep 17 00:00:00 2001
>> From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
>> Date: Sun, 3 Dec 2023 21:56:46 +0100
>> Subject: [PATCH] sysctl: move permanently empty flag to ctl_dir
>> MIME-Version: 1.0
>> Content-Type: text/plain; charset=UTF-8
>> Content-Transfer-Encoding: 8bit
>>
>> Simplify the logic by always keeping the permanently_empty flag on the
>> ctl_dir.
>> The previous logic kept the flag in the leaf ctl_table and from there
>> transferred it to the ctl_table from the directory.
>>
>> This also removes the need to have a mutable ctl_table and will allow
>> the constification of those structs.

> Please elaborate a bit more on this here in your next RFC.

> It's a pretty aggressive cleanup, specially with the new hipster guard()
> call but I'd love Eric's eyeballs on a proper v2.

I will look at a v2 time permitting.

My sense is that changing the locking probably make sense as a separate
patch.

Eric

2023-12-15 16:41:20

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-12 23:51:30-0800, Luis Chamberlain wrote:
> On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> > My idea was to do something similar to your originl RFC, where you have
> > an temporary proc_handler something like proc_hdlr_const (we would need
> > to work on the name) and move each subsystem to the new handler while
> > the others stay with the non-const one. At the end, the old proc_handler
> > function name would disapear and would be completely replaced by the new
> > proc_hdlr_const.
> >
> > This is of course extra work and might not be worth it if you don't get
> > negative feedback related to tree-wide changes. Therefore I stick to my
> > previous suggestion. Send the big tree-wide patches and only explore
> > this option if someone screams.
>
> I think we can do better, can't we just increase confidence in that we
> don't *need* muttable ctl_cables with something like smatch or
> coccinelle so that we can just make them const?

The fact that the code compiles should be enough, no?
Any funky casting that would trick the compiler to accept it would
probably also confuse any other tool.

> Seems like a noble endeavor for us to generalize.
>
> Then we just breeze through by first fixing those that *are* using
> mutable tables by having it just de-register and then re-register
> new tables if they need to be changed, and then a new series is sent
> once we fix all those muttable tables.

Ack. But I think the actual constification should really only be started
after the first series for the infrastructure is in.

Thomas

2023-12-15 17:05:51

by Julia Lawall

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables



On Fri, 15 Dec 2023, Thomas Wei?schuh wrote:

> On 2023-12-12 23:51:30-0800, Luis Chamberlain wrote:
> > On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> > > My idea was to do something similar to your originl RFC, where you have
> > > an temporary proc_handler something like proc_hdlr_const (we would need
> > > to work on the name) and move each subsystem to the new handler while
> > > the others stay with the non-const one. At the end, the old proc_handler
> > > function name would disapear and would be completely replaced by the new
> > > proc_hdlr_const.
> > >
> > > This is of course extra work and might not be worth it if you don't get
> > > negative feedback related to tree-wide changes. Therefore I stick to my
> > > previous suggestion. Send the big tree-wide patches and only explore
> > > this option if someone screams.
> >
> > I think we can do better, can't we just increase confidence in that we
> > don't *need* muttable ctl_cables with something like smatch or
> > coccinelle so that we can just make them const?
>
> The fact that the code compiles should be enough, no?
> Any funky casting that would trick the compiler to accept it would
> probably also confuse any other tool.

I don't know the context, but the fact that a particular file compiles
doesn't mean that all of the lines in the file have been subjected to the
compiler, due to ifdefs.

julia

>
> > Seems like a noble endeavor for us to generalize.
> >
> > Then we just breeze through by first fixing those that *are* using
> > mutable tables by having it just de-register and then re-register
> > new tables if they need to be changed, and then a new series is sent
> > once we fix all those muttable tables.
>
> Ack. But I think the actual constification should really only be started
> after the first series for the infrastructure is in.
>
> Thomas
>

2023-12-17 21:57:51

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Catching up with mail....

On Tue, Dec 12, 2023 at 11:51:30PM -0800, Luis Chamberlain wrote:
> On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> > My idea was to do something similar to your originl RFC, where you have
> > an temporary proc_handler something like proc_hdlr_const (we would need
> > to work on the name) and move each subsystem to the new handler while
> > the others stay with the non-const one. At the end, the old proc_handler
> > function name would disapear and would be completely replaced by the new
> > proc_hdlr_const.
> >
> > This is of course extra work and might not be worth it if you don't get
> > negative feedback related to tree-wide changes. Therefore I stick to my
> > previous suggestion. Send the big tree-wide patches and only explore
> > this option if someone screams.
>
> I think we can do better, can't we just increase confidence in that we
> don't *need* muttable ctl_cables with something like smatch or
> coccinelle so that we can just make them const?
>
> Seems like a noble endeavor for us to generalize.
>
> Then we just breeze through by first fixing those that *are* using
> mutable tables by having it just de-register and then re-register
So let me see if I understand your {de,re}-register idea:
When we have a situation (like in the networking code) where a ctl_table
is being used in an unmuttable way, we do your {de,re}-register trick.

The trick consists in unregistering an old ctl_table and reregistering
with a whole new const changed table. In this way, whatever we register
is always const.

Once we address all the places where this happens, then we just change
the handler to const and we are done.

Is that correct?

If that is indeed what you are proposing, you might not even need the
un-register step as all the mutability that I have seen occurs before
the register. So maybe instead of re-registering it, you can so a copy
(of the changed ctl_table) to a const pointer and then pass that along
to the register function.

Can't think of anything else off the top of my head. Would have to
actually see the code to evaluate further I think.

> new tables if they need to be changed, and then a new series is sent
> once we fix all those muttable tables.
>
> Luis

best

--

Joel Granados


Attachments:
(No filename) (2.28 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-17 22:10:30

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On 2023-12-17 13:02:01+0100, Joel Granados wrote:
> Catching up with mail....
>
> On Tue, Dec 12, 2023 at 11:51:30PM -0800, Luis Chamberlain wrote:
> > On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> > > My idea was to do something similar to your originl RFC, where you have
> > > an temporary proc_handler something like proc_hdlr_const (we would need
> > > to work on the name) and move each subsystem to the new handler while
> > > the others stay with the non-const one. At the end, the old proc_handler
> > > function name would disapear and would be completely replaced by the new
> > > proc_hdlr_const.
> > >
> > > This is of course extra work and might not be worth it if you don't get
> > > negative feedback related to tree-wide changes. Therefore I stick to my
> > > previous suggestion. Send the big tree-wide patches and only explore
> > > this option if someone screams.
> >
> > I think we can do better, can't we just increase confidence in that we
> > don't *need* muttable ctl_cables with something like smatch or
> > coccinelle so that we can just make them const?
> >
> > Seems like a noble endeavor for us to generalize.
> >
> > Then we just breeze through by first fixing those that *are* using
> > mutable tables by having it just de-register and then re-register
> So let me see if I understand your {de,re}-register idea:
> When we have a situation (like in the networking code) where a ctl_table
> is being used in an unmuttable way, we do your {de,re}-register trick.

unmuttable?

> The trick consists in unregistering an old ctl_table and reregistering
> with a whole new const changed table. In this way, whatever we register
> is always const.
>
> Once we address all the places where this happens, then we just change
> the handler to const and we are done.
>
> Is that correct?

I'm confused.

The handlers can already be made const as shown in this series, which
does convert the whole kernel tree.
There is only one handler (the stackleak one) which modifies the table
and this one is fixed as part of the series.

(Plus the changes needed to the sysctl core to avoid mutation there)

> If that is indeed what you are proposing, you might not even need the
> un-register step as all the mutability that I have seen occurs before
> the register. So maybe instead of re-registering it, you can so a copy
> (of the changed ctl_table) to a const pointer and then pass that along
> to the register function.

Tables that are modified, but *not* through the handler, would crop
during the constification of the table structs.
Which should be a second step.

But Luis' message was not completely clear to me.
I guess I'm missing something.

> Can't think of anything else off the top of my head. Would have to
> actually see the code to evaluate further I think.
>
> > new tables if they need to be changed, and then a new series is sent
> > once we fix all those muttable tables.

Thomas

2023-12-18 21:22:17

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

So we can split this up concentually in two:

* constificaiton of the table handlers
* constification of the table struct itself

On Sun, Dec 17, 2023 at 11:10:15PM +0100, Thomas Wei?schuh wrote:
> The handlers can already be made const as shown in this series,

The series did already produce issues with some builds, and so
Julia's point is confirmed that the series only proves hanlders
which you did build and for which 0-day has coverage for.

The challenge here was to see if we could draw up a test case
that would prove this without build tests, and what occurred to
me was coccinelle or smatch.

> > If that is indeed what you are proposing, you might not even need the
> > un-register step as all the mutability that I have seen occurs before
> > the register. So maybe instead of re-registering it, you can so a copy
> > (of the changed ctl_table) to a const pointer and then pass that along
> > to the register function.
>
> Tables that are modified, but *not* through the handler, would crop
> during the constification of the table structs.
> Which should be a second step.

Instead of "croping up" at build time again, I wonder if we can do
better with coccinelle / smatch.

Joel, and yes, what you described is what I was suggesting, that is to
avoid having to add a non-const handler a first step, instead we modify
those callers which do require to modify the table by first a
deregistration and later a registration. In fact to make this even
easier a new call would be nice so to aslo be able to git grep when
this is done in the kernel.

But if what you suggest is true that there are no registrations which
later modify the table, we don't need that. It is the uncertainty that
we might have that this is a true statment that I wanted to challenge
to see if we could do better. Can we avoid this being a stupid
regression later by doing code analysis with coccinelle / smatch?

The template of the above endeavor seems useful not only to this use
case but to any place in the kernel where this previously has been done
before, and hence my suggestion that this seems like a sensible thing
to think over to see if we could generalize.

Luis

2023-12-19 19:30:14

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

Hi Luis and Julia,

(Julia, there is a question and context for you inline, marked with your name)

On 2023-12-18 13:21:49-0800, Luis Chamberlain wrote:
> So we can split this up concentually in two:
>
> * constificaiton of the table handlers
> * constification of the table struct itself
>
> On Sun, Dec 17, 2023 at 11:10:15PM +0100, Thomas Weißschuh wrote:
> > The handlers can already be made const as shown in this series,
>
> The series did already produce issues with some builds, and so
> Julia's point is confirmed that the series only proves hanlders
> which you did build and for which 0-day has coverage for.
>
> The challenge here was to see if we could draw up a test case
> that would prove this without build tests, and what occurred to
> me was coccinelle or smatch.

I used the following coccinelle script to find more handlers that I
missed before:

virtual patch
virtual context
virtual report

@@
identifier func;
identifier ctl;
identifier write;
identifier buffer;
identifier lenp;
identifier ppos;
type loff_t;
@@

int func(
- struct ctl_table *ctl,
+ const struct ctl_table *ctl,
int write, void *buffer, size_t *lenp, loff_t *ppos) { ... }

It did not find any additional occurrences while it was able to match
the existing changes.

After that I manually reviewed all handlers that they are not modifying
their table argument, which they don't.

Should we do more?


For Julia:

Maybe you could advise on how to use coccinelle to find where a const
function argument or one of its members are modified directly or passed
to some other function as non-const arguments.
See the coccinelle patch above.

Is this possible?

> > > If that is indeed what you are proposing, you might not even need the
> > > un-register step as all the mutability that I have seen occurs before
> > > the register. So maybe instead of re-registering it, you can so a copy
> > > (of the changed ctl_table) to a const pointer and then pass that along
> > > to the register function.
> >
> > Tables that are modified, but *not* through the handler, would crop
> > during the constification of the table structs.
> > Which should be a second step.
>
> Instead of "croping up" at build time again, I wonder if we can do
> better with coccinelle / smatch.

As for smatch:

Doesn't smatch itself run as part of a normal build [0]?
So it would have the same visibility issues as the compiler itself.

> Joel, and yes, what you described is what I was suggesting, that is to
> avoid having to add a non-const handler a first step, instead we modify
> those callers which do require to modify the table by first a
> deregistration and later a registration. In fact to make this even
> easier a new call would be nice so to aslo be able to git grep when
> this is done in the kernel.
>
> But if what you suggest is true that there are no registrations which
> later modify the table, we don't need that. It is the uncertainty that
> we might have that this is a true statment that I wanted to challenge
> to see if we could do better. Can we avoid this being a stupid
> regression later by doing code analysis with coccinelle / smatch?
>
> The template of the above endeavor seems useful not only to this use
> case but to any place in the kernel where this previously has been done
> before, and hence my suggestion that this seems like a sensible thing
> to think over to see if we could generalize.

I'd like to split the series and submit the part up until and including
the constification of arguments first and on its own.
It keeps the subsystem maintainers out of the discussion of the core
sysctl changes.

I'll submit the core sysctl changes after I figure out proper responses
to all review comments and we can do this in parallel to the tree-wide
preparation.

What do you think Luis and Joel?

[0] https://repo.or.cz/smatch.git/blob/HEAD:/smatch_scripts/test_kernel.sh

2023-12-19 20:40:21

by Julia Lawall

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables



On Tue, 19 Dec 2023, Thomas Weißschuh wrote:

> Hi Luis and Julia,
>
> (Julia, there is a question and context for you inline, marked with your name)
>
> On 2023-12-18 13:21:49-0800, Luis Chamberlain wrote:
> > So we can split this up concentually in two:
> >
> > * constificaiton of the table handlers
> > * constification of the table struct itself
> >
> > On Sun, Dec 17, 2023 at 11:10:15PM +0100, Thomas Weißschuh wrote:
> > > The handlers can already be made const as shown in this series,
> >
> > The series did already produce issues with some builds, and so
> > Julia's point is confirmed that the series only proves hanlders
> > which you did build and for which 0-day has coverage for.
> >
> > The challenge here was to see if we could draw up a test case
> > that would prove this without build tests, and what occurred to
> > me was coccinelle or smatch.
>
> I used the following coccinelle script to find more handlers that I
> missed before:
>
> virtual patch
> virtual context
> virtual report
>
> @@
> identifier func;
> identifier ctl;
> identifier write;
> identifier buffer;
> identifier lenp;
> identifier ppos;
> type loff_t;
> @@
>
> int func(
> - struct ctl_table *ctl,
> + const struct ctl_table *ctl,
> int write, void *buffer, size_t *lenp, loff_t *ppos) { ... }
>
> It did not find any additional occurrences while it was able to match
> the existing changes.
>
> After that I manually reviewed all handlers that they are not modifying
> their table argument, which they don't.
>
> Should we do more?
>
>
> For Julia:
>
> Maybe you could advise on how to use coccinelle to find where a const
> function argument or one of its members are modified directly or passed
> to some other function as non-const arguments.
> See the coccinelle patch above.
>
> Is this possible?

I will propose something.

>
> > > > If that is indeed what you are proposing, you might not even need the
> > > > un-register step as all the mutability that I have seen occurs before
> > > > the register. So maybe instead of re-registering it, you can so a copy
> > > > (of the changed ctl_table) to a const pointer and then pass that along
> > > > to the register function.
> > >
> > > Tables that are modified, but *not* through the handler, would crop
> > > during the constification of the table structs.
> > > Which should be a second step.
> >
> > Instead of "croping up" at build time again, I wonder if we can do
> > better with coccinelle / smatch.
>
> As for smatch:
>
> Doesn't smatch itself run as part of a normal build [0]?
> So it would have the same visibility issues as the compiler itself.

I also believe that this is the case.

julia

> > Joel, and yes, what you described is what I was suggesting, that is to
> > avoid having to add a non-const handler a first step, instead we modify
> > those callers which do require to modify the table by first a
> > deregistration and later a registration. In fact to make this even
> > easier a new call would be nice so to aslo be able to git grep when
> > this is done in the kernel.
> >
> > But if what you suggest is true that there are no registrations which
> > later modify the table, we don't need that. It is the uncertainty that
> > we might have that this is a true statment that I wanted to challenge
> > to see if we could do better. Can we avoid this being a stupid
> > regression later by doing code analysis with coccinelle / smatch?
> >
> > The template of the above endeavor seems useful not only to this use
> > case but to any place in the kernel where this previously has been done
> > before, and hence my suggestion that this seems like a sensible thing
> > to think over to see if we could generalize.
>
> I'd like to split the series and submit the part up until and including
> the constification of arguments first and on its own.
> It keeps the subsystem maintainers out of the discussion of the core
> sysctl changes.
>
> I'll submit the core sysctl changes after I figure out proper responses
> to all review comments and we can do this in parallel to the tree-wide
> preparation.
>
> What do you think Luis and Joel?
>
> [0] https://repo.or.cz/smatch.git/blob/HEAD:/smatch_scripts/test_kernel.sh
>

2023-12-19 21:10:01

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 19, 2023 at 08:29:50PM +0100, Thomas Wei?schuh wrote:
>
> I used the following coccinelle script to find more handlers that I
> missed before:
>
> virtual patch
> virtual context
> virtual report
>
> @@
> identifier func;
> identifier ctl;
> identifier write;
> identifier buffer;
> identifier lenp;
> identifier ppos;
> type loff_t;
> @@
>
> int func(
> - struct ctl_table *ctl,
> + const struct ctl_table *ctl,
> int write, void *buffer, size_t *lenp, loff_t *ppos) { ... }

I think it would be useful to describe that the reason why you have
the parameters in places as required is you want to limit the scope
to the sysctl handler routines only, and these have these fixed
arguments.

make coccicheck MODE=patch COCCI=sysctl-const.cocci SPFLAGS="--in-place" > /dev/null
git diff --stat | tail -1
80 files changed, 390 insertions(+), 306 deletions(-)
git diff --stat | sha1sum
ec90851ba02dad069b11822782c74665a01142db -

> It did not find any additional occurrences while it was able to match
> the existing changes.

Fantastic, then please use and include the coccinelle rule to express
that this is the goal, it is easier to review *one* cocinelle rule
with intent rather than tons of changes.

> After that I manually reviewed all handlers that they are not modifying
> their table argument, which they don't.
>
> Should we do more?

Now that we started to think about *what* is the goal, and trying to
break it down it is easier to think about the ramifications of what we
need checked and how tools can help.

We break down the first goal into a simple grammatical expression listed
above, we want to constify the proc hanlders use of the struct ctl_table.

Given this, I think that for the first part the coccinelle grammar above
should take care of the cases where the compiler would not have caught
a few builds where your config was not testing the compiler build. Now
could this still allow

ctl->foo = bar ?

I think so, so here is a simple sysctl-const-mod.cocci which can be
used in coccicheck patch mode as well instead of coccicheck context mode
as the context mode just produces a removal visually, and I prefer to see
the removals with git diff instead due to color syntax highlighting:

make coccicheck MODE=patch COCCI=sysctl-const-mod.cocci SPFLAGS="--in-place" > /dev/null
virtual patch

@ r1 @
identifier func;
identifier ctl;
identifier write;
identifier buffer;
identifier lenp;
identifier ppos;
type loff_t;
@@

int func(
struct ctl_table *ctl,
int write, void *buffer, size_t *lenp, loff_t *ppos)
{ ... }

@ r2 depends on r1 @
struct ctl_table *ctl;
expression E1, E2;
@@

(
- ctl->extra1 = E1;
|
- ctl->extra2 = E1;
)


The git diff --stat:

arch/arm64/kernel/armv8_deprecated.c | 2 --
drivers/net/vrf.c | 3 ---
net/ipv4/devinet.c | 2 --
net/ipv4/route.c | 1 -
net/ipv6/addrconf.c | 2 --
net/ipv6/route.c | 1 -
net/mpls/af_mpls.c | 2 --
net/netfilter/ipvs/ip_vs_ctl.c | 6 +-----
net/netfilter/nf_log.c | 2 +-
net/sctp/sysctl.c | 5 -----
10 files changed, 2 insertions(+), 24 deletions(-)

So that needs review. And the OR could be expanded with more components
of the struct ctl_table

As I noted, I think this is a generically neat endeavor and so I think
it would be nice to shorthand *any* member of the struct. ctl->any.
Julia, is that possible?

The depends on is rather loose so I *think* this means the second rule
should only apply the rule on files which define handler. But that second
rule could perhaps be made as a long term generic goal without the first rule.

I first tried to attach the modification of the ctl table to the routine
itself with so only the caller is modified:

virtual patch

@ r1 @
identifier func;
struct ctl_table *ctl;
identifier write;
identifier buffer;
identifier lenp;
identifier ppos;
type loff_t;
@@

int func(
struct ctl_table *ctl,
int write, void *buffer, size_t *lenp, loff_t *ppos)
{ ... }

@ r2 depends on r1 @
r1.ctl;
expression E1, E2;
@@

(
- ctl->extra1 = E1;
|
- ctl->extra2 = E1;
)

But that didn't work.

> > The template of the above endeavor seems useful not only to this use
> > case but to any place in the kernel where this previously has been done
> > before, and hence my suggestion that this seems like a sensible thing
> > to think over to see if we could generalize.
>
> I'd like to split the series and submit the part up until and including
> the constification of arguments first and on its own.

The first part is the proc handlers.

If after that you generalize when its used in any routine as this:

virtual patch

@@
identifier func;
identifier ctl;
@@

int func(...,
- struct ctl_table *ctl,
+ const struct ctl_table *ctl,
...) { ... }

You increase the required changes and scope. This does not handle the
case where two different tables are in the same routine arguments, but
that is a special case and could be hanlded through its own rule.

> It keeps the subsystem maintainers out of the discussion of the core
> sysctl changes.

We'll need to involve subsystem maintainers eventually to deal with
special cases which don't fit the goal we want to normalize to. I
suggest you think about the changes in grammatical expressions, leading
up to the final gaol, where we could do a full sweep and ensure no
struct ctl_table is not const.

That is, as you work your way up to the goal, I suspect you may need
to modify a few loose drivers / components which may need special
handling so that we could normalize on the intended grammatical
requirements. Just as with the ctrl work Joel did -- a few drives
needed to be modified so that the long term goal for the sentinel
could be applied.

I don't think time is wasted in formalizing this endeavor as it is
a generic goal we tend to see. We're breaking this down then into
a few goals, leaps:

1) Start off with a few key special routines which deal with the
data structure we want to constify, so we create grammar rules
which modify the expected function data types with the one
we are intersted in with const. The value in this is that
Coccinelle will find changes we need outside of the scope of our
build.

2) Those routines then need checks to ensure that no variable is
modified, so we need a scaper first to report these so we can
inspect the routine and change it so that the grammar rule in
1) works without any expected compile failure.

3) Loosten the search to any routine that uses the struct we want
to constify and address cases where the struct is used more than
once in a routine.

4) Ensure globally we don't modify the struct as done in the report
on goal 1).

5) Constify the struct

Luis

2023-12-19 21:21:56

by Julia Lawall

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

> As I noted, I think this is a generically neat endeavor and so I think
> it would be nice to shorthand *any* member of the struct. ctl->any.
> Julia, is that possible?

What do you mean by *any* member? If any is an identifier typed
metavariable then that would get any immediate member. But maybe you want
something like

<+...ctl->any...+>

that will match anything that has ctl->any as a subexpression?

It may be necessary to put this in parentheses to address parsing issues,
but the () won't need to be present in the matched code.

You could also use

assignment operator aop;

rather than =, to also match += etc.

julia

2023-12-19 23:05:06

by Julia Lawall

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

I came up with the following:

@@
type t;
const t *x;
identifier y,z;
expression a;
assignment operator aop;
@@

(
(<+...(<+...x->y...+>)[...]...+>) aop a
|
(<+...(<+...x->y...+>)->z...+>) aop a
|
* (<+...x->y...+>) aop a
)

@fn disable optional_qualifier@
identifier f,x;
type t;
parameter list[n] ps;
@@

f(ps,t *x,...) { ... }

@@
identifier fn.f;
expression list[fn.n] es;
type t;
const t *e;
@@

*f(es,e,...)

---------------

The first rule takes care of assignments, while the remaining rules check
function calls.

This is not extensively tested and has false positives. One case is when
you have a->b[x->y] = 12; and it is x not a that is const. Maybe I can
improve it to avoid this problem.

I would suggest to replace the occurrences of t by your specific type of
interest (and then drop the occurrences type t;), to reduce the amount of
work to be done and the chance of false positives.

This is also limited in that it only works on a single file. Thus in
particular the last rule on function calls will only be triggered when the
called function is defined in the same file.

Despite the current limitations, maybe it will find something useful.

julia

2023-12-20 00:09:43

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 19, 2023 at 10:21:25PM +0100, Julia Lawall wrote:
> > As I noted, I think this is a generically neat endeavor and so I think
> > it would be nice to shorthand *any* member of the struct. ctl->any.
> > Julia, is that possible?
>
> What do you mean by *any* member?

I meant when any code tries to assign a new variable to any of the
members of the struct ctl_table *foo, so any foo->*any*

> If any is an identifier typed
> metavariable then that would get any immediate member. But maybe you want
> something like
>
> <+...ctl->any...+>
>
> that will match anything that has ctl->any as a subexpression?

If as just an expression, then no, we really want this to be tied to
the data struture in question we want to modify.

Luis

2023-12-20 07:40:31

by Julia Lawall

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables



On Tue, 19 Dec 2023, Luis Chamberlain wrote:

> On Tue, Dec 19, 2023 at 10:21:25PM +0100, Julia Lawall wrote:
> > > As I noted, I think this is a generically neat endeavor and so I think
> > > it would be nice to shorthand *any* member of the struct. ctl->any.
> > > Julia, is that possible?
> >
> > What do you mean by *any* member?
>
> I meant when any code tries to assign a new variable to any of the
> members of the struct ctl_table *foo, so any foo->*any*

Declaring any to be an identifier metavariable would be sufficient.

>
> > If any is an identifier typed
> > metavariable then that would get any immediate member. But maybe you want
> > something like
> >
> > <+...ctl->any...+>
> >
> > that will match anything that has ctl->any as a subexpression?
>
> If as just an expression, then no, we really want this to be tied to
> the data struture in question we want to modify.

What about foo->a.b? Or maybe that doesn't occur in your structure?

julia

2023-12-20 14:35:09

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Wed, Dec 20, 2023 at 08:39:20AM +0100, Julia Lawall wrote:
>
>
> On Tue, 19 Dec 2023, Luis Chamberlain wrote:
>
> > On Tue, Dec 19, 2023 at 10:21:25PM +0100, Julia Lawall wrote:
> > > > As I noted, I think this is a generically neat endeavor and so I think
> > > > it would be nice to shorthand *any* member of the struct. ctl->any.
> > > > Julia, is that possible?
> > >
> > > What do you mean by *any* member?
> >
> > I meant when any code tries to assign a new variable to any of the
> > members of the struct ctl_table *foo, so any foo->*any*
>
> Declaring any to be an identifier metavariable would be sufficient.

Fantastic thanks!

> > > If any is an identifier typed
> > > metavariable then that would get any immediate member. But maybe you want
> > > something like
> > >
> > > <+...ctl->any...+>
> > >
> > > that will match anything that has ctl->any as a subexpression?
> >
> > If as just an expression, then no, we really want this to be tied to
> > the data struture in question we want to modify.
>
> What about foo->a.b? Or maybe that doesn't occur in your structure?

We'll consider that too, good idea!

Luis

2023-12-23 12:09:22

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

Hey Thomas.

I had some available cycles today and wanted to look at the patch that
you sent. I could not apply it on top of 6.7-rc6. Have you thought about
taking this out of your "constification" series and posting it as
something that comes before the const stuff?

Best

On Wed, Dec 06, 2023 at 06:53:10AM +0100, Thomas Weißschuh wrote:
> On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> > On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> > >
> > > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > > return -EROFS;
> > > > >
> > > > > /* Am I creating a permanently empty directory? */
> > > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > > return -EINVAL;
> > > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > > >
> > > > While you're at it.
> > >
> > > This hunk is completely gone in v3/the code that you merged.
> >
> > It is worse in that it is not obvious:
> >
> > + if (table == sysctl_mount_point)
> > + sysctl_set_perm_empty_ctl_header(head);
> >
> > > Which kind of unsafety do you envision here?
> >
> > Making the code obvious during patch review hy this is needed /
> > special, and if we special case this, why not remove enum, and make it
> > specific to only that one table. The catch is that it is not
> > immediately obvious that we actually call
> > sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> > question if this can be cleaned up somehow.
>
> Making it specific won't work because the flag needs to be transferred
> from the leaf table to the table representing the directory.
>
> What do you think of the aproach taken in the attached patch?
> (On top of current sysctl-next, including my series)
>
> Note: Current sysctl-next ist still based on v6.6.

> From 2fb9887fb2a5024c2620f2d694bc6dcc32afde67 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> Date: Wed, 6 Dec 2023 06:17:22 +0100
> Subject: [PATCH] sysctl: simplify handling of permanently empty directories
>
> ---
> fs/proc/proc_sysctl.c | 76 +++++++++++++++++++-----------------------
> include/linux/sysctl.h | 13 ++------
> 2 files changed, 36 insertions(+), 53 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index c92e9b972ada..c4d6d09b0e68 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -17,6 +17,7 @@
> #include <linux/bpf-cgroup.h>
> #include <linux/mount.h>
> #include <linux/kmemleak.h>
> +#include <linux/cleanup.h>
> #include "internal.h"
>
> #define list_for_each_table_entry(entry, header) \
> @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> static const struct file_operations proc_sys_dir_file_operations;
> static const struct inode_operations proc_sys_dir_operations;
>
> -/* Support for permanently empty directories */
> -static const struct ctl_table sysctl_mount_point[] = {
> - { }
> -};
> -
> -/**
> - * register_sysctl_mount_point() - registers a sysctl mount point
> - * @path: path for the mount point
> - *
> - * Used to create a permanently empty directory to serve as mount point.
> - * There are some subtle but important permission checks this allows in the
> - * case of unprivileged mounts.
> - */
> -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> -{
> - return register_sysctl(path, sysctl_mount_point);
> -}
> -EXPORT_SYMBOL(register_sysctl_mount_point);
> -
> -#define sysctl_is_perm_empty_ctl_header(hptr) \
> - (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_set_perm_empty_ctl_header(hptr) \
> - (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> - (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
> -
> void proc_sys_poll_notify(struct ctl_table_poll *poll)
> {
> if (!poll)
> @@ -199,8 +174,6 @@ static void init_header(struct ctl_table_header *head,
> head->set = set;
> head->parent = NULL;
> head->node = node;
> - if (table == sysctl_mount_point)
> - sysctl_set_perm_empty_ctl_header(head);
> INIT_HLIST_HEAD(&head->inodes);
> if (node) {
> const struct ctl_table *entry;
> @@ -228,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
>
>
> /* Is this a permanently empty directory? */
> - if (sysctl_is_perm_empty_ctl_header(dir_h))
> + if (dir->permanently_empty)
> return -EROFS;
>
> - /* Am I creating a permanently empty directory? */
> - if (header->ctl_table_size > 0 &&
> - sysctl_is_perm_empty_ctl_header(header)) {
> - if (!RB_EMPTY_ROOT(&dir->root))
> - return -EINVAL;
> - sysctl_set_perm_empty_ctl_header(dir_h);
> - }
> -
> dir_h->nreg++;
> header->parent = dir;
> err = insert_links(header);
> @@ -254,8 +219,6 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> erase_header(header);
> put_links(header);
> fail_links:
> - if (header->ctl_table == sysctl_mount_point)
> - sysctl_clear_perm_empty_ctl_header(dir_h);
> header->parent = NULL;
> drop_sysctl_table(dir_h);
> return err;
> @@ -442,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> struct ctl_table_header *head, const struct ctl_table *table)
> {
> struct ctl_table_root *root = head->root;
> + struct ctl_dir *ctl_dir;
> struct inode *inode;
> struct proc_inode *ei;
>
> @@ -475,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> inode->i_mode |= S_IFDIR;
> inode->i_op = &proc_sys_dir_operations;
> inode->i_fop = &proc_sys_dir_file_operations;
> - if (sysctl_is_perm_empty_ctl_header(head))
> +
> + ctl_dir = container_of(head, struct ctl_dir, header);
> + if (ctl_dir->permanently_empty)
> make_empty_dir_inode(inode);
> }
>
> @@ -1214,8 +1180,7 @@ static bool get_links(struct ctl_dir *dir,
> struct ctl_table_header *tmp_head;
> const struct ctl_table *entry, *link;
>
> - if (header->ctl_table_size == 0 ||
> - sysctl_is_perm_empty_ctl_header(header))
> + if (header->ctl_table_size == 0 || dir->permanently_empty)
> return true;
>
> /* Are there links available for every entry in table? */
> @@ -1536,6 +1501,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> }
> EXPORT_SYMBOL(unregister_sysctl_table);
>
> +/**
> + * register_sysctl_mount_point() - registers a sysctl mount point
> + * @path: path for the mount point
> + *
> + * Used to create a permanently empty directory to serve as mount point.
> + * There are some subtle but important permission checks this allows in the
> + * case of unprivileged mounts.
> + */
> +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> +{
> + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);
> +
> + if (IS_ERR(dir))
> + return NULL;
> +
> + guard(spinlock)(&sysctl_lock);
> +
> + if (!RB_EMPTY_ROOT(&dir->root)) {
> + drop_sysctl_table(&dir->header);
> + return NULL;
> + }
> +
> + dir->permanently_empty = true;
> + return &dir->header;
> +}
> +EXPORT_SYMBOL(register_sysctl_mount_point);
> +
> void setup_sysctl_set(struct ctl_table_set *set,
> struct ctl_table_root *root,
> int (*is_seen)(struct ctl_table_set *))
> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> index 7c96d5abafc7..329e68d484ed 100644
> --- a/include/linux/sysctl.h
> +++ b/include/linux/sysctl.h
> @@ -177,23 +177,14 @@ struct ctl_table_header {
> struct ctl_dir *parent;
> struct ctl_node *node;
> struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
> - /**
> - * enum type - Enumeration to differentiate between ctl target types
> - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> - * empty directory target to serve
> - * as mount point.
> - */
> - enum {
> - SYSCTL_TABLE_TYPE_DEFAULT,
> - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> - } type;
> };
>
> struct ctl_dir {
> /* Header must be at the start of ctl_dir */
> struct ctl_table_header header;
> struct rb_root root;
> + /* Permanently empty directory target to serve as mount point. */
> + bool permanently_empty;
> };
>
> struct ctl_table_set {
>
> base-commit: a6fd07f80ab7bd94edb4d56c35e61117ffb9957e
> prerequisite-patch-id: 0000000000000000000000000000000000000000
> prerequisite-patch-id: 13932e9add940cb65c71e04b5efdfcd3622fd27e
> prerequisite-patch-id: 2e4d88f7b8aaa805598f0e87a3ea726825bb4264
> prerequisite-patch-id: 674a680d9cb138cd34cfd0e1a4ec3a5d1c220078
> prerequisite-patch-id: e27c92582aa20b1dfb122c172b336dbaf9d6508a
> prerequisite-patch-id: 9b409a34ab6a4d8d8c5225ba9a72db3116e3c8b3
> prerequisite-patch-id: 86ff15a81d850ebda16bb707491251f4b705e4fd
> prerequisite-patch-id: b7ab65512ac9acfb2dd482b0271b399467afc56d
> prerequisite-patch-id: 0354922fbf2508a89f3e9d9a4e274fc98deb2e93
> prerequisite-patch-id: b71389e82026ffc19cbb717bba1a014ad6cab6da
> prerequisite-patch-id: fbb0201f89bf6c41d0585af867bdeec8d51649b2
> prerequisite-patch-id: e3b4b5b69b4eadf87ed97beb8c03a471e7628cb9
> prerequisite-patch-id: 3fbc9745cf3f28872b3e63f6d1f6e2fd7598be8a
> prerequisite-patch-id: ba2b190c2e54cfb505a282e688c2222712f0acd7
> prerequisite-patch-id: 47e5ca730748bb7bf9248a9e711045d8c1028199
> prerequisite-patch-id: dcd9f87f00290d2f9be83e404f8883eb90c5fb1c
> prerequisite-patch-id: d4629be1a61585ab821da2d2850f246761f72f25
> prerequisite-patch-id: f740190f4b94e57cbf3659f220d94483713341a1
> prerequisite-patch-id: 301c2e530e2af4568267e19247d4a49ac2a9871d
> --
> 2.43.0
>


--

Joel Granados


Attachments:
(No filename) (10.14 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-23 12:09:50

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Mon, Dec 18, 2023 at 01:21:49PM -0800, Luis Chamberlain wrote:
> So we can split this up concentually in two:
>
> * constificaiton of the table handlers
> * constification of the table struct itself
>
> On Sun, Dec 17, 2023 at 11:10:15PM +0100, Thomas Wei?schuh wrote:
> > The handlers can already be made const as shown in this series,
>
> The series did already produce issues with some builds, and so
> Julia's point is confirmed that the series only proves hanlders
> which you did build and for which 0-day has coverage for.
>
> The challenge here was to see if we could draw up a test case
> that would prove this without build tests, and what occurred to
> me was coccinelle or smatch.
>
> > > If that is indeed what you are proposing, you might not even need the
> > > un-register step as all the mutability that I have seen occurs before
> > > the register. So maybe instead of re-registering it, you can so a copy
> > > (of the changed ctl_table) to a const pointer and then pass that along
> > > to the register function.
> >
> > Tables that are modified, but *not* through the handler, would crop
> > during the constification of the table structs.
> > Which should be a second step.
>
> Instead of "croping up" at build time again, I wonder if we can do
> better with coccinelle / smatch.
>
> Joel, and yes, what you described is what I was suggesting, that is to
> avoid having to add a non-const handler a first step, instead we modify
> those callers which do require to modify the table by first a
> deregistration and later a registration. In fact to make this even
> easier a new call would be nice so to aslo be able to git grep when
> this is done in the kernel.
>
> But if what you suggest is true that there are no registrations which
> later modify the table, we don't need that. It is the uncertainty that
> we might have that this is a true statment that I wanted to challenge
> to see if we could do better. Can we avoid this being a stupid
> regression later by doing code analysis with coccinelle / smatch?
That would be amazing! Having an analysis (coccinelle or smatch) that
prevents the regression would be the cherry on top.

So to further clarify: what you propose is an additional patch in the
series that adds this regression prevention.
Or do you want a general analysis that prevents changing a variable
variable that was defined as const.

>
> The template of the above endeavor seems useful not only to this use
> case but to any place in the kernel where this previously has been done
> before, and hence my suggestion that this seems like a sensible thing
> to think over to see if we could generalize.
A generalized analysis for inadvertent de-constification would be great.
It would point to places where we need remove the const qualifier or add
it.

>
> Luis

--

Joel Granados


Attachments:
(No filename) (2.84 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-23 12:10:21

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Tue, Dec 19, 2023 at 08:29:50PM +0100, Thomas Wei?schuh wrote:
> Hi Luis and Julia,
>
> (Julia, there is a question and context for you inline, marked with your name)
>
> On 2023-12-18 13:21:49-0800, Luis Chamberlain wrote:
> > So we can split this up concentually in two:
> >
> > * constificaiton of the table handlers
> > * constification of the table struct itself
<--- snip --->
> > case but to any place in the kernel where this previously has been done
> > before, and hence my suggestion that this seems like a sensible thing
> > to think over to see if we could generalize.
>
> I'd like to split the series and submit the part up until and including
> the constification of arguments first and on its own.
> It keeps the subsystem maintainers out of the discussion of the core
> sysctl changes.
quick comment : Note that if this contains the tree-wide patches, it
will inevitably bring in the rest of the maintainers.

>
> I'll submit the core sysctl changes after I figure out proper responses
> to all review comments and we can do this in parallel to the tree-wide
> preparation.
>
> What do you think Luis and Joel?
Separating all this into patch series that have a defined motivation and
that are self contained is the way to go IMO.

Best
>
> [0] https://protect2.fireeye.com/v1/url?k=0ddcce36-6d3e536b-0ddd4579-000babd9f1ba-c68841e97c452963&q=1&e=d70f9b65-8465-4489-b777-b13eb1ffc99b&u=https%3A%2F%2Frepo.or.cz%2Fsmatch.git%2Fblob%2FHEAD%3A%2Fsmatch_scripts%2Ftest_kernel.sh

--

Joel Granados


Attachments:
(No filename) (1.52 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-23 12:11:01

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] sysctl: constify sysctl ctl_tables

On Sun, Dec 17, 2023 at 11:10:15PM +0100, Thomas Wei?schuh wrote:
> On 2023-12-17 13:02:01+0100, Joel Granados wrote:
> > Catching up with mail....
> >
> > On Tue, Dec 12, 2023 at 11:51:30PM -0800, Luis Chamberlain wrote:
> > > On Tue, Dec 12, 2023 at 10:09:30AM +0100, Joel Granados wrote:
> > > > My idea was to do something similar to your originl RFC, where you have
> > > > an temporary proc_handler something like proc_hdlr_const (we would need
> > > > to work on the name) and move each subsystem to the new handler while
> > > > the others stay with the non-const one. At the end, the old proc_handler
> > > > function name would disapear and would be completely replaced by the new
> > > > proc_hdlr_const.
> > > >
> > > > This is of course extra work and might not be worth it if you don't get
> > > > negative feedback related to tree-wide changes. Therefore I stick to my
> > > > previous suggestion. Send the big tree-wide patches and only explore
> > > > this option if someone screams.
> > >
> > > I think we can do better, can't we just increase confidence in that we
> > > don't *need* muttable ctl_cables with something like smatch or
> > > coccinelle so that we can just make them const?
> > >
> > > Seems like a noble endeavor for us to generalize.
> > >
> > > Then we just breeze through by first fixing those that *are* using
> > > mutable tables by having it just de-register and then re-register
> > So let me see if I understand your {de,re}-register idea:
> > When we have a situation (like in the networking code) where a ctl_table
> > is being used in an unmuttable way, we do your {de,re}-register trick.
>
> unmuttable?
meant muttable here.

>
> > The trick consists in unregistering an old ctl_table and reregistering
> > with a whole new const changed table. In this way, whatever we register
> > is always const.
> >
> > Once we address all the places where this happens, then we just change
> > the handler to const and we are done.
> >
> > Is that correct?
>
> I'm confused.
>
> The handlers can already be made const as shown in this series, which
> does convert the whole kernel tree.
> There is only one handler (the stackleak one) which modifies the table
> and this one is fixed as part of the series.
>
> (Plus the changes needed to the sysctl core to avoid mutation there)
>
> > If that is indeed what you are proposing, you might not even need the
> > un-register step as all the mutability that I have seen occurs before
> > the register. So maybe instead of re-registering it, you can so a copy
> > (of the changed ctl_table) to a const pointer and then pass that along
> > to the register function.
>
> Tables that are modified, but *not* through the handler, would crop
> during the constification of the table structs.
> Which should be a second step.
>
> But Luis' message was not completely clear to me.
> I guess I'm missing something.
>
> > Can't think of anything else off the top of my head. Would have to
> > actually see the code to evaluate further I think.
> >
> > > new tables if they need to be changed, and then a new series is sent
> > > once we fix all those muttable tables.
>
> Thomas

--

Joel Granados


Attachments:
(No filename) (3.18 kB)
signature.asc (673.00 B)
Download all attachments

2023-12-23 13:05:03

by Thomas Weißschuh

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

Hi Joel,

On 2023-12-21 13:09:19+0100, Joel Granados wrote:
> I had some available cycles today and wanted to look at the patch that
> you sent. I could not apply it on top of 6.7-rc6. Have you thought about
> taking this out of your "constification" series and posting it as
> something that comes before the const stuff?

Yes, I am planning to submit this standalone. But I need to do some more
investigation to properly handle the existing comments.

FYI this out-of-series patch is meant to be applied on top of the rest
of the series.


Another question:

When did you write this mail?

The Date header says it's from the 21st but I only received it today
(the 23rd). All other mail headers also say that it was only sent on
23rd. The same seems to happen with your other mails, too.

Thomas

> On Wed, Dec 06, 2023 at 06:53:10AM +0100, Thomas Weißschuh wrote:
> > On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> > > On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> > > >
> > > > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > > > return -EROFS;
> > > > > >
> > > > > > /* Am I creating a permanently empty directory? */
> > > > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > > > return -EINVAL;
> > > > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > > > >
> > > > > While you're at it.
> > > >
> > > > This hunk is completely gone in v3/the code that you merged.
> > >
> > > It is worse in that it is not obvious:
> > >
> > > + if (table == sysctl_mount_point)
> > > + sysctl_set_perm_empty_ctl_header(head);
> > >
> > > > Which kind of unsafety do you envision here?
> > >
> > > Making the code obvious during patch review hy this is needed /
> > > special, and if we special case this, why not remove enum, and make it
> > > specific to only that one table. The catch is that it is not
> > > immediately obvious that we actually call
> > > sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> > > question if this can be cleaned up somehow.
> >
> > Making it specific won't work because the flag needs to be transferred
> > from the leaf table to the table representing the directory.
> >
> > What do you think of the aproach taken in the attached patch?
> > (On top of current sysctl-next, including my series)
> >
> > Note: Current sysctl-next ist still based on v6.6.
>
> > From 2fb9887fb2a5024c2620f2d694bc6dcc32afde67 Mon Sep 17 00:00:00 2001
> > From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> > Date: Wed, 6 Dec 2023 06:17:22 +0100
> > Subject: [PATCH] sysctl: simplify handling of permanently empty directories
> >
> > ---
> > fs/proc/proc_sysctl.c | 76 +++++++++++++++++++-----------------------
> > include/linux/sysctl.h | 13 ++------
> > 2 files changed, 36 insertions(+), 53 deletions(-)
> >
> > diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> > index c92e9b972ada..c4d6d09b0e68 100644
> > --- a/fs/proc/proc_sysctl.c
> > +++ b/fs/proc/proc_sysctl.c
> > @@ -17,6 +17,7 @@
> > #include <linux/bpf-cgroup.h>
> > #include <linux/mount.h>
> > #include <linux/kmemleak.h>
> > +#include <linux/cleanup.h>
> > #include "internal.h"
> >
> > #define list_for_each_table_entry(entry, header) \
> > @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> > static const struct file_operations proc_sys_dir_file_operations;
> > static const struct inode_operations proc_sys_dir_operations;
> >
> > -/* Support for permanently empty directories */
> > -static const struct ctl_table sysctl_mount_point[] = {
> > - { }
> > -};
> > -
> > -/**
> > - * register_sysctl_mount_point() - registers a sysctl mount point
> > - * @path: path for the mount point
> > - *
> > - * Used to create a permanently empty directory to serve as mount point.
> > - * There are some subtle but important permission checks this allows in the
> > - * case of unprivileged mounts.
> > - */
> > -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> > -{
> > - return register_sysctl(path, sysctl_mount_point);
> > -}
> > -EXPORT_SYMBOL(register_sysctl_mount_point);
> > -
> > -#define sysctl_is_perm_empty_ctl_header(hptr) \
> > - (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> > -#define sysctl_set_perm_empty_ctl_header(hptr) \
> > - (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> > -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> > - (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
> > -
> > void proc_sys_poll_notify(struct ctl_table_poll *poll)
> > {
> > if (!poll)
> > @@ -199,8 +174,6 @@ static void init_header(struct ctl_table_header *head,
> > head->set = set;
> > head->parent = NULL;
> > head->node = node;
> > - if (table == sysctl_mount_point)
> > - sysctl_set_perm_empty_ctl_header(head);
> > INIT_HLIST_HEAD(&head->inodes);
> > if (node) {
> > const struct ctl_table *entry;
> > @@ -228,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> >
> >
> > /* Is this a permanently empty directory? */
> > - if (sysctl_is_perm_empty_ctl_header(dir_h))
> > + if (dir->permanently_empty)
> > return -EROFS;
> >
> > - /* Am I creating a permanently empty directory? */
> > - if (header->ctl_table_size > 0 &&
> > - sysctl_is_perm_empty_ctl_header(header)) {
> > - if (!RB_EMPTY_ROOT(&dir->root))
> > - return -EINVAL;
> > - sysctl_set_perm_empty_ctl_header(dir_h);
> > - }
> > -
> > dir_h->nreg++;
> > header->parent = dir;
> > err = insert_links(header);
> > @@ -254,8 +219,6 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > erase_header(header);
> > put_links(header);
> > fail_links:
> > - if (header->ctl_table == sysctl_mount_point)
> > - sysctl_clear_perm_empty_ctl_header(dir_h);
> > header->parent = NULL;
> > drop_sysctl_table(dir_h);
> > return err;
> > @@ -442,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> > struct ctl_table_header *head, const struct ctl_table *table)
> > {
> > struct ctl_table_root *root = head->root;
> > + struct ctl_dir *ctl_dir;
> > struct inode *inode;
> > struct proc_inode *ei;
> >
> > @@ -475,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> > inode->i_mode |= S_IFDIR;
> > inode->i_op = &proc_sys_dir_operations;
> > inode->i_fop = &proc_sys_dir_file_operations;
> > - if (sysctl_is_perm_empty_ctl_header(head))
> > +
> > + ctl_dir = container_of(head, struct ctl_dir, header);
> > + if (ctl_dir->permanently_empty)
> > make_empty_dir_inode(inode);
> > }
> >
> > @@ -1214,8 +1180,7 @@ static bool get_links(struct ctl_dir *dir,
> > struct ctl_table_header *tmp_head;
> > const struct ctl_table *entry, *link;
> >
> > - if (header->ctl_table_size == 0 ||
> > - sysctl_is_perm_empty_ctl_header(header))
> > + if (header->ctl_table_size == 0 || dir->permanently_empty)
> > return true;
> >
> > /* Are there links available for every entry in table? */
> > @@ -1536,6 +1501,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> > }
> > EXPORT_SYMBOL(unregister_sysctl_table);
> >
> > +/**
> > + * register_sysctl_mount_point() - registers a sysctl mount point
> > + * @path: path for the mount point
> > + *
> > + * Used to create a permanently empty directory to serve as mount point.
> > + * There are some subtle but important permission checks this allows in the
> > + * case of unprivileged mounts.
> > + */
> > +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> > +{
> > + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);
> > +
> > + if (IS_ERR(dir))
> > + return NULL;
> > +
> > + guard(spinlock)(&sysctl_lock);
> > +
> > + if (!RB_EMPTY_ROOT(&dir->root)) {
> > + drop_sysctl_table(&dir->header);
> > + return NULL;
> > + }
> > +
> > + dir->permanently_empty = true;
> > + return &dir->header;
> > +}
> > +EXPORT_SYMBOL(register_sysctl_mount_point);
> > +
> > void setup_sysctl_set(struct ctl_table_set *set,
> > struct ctl_table_root *root,
> > int (*is_seen)(struct ctl_table_set *))
> > diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> > index 7c96d5abafc7..329e68d484ed 100644
> > --- a/include/linux/sysctl.h
> > +++ b/include/linux/sysctl.h
> > @@ -177,23 +177,14 @@ struct ctl_table_header {
> > struct ctl_dir *parent;
> > struct ctl_node *node;
> > struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
> > - /**
> > - * enum type - Enumeration to differentiate between ctl target types
> > - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> > - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> > - * empty directory target to serve
> > - * as mount point.
> > - */
> > - enum {
> > - SYSCTL_TABLE_TYPE_DEFAULT,
> > - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> > - } type;
> > };
> >
> > struct ctl_dir {
> > /* Header must be at the start of ctl_dir */
> > struct ctl_table_header header;
> > struct rb_root root;
> > + /* Permanently empty directory target to serve as mount point. */
> > + bool permanently_empty;
> > };
> >
> > struct ctl_table_set {
> >
> > base-commit: a6fd07f80ab7bd94edb4d56c35e61117ffb9957e
> > prerequisite-patch-id: 0000000000000000000000000000000000000000
> > prerequisite-patch-id: 13932e9add940cb65c71e04b5efdfcd3622fd27e
> > prerequisite-patch-id: 2e4d88f7b8aaa805598f0e87a3ea726825bb4264
> > prerequisite-patch-id: 674a680d9cb138cd34cfd0e1a4ec3a5d1c220078
> > prerequisite-patch-id: e27c92582aa20b1dfb122c172b336dbaf9d6508a
> > prerequisite-patch-id: 9b409a34ab6a4d8d8c5225ba9a72db3116e3c8b3
> > prerequisite-patch-id: 86ff15a81d850ebda16bb707491251f4b705e4fd
> > prerequisite-patch-id: b7ab65512ac9acfb2dd482b0271b399467afc56d
> > prerequisite-patch-id: 0354922fbf2508a89f3e9d9a4e274fc98deb2e93
> > prerequisite-patch-id: b71389e82026ffc19cbb717bba1a014ad6cab6da
> > prerequisite-patch-id: fbb0201f89bf6c41d0585af867bdeec8d51649b2
> > prerequisite-patch-id: e3b4b5b69b4eadf87ed97beb8c03a471e7628cb9
> > prerequisite-patch-id: 3fbc9745cf3f28872b3e63f6d1f6e2fd7598be8a
> > prerequisite-patch-id: ba2b190c2e54cfb505a282e688c2222712f0acd7
> > prerequisite-patch-id: 47e5ca730748bb7bf9248a9e711045d8c1028199
> > prerequisite-patch-id: dcd9f87f00290d2f9be83e404f8883eb90c5fb1c
> > prerequisite-patch-id: d4629be1a61585ab821da2d2850f246761f72f25
> > prerequisite-patch-id: f740190f4b94e57cbf3659f220d94483713341a1
> > prerequisite-patch-id: 301c2e530e2af4568267e19247d4a49ac2a9871d
> > --
> > 2.43.0
> >
>
>
> --
>
> Joel Granados



2023-12-24 18:51:52

by Joel Granados

[permalink] [raw]
Subject: Re: [PATCH v2 13/18] sysctl: move sysctl type to ctl_table_header

On Sat, Dec 23, 2023 at 02:04:27PM +0100, Thomas Weißschuh wrote:
> Hi Joel,
>
> On 2023-12-21 13:09:19+0100, Joel Granados wrote:
> > I had some available cycles today and wanted to look at the patch that
> > you sent. I could not apply it on top of 6.7-rc6. Have you thought about
> > taking this out of your "constification" series and posting it as
> > something that comes before the const stuff?
>
> Yes, I am planning to submit this standalone. But I need to do some more
> investigation to properly handle the existing comments.
Understood.

>
> FYI this out-of-series patch is meant to be applied on top of the rest
> of the series.
Ok.

>
>
> Another question:
>
> When did you write this mail?
>
> The Date header says it's from the 21st but I only received it today
> (the 23rd). All other mail headers also say that it was only sent on
> 23rd. The same seems to happen with your other mails, too.
Sometimes I do the review even if I don't have connection. Everything
goes out once I get back on the network.

So there is the timestamp of when I "sent" but was on standby in my
outgoing mails 21st. And then the actual sending occurred some days
later when I was back on the network.

>
> Thomas
>
> > On Wed, Dec 06, 2023 at 06:53:10AM +0100, Thomas Weißschuh wrote:
> > > On 2023-12-05 14:50:01-0800, Luis Chamberlain wrote:
> > > > On Tue, Dec 5, 2023 at 2:41 PM Thomas Weißschuh <[email protected]> wrote:
> > > > >
> > > > > On 2023-12-05 14:33:38-0800, Luis Chamberlain wrote:
> > > > > > On Mon, Dec 04, 2023 at 08:52:26AM +0100, Thomas Weißschuh wrote:
> > > > > > > @@ -231,7 +231,8 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > > > > > return -EROFS;
> > > > > > >
> > > > > > > /* Am I creating a permanently empty directory? */
> > > > > > > - if (sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > > + if (header->ctl_table == sysctl_mount_point ||
> > > > > > > + sysctl_is_perm_empty_ctl_header(header)) {
> > > > > > > if (!RB_EMPTY_ROOT(&dir->root))
> > > > > > > return -EINVAL;
> > > > > > > sysctl_set_perm_empty_ctl_header(dir_h);
> > > > > >
> > > > > > While you're at it.
> > > > >
> > > > > This hunk is completely gone in v3/the code that you merged.
> > > >
> > > > It is worse in that it is not obvious:
> > > >
> > > > + if (table == sysctl_mount_point)
> > > > + sysctl_set_perm_empty_ctl_header(head);
> > > >
> > > > > Which kind of unsafety do you envision here?
> > > >
> > > > Making the code obvious during patch review hy this is needed /
> > > > special, and if we special case this, why not remove enum, and make it
> > > > specific to only that one table. The catch is that it is not
> > > > immediately obvious that we actually call
> > > > sysctl_set_perm_empty_ctl_header() in other places, and it begs the
> > > > question if this can be cleaned up somehow.
> > >
> > > Making it specific won't work because the flag needs to be transferred
> > > from the leaf table to the table representing the directory.
> > >
> > > What do you think of the aproach taken in the attached patch?
> > > (On top of current sysctl-next, including my series)
> > >
> > > Note: Current sysctl-next ist still based on v6.6.
> >
> > > From 2fb9887fb2a5024c2620f2d694bc6dcc32afde67 Mon Sep 17 00:00:00 2001
> > > From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <[email protected]>
> > > Date: Wed, 6 Dec 2023 06:17:22 +0100
> > > Subject: [PATCH] sysctl: simplify handling of permanently empty directories
> > >
> > > ---
> > > fs/proc/proc_sysctl.c | 76 +++++++++++++++++++-----------------------
> > > include/linux/sysctl.h | 13 ++------
> > > 2 files changed, 36 insertions(+), 53 deletions(-)
> > >
> > > diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> > > index c92e9b972ada..c4d6d09b0e68 100644
> > > --- a/fs/proc/proc_sysctl.c
> > > +++ b/fs/proc/proc_sysctl.c
> > > @@ -17,6 +17,7 @@
> > > #include <linux/bpf-cgroup.h>
> > > #include <linux/mount.h>
> > > #include <linux/kmemleak.h>
> > > +#include <linux/cleanup.h>
> > > #include "internal.h"
> > >
> > > #define list_for_each_table_entry(entry, header) \
> > > @@ -29,32 +30,6 @@ static const struct inode_operations proc_sys_inode_operations;
> > > static const struct file_operations proc_sys_dir_file_operations;
> > > static const struct inode_operations proc_sys_dir_operations;
> > >
> > > -/* Support for permanently empty directories */
> > > -static const struct ctl_table sysctl_mount_point[] = {
> > > - { }
> > > -};
> > > -
> > > -/**
> > > - * register_sysctl_mount_point() - registers a sysctl mount point
> > > - * @path: path for the mount point
> > > - *
> > > - * Used to create a permanently empty directory to serve as mount point.
> > > - * There are some subtle but important permission checks this allows in the
> > > - * case of unprivileged mounts.
> > > - */
> > > -struct ctl_table_header *register_sysctl_mount_point(const char *path)
> > > -{
> > > - return register_sysctl(path, sysctl_mount_point);
> > > -}
> > > -EXPORT_SYMBOL(register_sysctl_mount_point);
> > > -
> > > -#define sysctl_is_perm_empty_ctl_header(hptr) \
> > > - (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> > > -#define sysctl_set_perm_empty_ctl_header(hptr) \
> > > - (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
> > > -#define sysctl_clear_perm_empty_ctl_header(hptr) \
> > > - (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
> > > -
> > > void proc_sys_poll_notify(struct ctl_table_poll *poll)
> > > {
> > > if (!poll)
> > > @@ -199,8 +174,6 @@ static void init_header(struct ctl_table_header *head,
> > > head->set = set;
> > > head->parent = NULL;
> > > head->node = node;
> > > - if (table == sysctl_mount_point)
> > > - sysctl_set_perm_empty_ctl_header(head);
> > > INIT_HLIST_HEAD(&head->inodes);
> > > if (node) {
> > > const struct ctl_table *entry;
> > > @@ -228,17 +201,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > >
> > >
> > > /* Is this a permanently empty directory? */
> > > - if (sysctl_is_perm_empty_ctl_header(dir_h))
> > > + if (dir->permanently_empty)
> > > return -EROFS;
> > >
> > > - /* Am I creating a permanently empty directory? */
> > > - if (header->ctl_table_size > 0 &&
> > > - sysctl_is_perm_empty_ctl_header(header)) {
> > > - if (!RB_EMPTY_ROOT(&dir->root))
> > > - return -EINVAL;
> > > - sysctl_set_perm_empty_ctl_header(dir_h);
> > > - }
> > > -
> > > dir_h->nreg++;
> > > header->parent = dir;
> > > err = insert_links(header);
> > > @@ -254,8 +219,6 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
> > > erase_header(header);
> > > put_links(header);
> > > fail_links:
> > > - if (header->ctl_table == sysctl_mount_point)
> > > - sysctl_clear_perm_empty_ctl_header(dir_h);
> > > header->parent = NULL;
> > > drop_sysctl_table(dir_h);
> > > return err;
> > > @@ -442,6 +405,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> > > struct ctl_table_header *head, const struct ctl_table *table)
> > > {
> > > struct ctl_table_root *root = head->root;
> > > + struct ctl_dir *ctl_dir;
> > > struct inode *inode;
> > > struct proc_inode *ei;
> > >
> > > @@ -475,7 +439,9 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
> > > inode->i_mode |= S_IFDIR;
> > > inode->i_op = &proc_sys_dir_operations;
> > > inode->i_fop = &proc_sys_dir_file_operations;
> > > - if (sysctl_is_perm_empty_ctl_header(head))
> > > +
> > > + ctl_dir = container_of(head, struct ctl_dir, header);
> > > + if (ctl_dir->permanently_empty)
> > > make_empty_dir_inode(inode);
> > > }
> > >
> > > @@ -1214,8 +1180,7 @@ static bool get_links(struct ctl_dir *dir,
> > > struct ctl_table_header *tmp_head;
> > > const struct ctl_table *entry, *link;
> > >
> > > - if (header->ctl_table_size == 0 ||
> > > - sysctl_is_perm_empty_ctl_header(header))
> > > + if (header->ctl_table_size == 0 || dir->permanently_empty)
> > > return true;
> > >
> > > /* Are there links available for every entry in table? */
> > > @@ -1536,6 +1501,33 @@ void unregister_sysctl_table(struct ctl_table_header * header)
> > > }
> > > EXPORT_SYMBOL(unregister_sysctl_table);
> > >
> > > +/**
> > > + * register_sysctl_mount_point() - registers a sysctl mount point
> > > + * @path: path for the mount point
> > > + *
> > > + * Used to create a permanently empty directory to serve as mount point.
> > > + * There are some subtle but important permission checks this allows in the
> > > + * case of unprivileged mounts.
> > > + */
> > > +struct ctl_table_header *register_sysctl_mount_point(const char *path)
> > > +{
> > > + struct ctl_dir *dir = sysctl_mkdir_p(&sysctl_table_root.default_set.dir, path);
> > > +
> > > + if (IS_ERR(dir))
> > > + return NULL;
> > > +
> > > + guard(spinlock)(&sysctl_lock);
> > > +
> > > + if (!RB_EMPTY_ROOT(&dir->root)) {
> > > + drop_sysctl_table(&dir->header);
> > > + return NULL;
> > > + }
> > > +
> > > + dir->permanently_empty = true;
> > > + return &dir->header;
> > > +}
> > > +EXPORT_SYMBOL(register_sysctl_mount_point);
> > > +
> > > void setup_sysctl_set(struct ctl_table_set *set,
> > > struct ctl_table_root *root,
> > > int (*is_seen)(struct ctl_table_set *))
> > > diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
> > > index 7c96d5abafc7..329e68d484ed 100644
> > > --- a/include/linux/sysctl.h
> > > +++ b/include/linux/sysctl.h
> > > @@ -177,23 +177,14 @@ struct ctl_table_header {
> > > struct ctl_dir *parent;
> > > struct ctl_node *node;
> > > struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
> > > - /**
> > > - * enum type - Enumeration to differentiate between ctl target types
> > > - * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
> > > - * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
> > > - * empty directory target to serve
> > > - * as mount point.
> > > - */
> > > - enum {
> > > - SYSCTL_TABLE_TYPE_DEFAULT,
> > > - SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
> > > - } type;
> > > };
> > >
> > > struct ctl_dir {
> > > /* Header must be at the start of ctl_dir */
> > > struct ctl_table_header header;
> > > struct rb_root root;
> > > + /* Permanently empty directory target to serve as mount point. */
> > > + bool permanently_empty;
> > > };
> > >
> > > struct ctl_table_set {
> > >
> > > base-commit: a6fd07f80ab7bd94edb4d56c35e61117ffb9957e
> > > prerequisite-patch-id: 0000000000000000000000000000000000000000
> > > prerequisite-patch-id: 13932e9add940cb65c71e04b5efdfcd3622fd27e
> > > prerequisite-patch-id: 2e4d88f7b8aaa805598f0e87a3ea726825bb4264
> > > prerequisite-patch-id: 674a680d9cb138cd34cfd0e1a4ec3a5d1c220078
> > > prerequisite-patch-id: e27c92582aa20b1dfb122c172b336dbaf9d6508a
> > > prerequisite-patch-id: 9b409a34ab6a4d8d8c5225ba9a72db3116e3c8b3
> > > prerequisite-patch-id: 86ff15a81d850ebda16bb707491251f4b705e4fd
> > > prerequisite-patch-id: b7ab65512ac9acfb2dd482b0271b399467afc56d
> > > prerequisite-patch-id: 0354922fbf2508a89f3e9d9a4e274fc98deb2e93
> > > prerequisite-patch-id: b71389e82026ffc19cbb717bba1a014ad6cab6da
> > > prerequisite-patch-id: fbb0201f89bf6c41d0585af867bdeec8d51649b2
> > > prerequisite-patch-id: e3b4b5b69b4eadf87ed97beb8c03a471e7628cb9
> > > prerequisite-patch-id: 3fbc9745cf3f28872b3e63f6d1f6e2fd7598be8a
> > > prerequisite-patch-id: ba2b190c2e54cfb505a282e688c2222712f0acd7
> > > prerequisite-patch-id: 47e5ca730748bb7bf9248a9e711045d8c1028199
> > > prerequisite-patch-id: dcd9f87f00290d2f9be83e404f8883eb90c5fb1c
> > > prerequisite-patch-id: d4629be1a61585ab821da2d2850f246761f72f25
> > > prerequisite-patch-id: f740190f4b94e57cbf3659f220d94483713341a1
> > > prerequisite-patch-id: 301c2e530e2af4568267e19247d4a49ac2a9871d
> > > --
> > > 2.43.0
> > >
> >
> >
> > --
> >
> > Joel Granados
>
>

--

Joel Granados


Attachments:
(No filename) (12.13 kB)
signature.asc (673.00 B)
Download all attachments