lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 25 Nov 2023 13:52:52 +0100
From: Thomas Weißschuh <linux@...ssschuh.net>
To: Kees Cook <keescook@...omium.org>, 
 "Gustavo A. R. Silva" <gustavoars@...nel.org>, 
 Luis Chamberlain <mcgrof@...nel.org>, Iurii Zaikin <yzaikin@...gle.com>, 
 Greg Kroah-Hartman <gregkh@...uxfoundation.org>, 
 Joel Granados <j.granados@...sung.com>
Cc: linux-hardening@...r.kernel.org, linux-kernel@...r.kernel.org, 
 linux-fsdevel@...r.kernel.org, 
 Thomas Weißschuh <linux@...ssschuh.net>
Subject: [PATCH RFC 3/7] sysctl: add proc_handler_new to struct ctl_table

The existing handler function take the struct ctl_table as a mutable
parameter. This prevents the table definitions from being put into
.rodata where they would be protected from accidental or malicious
modification.

As many parts of the kernel define proc_handlers provide a gradual
transition mechanism through the introduction of a new field which takes
the table as a read-only parameter.

Signed-off-by: Thomas Weißschuh <linux@...ssschuh.net>
---
 fs/proc/proc_sysctl.c  |  6 ++++--
 include/linux/sysctl.h | 17 +++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 1bb0aa2ff501..810ecdd3b84c 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -573,7 +573,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
 
 	/* if that can happen at all, it should be -EINVAL, not -EISDIR */
 	error = -EINVAL;
-	if (!table->proc_handler)
+	if (!table->proc_handler && !table->proc_handler_new)
 		goto out;
 
 	/* don't even try if the size is too large */
@@ -655,7 +655,7 @@ static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
 	if (IS_ERR(head))
 		return EPOLLERR | EPOLLHUP;
 
-	if (!table->proc_handler)
+	if (!table->proc_handler && !table->proc_handler_new)
 		goto out;
 
 	if (!table->poll)
@@ -1333,6 +1333,8 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
  *
  * proc_handler - the text handler routine (described below)
  *
+ * proc_handler_new - const variant of the text handler routine (described below)
+ *
  * extra1, extra2 - extra pointers usable by the proc handler routines
  * XXX: we should eventually modify these to use long min / max [0]
  * [0] https://lkml.kernel.org/87zgpte9o4.fsf@email.froward.int.ebiederm.org
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 604aaaa1fce2..de1a5a714070 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -63,6 +63,8 @@ extern const unsigned long sysctl_long_vals[];
 
 typedef int proc_handler(struct ctl_table *ctl, int write, void *buffer,
 		size_t *lenp, loff_t *ppos);
+typedef int proc_handler_new(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,
@@ -107,10 +109,10 @@ int proc_do_static_key(struct ctl_table *table, int write, void *buffer,
  * struct enable minimal validation of the values being written to be
  * performed, and the mode field allows minimal authentication.
  * 
- * There must be a proc_handler routine for any terminal nodes
- * mirrored under /proc/sys (non-terminals are handled by a built-in
- * directory handler).  Several default handlers are available to
- * cover common cases.
+ * There must be one proc_handler/proc_handler_new routine for any terminal
+ * nodes mirrored under /proc/sys (non-terminals are handled by a built-in
+ * directory handler).
+ * Several default handlers are available to cover common cases.
  */
 
 /* Support for userspace poll() to watch for changes */
@@ -149,6 +151,7 @@ struct ctl_table {
 		SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
 	} type;
 	proc_handler *proc_handler;	/* Callback for text formatting */
+	proc_handler_new *proc_handler_new;	/* Callback for text formatting */
 	struct ctl_table_poll *poll;
 	void *extra1;
 	void *extra2;
@@ -301,6 +304,12 @@ int sysctl_max_threads(struct ctl_table *table, int write, void *buffer,
 static inline int sysctl_run_handler(struct ctl_table *ctl, int write,
 				     void *buffer, size_t *lenp, loff_t *ppos)
 {
+	if (ctl->proc_handler_new && ctl->proc_handler)
+		pr_warn_ratelimited("sysctl table %s has both proc_handler and proc_handler_new, this is a but\n",
+				    ctl->procname);
+
+	if (ctl->proc_handler_new)
+		return ctl->proc_handler_new(ctl, write, buffer, lenp, ppos);
 	return ctl->proc_handler(ctl, write, buffer, lenp, ppos);
 }
 

-- 
2.43.0


Powered by blists - more mailing lists