raid6: riscv: Fix NULL pointer dereference caused by a missing clobber

When running the raid6 user-space test program on RISC-V QEMU, there's a
segmentation fault which seems caused by accessing a NULL pointer,
which is the pointer variable p/q in raid6_rvv*_gen/xor_syndrome_real(),
p/q should have been equal to dptr[x], but when I use GDB command to
see its value, which was 0x10 like below:

"
Program received signal SIGSEGV, Segmentation fault.
0x0000000000011062 in raid6_rvv2_xor_syndrome_real (disks=<optimized out>, start=0, stop=<optimized out>, bytes=4096, ptrs=<optimized out>) at rvv.c:386
(gdb) p p
$1 = (u8 *) 0x10 <error: Cannot access memory at address 0x10>
"

The issue was found to be related with:
1) Compile optimization
   There's no segmentation fault if compiling the raid6test program with
   the optimization flag -O0.
2) The RISC-V vector command vsetvli
   If not used t0 as the first parameter in vsetvli, there's no
   segmentation fault either.

This patch selects the 2nd solution to fix the issue.

[Palmer: The actual issue here is a missing clobber in the vsetvli code.
It's a little tricky: we've already probed for VLENB so we don't need to
look at the output register, we just need to have an X register in the
instruction as that's the form required to actually set VL.  Thus we
clobber a register, and without describing that we end up breaking
compilers.]

Fixes: 6093faaf95 ("raid6: Add RISC-V SIMD syndrome and recovery calculations")
Signed-off-by: Chunyan Zhang <zhangchunyan@iscas.ac.cn>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20250610101234.1100660-3-zhangchunyan@iscas.ac.cn
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
This commit is contained in:
Chunyan Zhang 2025-06-10 18:12:32 +08:00 committed by Palmer Dabbelt
parent 19272b37aa
commit bc75552b80
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889

View File

@ -26,9 +26,9 @@ static int rvv_has_vector(void)
static void raid6_rvv1_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
{
u8 **dptr = (u8 **)ptrs;
unsigned long d;
int z, z0;
u8 *p, *q;
unsigned long vl, d;
int z, z0;
z0 = disks - 3; /* Highest data disk */
p = dptr[z0 + 1]; /* XOR parity */
@ -36,8 +36,9 @@ static void raid6_rvv1_gen_syndrome_real(int disks, unsigned long bytes, void **
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */
@ -99,7 +100,7 @@ static void raid6_rvv1_xor_syndrome_real(int disks, int start, int stop,
{
u8 **dptr = (u8 **)ptrs;
u8 *p, *q;
unsigned long d;
unsigned long vl, d;
int z, z0;
z0 = stop; /* P/Q right side optimization */
@ -108,8 +109,9 @@ static void raid6_rvv1_xor_syndrome_real(int disks, int start, int stop,
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */
@ -195,9 +197,9 @@ static void raid6_rvv1_xor_syndrome_real(int disks, int start, int stop,
static void raid6_rvv2_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
{
u8 **dptr = (u8 **)ptrs;
unsigned long d;
int z, z0;
u8 *p, *q;
unsigned long vl, d;
int z, z0;
z0 = disks - 3; /* Highest data disk */
p = dptr[z0 + 1]; /* XOR parity */
@ -205,8 +207,9 @@ static void raid6_rvv2_gen_syndrome_real(int disks, unsigned long bytes, void **
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*
@ -287,7 +290,7 @@ static void raid6_rvv2_xor_syndrome_real(int disks, int start, int stop,
{
u8 **dptr = (u8 **)ptrs;
u8 *p, *q;
unsigned long d;
unsigned long vl, d;
int z, z0;
z0 = stop; /* P/Q right side optimization */
@ -296,8 +299,9 @@ static void raid6_rvv2_xor_syndrome_real(int disks, int start, int stop,
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*
@ -413,9 +417,9 @@ static void raid6_rvv2_xor_syndrome_real(int disks, int start, int stop,
static void raid6_rvv4_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
{
u8 **dptr = (u8 **)ptrs;
unsigned long d;
int z, z0;
u8 *p, *q;
unsigned long vl, d;
int z, z0;
z0 = disks - 3; /* Highest data disk */
p = dptr[z0 + 1]; /* XOR parity */
@ -423,8 +427,9 @@ static void raid6_rvv4_gen_syndrome_real(int disks, unsigned long bytes, void **
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*
@ -539,7 +544,7 @@ static void raid6_rvv4_xor_syndrome_real(int disks, int start, int stop,
{
u8 **dptr = (u8 **)ptrs;
u8 *p, *q;
unsigned long d;
unsigned long vl, d;
int z, z0;
z0 = stop; /* P/Q right side optimization */
@ -548,8 +553,9 @@ static void raid6_rvv4_xor_syndrome_real(int disks, int start, int stop,
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*
@ -721,9 +727,9 @@ static void raid6_rvv4_xor_syndrome_real(int disks, int start, int stop,
static void raid6_rvv8_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
{
u8 **dptr = (u8 **)ptrs;
unsigned long d;
int z, z0;
u8 *p, *q;
unsigned long vl, d;
int z, z0;
z0 = disks - 3; /* Highest data disk */
p = dptr[z0 + 1]; /* XOR parity */
@ -731,8 +737,9 @@ static void raid6_rvv8_gen_syndrome_real(int disks, unsigned long bytes, void **
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*
@ -915,7 +922,7 @@ static void raid6_rvv8_xor_syndrome_real(int disks, int start, int stop,
{
u8 **dptr = (u8 **)ptrs;
u8 *p, *q;
unsigned long d;
unsigned long vl, d;
int z, z0;
z0 = stop; /* P/Q right side optimization */
@ -924,8 +931,9 @@ static void raid6_rvv8_xor_syndrome_real(int disks, int start, int stop,
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli t0, x0, e8, m1, ta, ma\n"
"vsetvli %0, x0, e8, m1, ta, ma\n"
".option pop\n"
: "=&r" (vl)
);
/*