Kees Cook
unread,May 21, 2026, 11:11:26 AMMay 21Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Luis Chamberlain, Kees Cook, Pengpeng Hou, Petr Pavlu, Richard Weinberger, Anton Ivanov, Johannes Berg, Rafael J. Wysocki, Len Brown, Corey Minyard, Gabriel Somlo, Michael S. Tsirkin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, David Airlie, Simona Vetter, Bart Van Assche, Jason Gunthorpe, Leon Romanovsky, Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab, Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley, Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba, Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo, Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie, Benjamin Berg, Ilpo Järvinen, David E. Box, Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra, Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x...@kernel.org, H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov, Andrew Morton, John Johansen, Paul Moore, James Morris, Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, k...@vger.kernel.org, dmae...@vger.kernel.org, linux-...@vger.kernel.org, kasa...@googlegroups.com, linu...@kvack.org, appa...@lists.ubuntu.com, linux-secu...@vger.kernel.org, linu...@lists.infradead.org, linux...@vger.kernel.org, openipmi-...@lists.sourceforge.net, qemu-...@nongnu.org, inte...@lists.freedesktop.org, dri-...@lists.freedesktop.org, linux...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linuxp...@lists.ozlabs.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, usb-s...@lists.one-eyed-alien.net, virtual...@lists.linux.dev, linux-...@vger.kernel.org, linux...@vger.kernel.org, net...@vger.kernel.org, linux-...@vger.kernel.org, linux-h...@vger.kernel.org
Add a new struct kernel_param_ops::get callback whose signature
takes a struct seq_buf instead of a raw char buffer:
int (*get)(struct seq_buf *sb, const struct kernel_param *kp);
The previously-legacy .get field is now .get_str (char *buffer);
.get is the new seq_buf-aware form. param_attr_show() prefers .get
when set, otherwise falls back to .get_str. WARN_ON_ONCE() if both
are set. Return contract for .get:
< 0 : errno propagated to userspace; seq_buf contents discarded
= 0 : success; length derived from seq_buf_used()
> 0 : forbidden; the dispatcher WARN_ON_ONCE()s and treats as 0
The default policy on seq_buf_has_overflowed() is silent truncation,
matching scnprintf()/sysfs_emit() behaviour. Callbacks that want a
specific overflow errno can check seq_buf_has_overflowed() and
return their preferred error.
No callbacks use .get yet; the legacy path is still the only one in use
after this commit. A subsequent commit teaches DEFINE_KERNEL_PARAM_OPS
to route initializers by type.
Signed-off-by: Kees Cook <
ke...@kernel.org>
---
include/linux/moduleparam.h | 13 ++++++++++++-
kernel/params.c | 26 ++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index f5f4148e2504..c52120f6ac28 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -7,6 +7,7 @@
#include <linux/build_bug.h>
#include <linux/compiler.h>
#include <linux/init.h>
+#include <linux/seq_buf.h>
#include <linux/stringify.h>
#include <linux/sysfs.h>
#include <linux/types.h>
@@ -62,7 +63,17 @@ struct kernel_param_ops {
unsigned int flags;
/* Returns 0, or -errno. arg is in kp->arg. */
int (*set)(const char *val, const struct kernel_param *kp);
- /* Returns length written or -errno. Buffer is 4k (ie. be short!) */
+ /*
+ * Format the parameter's value into @s. Return 0 on success
+ * (length derived from seq_buf_used()) or -errno on error.
+ * Exactly one of .get and .get_str should be set; the dispatcher
+ * WARNs and prefers .get if both are.
+ */
+ int (*get)(struct seq_buf *s, const struct kernel_param *kp);
+ /*
+ * Returns length written or -errno. Buffer is 4k (ie. be short!).
+ * Deprecated: callbacks should implement .get instead.
+ */
int (*get_str)(char *buffer, const struct kernel_param *kp);
/* Optional function to free kp->arg when module unloaded. */
void (*free)(void *arg);
diff --git a/kernel/params.c b/kernel/params.c
index 6852caea1785..4eda2d23ddf2 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -553,12 +553,34 @@ static ssize_t param_attr_show(const struct module_attribute *mattr,
{
int count;
const struct param_attribute *attribute = to_param_attr(mattr);
+ const struct kernel_param_ops *ops = attribute->param->ops;
- if (!attribute->param->ops->get_str)
+ if (!ops->get && !ops->get_str)
return -EPERM;
+ WARN_ON_ONCE(ops->get && ops->get_str);
+
kernel_param_lock(mk->mod);
- count = attribute->param->ops->get_str(buf, attribute->param);
+ if (ops->get) {
+ struct seq_buf s;
+
+ seq_buf_init(&s, buf, PAGE_SIZE);
+ count = ops->get(&s, attribute->param);
+ if (count >= 0) {
+ WARN_ON_ONCE(count > 0);
+ count = seq_buf_used(&s);
+ /* Make sure string is terminated. */
+ seq_buf_str(&s);
+ /*
+ * If overflowed, reduce count by 1 for trailing
+ * NUL byte.
+ */
+ if (seq_buf_has_overflowed(&s))
+ count--;
+ }
+ } else {
+ count = ops->get_str(buf, attribute->param);
+ }
kernel_param_unlock(mk->mod);
return count;
}
--
2.34.1