lib/tests/printf_kunit.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
Fill out the tests for restricted kernel pointers, using the %pK format.
This test can only be executed when built into the kernel, as modules
do not have access to the kptr_restrict knob.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
Please note that changes to the kptr_restrict sysctl from the kernel
commandline are only applied *after* the boot-time KUnit tests run.
---
lib/tests/printf_kunit.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c
index 7617e5b8b02c..af15d2ab4046 100644
--- a/lib/tests/printf_kunit.c
+++ b/lib/tests/printf_kunit.c
@@ -316,7 +316,31 @@ symbol_ptr(struct kunit *kunittest)
static void
kernel_ptr(struct kunit *kunittest)
{
- /* We can't test this without access to kptr_restrict. */
+#ifdef MODULE
+ kunit_skip(kunittest, "cannot access kptr_restrict from test module");
+ return;
+#endif
+
+ switch (kptr_restrict) {
+ case 0:
+ if (no_hash_pointers) {
+ test(PTR_STR, "%pK", PTR);
+ } else {
+ char buf[PLAIN_BUF_SIZE];
+
+ plain_hash_to_buffer(kunittest, PTR, buf, PLAIN_BUF_SIZE);
+ /* %pK behaves the same as hashing */
+ test(buf, "%pK", PTR);
+ }
+ break;
+ case 1:
+ test(PTR_STR, "%pK", PTR);
+ break;
+ case 2:
+ default:
+ test(ZEROS "00000000", "%pK", PTR);
+ break;
+ }
}
static void
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20260109-restricted-pointers-kunit-test-ff4ec887bcd8
Best regards,
--
Thomas Weißschuh <thomas.weissschuh@linutronix.de>
On Wed 2026-01-14 08:27:34, Thomas Weißschuh wrote:
> Fill out the tests for restricted kernel pointers, using the %pK format.
> This test can only be executed when built into the kernel, as modules
> do not have access to the kptr_restrict knob.
I think that we could export "kptr_restrict" like we did
with no_hash_pointers. AFAIK, it has been exported just because
of the test module as well.
> Please note that changes to the kptr_restrict sysctl from the kernel
> commandline are only applied *after* the boot-time KUnit tests run.
This is another motivation to export the symbol. Otherwise, it is
really hard to test the non-default variants.
BTW: I have recently heard about EXPORT_SYMBOL_NS(). It would allow
to export the symbol only for some specific modules.
I am not sure how exactly it works. I wonder if there already
exists a namespace for KUnit tests.
It would be nice to use it, even for "no_hash_pointers"...
> --- a/lib/tests/printf_kunit.c
> +++ b/lib/tests/printf_kunit.c
> @@ -316,7 +316,31 @@ symbol_ptr(struct kunit *kunittest)
> static void
> kernel_ptr(struct kunit *kunittest)
> {
> - /* We can't test this without access to kptr_restrict. */
> +#ifdef MODULE
> + kunit_skip(kunittest, "cannot access kptr_restrict from test module");
> + return;
> +#endif
> +
> + switch (kptr_restrict) {
> + case 0:
> + if (no_hash_pointers) {
> + test(PTR_STR, "%pK", PTR);
> + } else {
> + char buf[PLAIN_BUF_SIZE];
> +
> + plain_hash_to_buffer(kunittest, PTR, buf, PLAIN_BUF_SIZE);
> + /* %pK behaves the same as hashing */
> + test(buf, "%pK", PTR);
> + }
> + break;
> + case 1:
> + test(PTR_STR, "%pK", PTR);
Hmm, the behavior of %pK depends on capabilities of the caller.
The above code would work when the test is built in.
But we might need to check the capabilities when using test module.
If I get it correctly, the module loaded requires CAP_SYS_MODULE
while %pK behavior depends on CAP_SYSLOG...
> + break;
> + case 2:
> + default:
> + test(ZEROS "00000000", "%pK", PTR);
> + break;
> + }
> }
>
> static void
Anyway, thanks for working on this.
Best Regards,
Petr
On Fri, Jan 16, 2026 at 06:06:59PM +0100, Petr Mladek wrote:
> On Wed 2026-01-14 08:27:34, Thomas Weißschuh wrote:
> > Fill out the tests for restricted kernel pointers, using the %pK format.
> > This test can only be executed when built into the kernel, as modules
> > do not have access to the kptr_restrict knob.
>
> I think that we could export "kptr_restrict" like we did
> with no_hash_pointers. AFAIK, it has been exported just because
> of the test module as well.
>
> > Please note that changes to the kptr_restrict sysctl from the kernel
> > commandline are only applied *after* the boot-time KUnit tests run.
>
> This is another motivation to export the symbol. Otherwise, it is
> really hard to test the non-default variants.
This might a good place to pitch an idea I have for %pK,
which would also make testing easier:
I'd like to split out the configuration lookup out of vsprintf() into a
dedicated function and let the user of vsprintf pass its explicitly.
This allows us the enforce its usage only from file context and makes the
caller responsible for handling the potential sleeping calls into the
security subsystem. vsprintf() becomes a predictable string formatting
function again.
/* include/linux/sprintf.h */
enum ptr_format {
PTR_FORMAT_HASHED,
PTR_FORMAT_PLAIN,
PTR_FORMAT_ZEROS,
};
/* Also calls might_sleep() */
enum ptr_format ptr_format_for_file(struct file *);
/* regular source file */
/* Perform kernel configuration and capabilities lookup */
enum ptr_format format = ptr_format_for_file(file);
/* potentially stash format in file-private data for caching */
/* Actually format the pointer */
printk("%*pK\n, format, some_pointer);
Note: I removed all the non-file usages of %pK in the tree.
Except for the one in arch/arm/mm/physaddr.c.
> BTW: I have recently heard about EXPORT_SYMBOL_NS(). It would allow
> to export the symbol only for some specific modules.
>
> I am not sure how exactly it works. I wonder if there already
> exists a namespace for KUnit tests.
>
> It would be nice to use it, even for "no_hash_pointers"...
We also have EXPORT_SYMBOL_IF_KUNIT(). That would make the symbol visible
to all kunit tests, but only if kunit is enabled.
> > --- a/lib/tests/printf_kunit.c
> > +++ b/lib/tests/printf_kunit.c
> > @@ -316,7 +316,31 @@ symbol_ptr(struct kunit *kunittest)
> > static void
> > kernel_ptr(struct kunit *kunittest)
> > {
> > - /* We can't test this without access to kptr_restrict. */
> > +#ifdef MODULE
> > + kunit_skip(kunittest, "cannot access kptr_restrict from test module");
> > + return;
> > +#endif
> > +
> > + switch (kptr_restrict) {
> > + case 0:
> > + if (no_hash_pointers) {
> > + test(PTR_STR, "%pK", PTR);
> > + } else {
> > + char buf[PLAIN_BUF_SIZE];
> > +
> > + plain_hash_to_buffer(kunittest, PTR, buf, PLAIN_BUF_SIZE);
> > + /* %pK behaves the same as hashing */
> > + test(buf, "%pK", PTR);
> > + }
> > + break;
> > + case 1:
> > + test(PTR_STR, "%pK", PTR);
>
> Hmm, the behavior of %pK depends on capabilities of the caller.
> The above code would work when the test is built in.
> But we might need to check the capabilities when using test module.
> If I get it correctly, the module loaded requires CAP_SYS_MODULE
> while %pK behavior depends on CAP_SYSLOG...
The kunit test executes in a dedicated kthread.
That should have its own capabilities, independently from the user
loading the module. I think...
A comment is in order.
> > + break;
> > + case 2:
> > + default:
> > + test(ZEROS "00000000", "%pK", PTR);
> > + break;
> > + }
> > }
> >
> > static void
>
> Anyway, thanks for working on this.
>
> Best Regards,
> Petr
On Fri, Jan 16, 2026 at 06:06:59PM +0100, Petr Mladek wrote: > On Wed 2026-01-14 08:27:34, Thomas Weißschuh wrote: ... > > Fill out the tests for restricted kernel pointers, using the %pK format. > > This test can only be executed when built into the kernel, as modules > > do not have access to the kptr_restrict knob. > > I think that we could export "kptr_restrict" like we did > with no_hash_pointers. AFAIK, it has been exported just because > of the test module as well. > > > Please note that changes to the kptr_restrict sysctl from the kernel > > commandline are only applied *after* the boot-time KUnit tests run. > > This is another motivation to export the symbol. Otherwise, it is > really hard to test the non-default variants. > > BTW: I have recently heard about EXPORT_SYMBOL_NS(). It would allow > to export the symbol only for some specific modules. > > I am not sure how exactly it works. I wonder if there already > exists a namespace for KUnit tests. > > It would be nice to use it, even for "no_hash_pointers"... This is a variant for really strict use: EXPORT_SYNBOL_FOR_MODULES(). -- With Best Regards, Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.