diff options
| author | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-09-04 10:43:19 +0200 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-04 07:58:36 -0700 |
| commit | 6668ed271eaefaa63e686bdfbedaeb7b8e492722 (patch) | |
| tree | 58e8288fead484f6755ad0815fc74c3742663761 /arch/m68k/mm/hwtest.c | |
| download | linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.tar.gz linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.zip | |
selftests/bpf: Reject graph kptr use after RCU unlockgrafted
Add a sleepable verifier test that loads a graph-node local kptr in an
explicit RCU read-side critical section, then passes its node to
bpf_rbtree_remove() after the section ends.
Before the verifier fix, the stale NON_OWN_REF flag makes the node look like
a live borrowed reference and the program is accepted. After the fix, the
pointer is demoted without NON_OWN_REF and the graph kfunc argument is
rejected.
Also exercise a graph kptr loaded while a spin lock provides implicit RCU
protection. The pointer must be invalidated when the lock is released, which
guards the required ordering between non-owning-reference invalidation and
RCU demotion.
Update the existing fault-protected load test state description. The
post-unlock pointer no longer carries NON_OWN_REF, but remains readable
because the load is rewritten to use BPF_PROBE_MEM.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904084325.52250-7-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'arch/m68k/mm/hwtest.c')
| -rw-r--r-- | arch/m68k/mm/hwtest.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c new file mode 100644 index 000000000..8ee7a3368 --- /dev/null +++ b/arch/m68k/mm/hwtest.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Tests for presence or absence of hardware registers. + * This code was originally in atari/config.c, but I noticed + * that it was also in drivers/nubus/nubus.c and I wanted to + * use it in hp300/config.c, so it seemed sensible to pull it + * out into its own file. + * + * The test is for use when trying to read a hardware register + * that isn't present would cause a bus error. We set up a + * temporary handler so that this doesn't kill the kernel. + * + * There is a test-by-reading and a test-by-writing; I present + * them here complete with the comments from the original atari + * config.c... + * -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998 + */ + +/* This function tests for the presence of an address, specially a + * hardware register address. It is called very early in the kernel + * initialization process, when the VBR register isn't set up yet. On + * an Atari, it still points to address 0, which is unmapped. So a bus + * error would cause another bus error while fetching the exception + * vector, and the CPU would do nothing at all. So we needed to set up + * a temporary VBR and a vector table for the duration of the test. + */ + +#include <linux/module.h> + +#include <asm/hwtest.h> + +int hwreg_present(volatile void *regp) +{ + int ret = 0; + unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + + local_irq_save(flags); + __asm__ __volatile__ ( + "movec %/vbr,%2\n\t" + "movel #Lberr1,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "tstb %3@\n\t" + "nop\n\t" + "moveq #1,%0\n" + "Lberr1:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors) + ); + local_irq_restore(flags); + + return ret; +} +EXPORT_SYMBOL(hwreg_present); + +/* Basically the same, but writes a value into a word register, protected + * by a bus error handler. Returns 1 if successful, 0 otherwise. + */ + +int hwreg_write(volatile void *regp, unsigned short val) +{ + int ret; + unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + + local_irq_save(flags); + __asm__ __volatile__ ( + "movec %/vbr,%2\n\t" + "movel #Lberr2,%4@(8)\n\t" + "movec %4,%/vbr\n\t" + "movel %/sp,%1\n\t" + "moveq #0,%0\n\t" + "movew %5,%3@\n\t" + "nop\n\t" + /* + * If this nop isn't present, 'ret' may already be loaded + * with 1 at the time the bus error happens! + */ + "moveq #1,%0\n" + "Lberr2:\n\t" + "movel %1,%/sp\n\t" + "movec %2,%/vbr" + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors), "g" (val) + ); + local_irq_restore(flags); + + return ret; +} +EXPORT_SYMBOL(hwreg_write); + |
