Skip to content

Commit 4b05b99

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: uaccess: Return the number of bytes effectively not copied
It was reported that the riscv kernel hangs while executing the test in [1]. Indeed, the test hangs when trying to write a buffer to a file. The problem is that the riscv implementation of raw_copy_from_user() does not return the correct number of bytes not written when an exception happens and is fixed up, instead it always returns the initial size to copy, even if some bytes were actually copied. generic_perform_write() pre-faults the user pages and bails out if nothing can be written, otherwise it will access the userspace buffer: here the riscv implementation keeps returning it was not able to copy any byte though the pre-faulting indicates otherwise. So generic_perform_write() keeps retrying to access the user memory and ends up in an infinite loop. Note that before the commit mentioned in [1] that introduced this regression, it worked because generic_perform_write() would bail out if only one byte could not be written. So fix this by returning the number of bytes effectively not written in __asm_copy_[to|from]_user() and __clear_user(), as it is expected. Link: https://lore.kernel.org/linux-riscv/20230309151841.bomov6hq3ybyp42a@debian/ [1] Fixes: ebcbd75 ("riscv: Fix the bug in memory access fixup code") Reported-by: Bo YU <tsu.yubo@gmail.com> Closes: https://lore.kernel.org/linux-riscv/20230309151841.bomov6hq3ybyp42a@debian/#t Reported-by: Aurelien Jarno <aurelien@aurel32.net> Closes: https://lore.kernel.org/linux-riscv/ZNOnCakhwIeue3yr@aurel32.net/ Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> Reviewed-by: Björn Töpel <bjorn@rivosinc.com> Tested-by: Aurelien Jarno <aurelien@aurel32.net> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> Link: https://lore.kernel.org/r/20230811150604.1621784-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent ebc9cb0 commit 4b05b99

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

arch/riscv/lib/uaccess.S

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ ENTRY(__asm_copy_from_user)
1717
li t6, SR_SUM
1818
csrs CSR_STATUS, t6
1919

20-
/* Save for return value */
21-
mv t5, a2
20+
/*
21+
* Save the terminal address which will be used to compute the number
22+
* of bytes copied in case of a fixup exception.
23+
*/
24+
add t5, a0, a2
2225

2326
/*
2427
* Register allocation for code below:
@@ -176,7 +179,7 @@ ENTRY(__asm_copy_from_user)
176179
10:
177180
/* Disable access to user memory */
178181
csrc CSR_STATUS, t6
179-
mv a0, t5
182+
sub a0, t5, a0
180183
ret
181184
ENDPROC(__asm_copy_to_user)
182185
ENDPROC(__asm_copy_from_user)
@@ -228,7 +231,7 @@ ENTRY(__clear_user)
228231
11:
229232
/* Disable access to user memory */
230233
csrc CSR_STATUS, t6
231-
mv a0, a1
234+
sub a0, a3, a0
232235
ret
233236
ENDPROC(__clear_user)
234237
EXPORT_SYMBOL(__clear_user)

0 commit comments

Comments
 (0)