[PATCH 06/11] moduleparam: Add seq_buf-based .get callback alongside .get_str

4 views
Skip to first unread message

Kees Cook

unread,
May 21, 2026, 11:11:26 AMMay 21
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

Petr Pavlu

unread,
May 25, 2026, 12:21:14 PMMay 25
to Kees Cook, Luis Chamberlain, Pengpeng Hou, 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
On 5/21/26 3:33 PM, Kees Cook wrote:
> 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>

Reviewed-by: Petr Pavlu <petr....@suse.com>

-- Petr
Reply all
Reply to author
Forward
0 new messages