Commit 4b05b993 authored by Alexandre Ghiti's avatar Alexandre Ghiti Committed by Palmer Dabbelt

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: ebcbd75e ("riscv: Fix the bug in memory access fixup code")
Reported-by: default avatarBo YU <tsu.yubo@gmail.com>
Closes: https://lore.kernel.org/linux-riscv/20230309151841.bomov6hq3ybyp42a@debian/#tReported-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Closes: https://lore.kernel.org/linux-riscv/ZNOnCakhwIeue3yr@aurel32.net/Signed-off-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: default avatarBjörn Töpel <bjorn@rivosinc.com>
Tested-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Reviewed-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Link: https://lore.kernel.org/r/20230811150604.1621784-1-alexghiti@rivosinc.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent ebc9cb03
...@@ -17,8 +17,11 @@ ENTRY(__asm_copy_from_user) ...@@ -17,8 +17,11 @@ ENTRY(__asm_copy_from_user)
li t6, SR_SUM li t6, SR_SUM
csrs CSR_STATUS, t6 csrs CSR_STATUS, t6
/* Save for return value */ /*
mv t5, a2 * Save the terminal address which will be used to compute the number
* of bytes copied in case of a fixup exception.
*/
add t5, a0, a2
/* /*
* Register allocation for code below: * Register allocation for code below:
...@@ -176,7 +179,7 @@ ENTRY(__asm_copy_from_user) ...@@ -176,7 +179,7 @@ ENTRY(__asm_copy_from_user)
10: 10:
/* Disable access to user memory */ /* Disable access to user memory */
csrc CSR_STATUS, t6 csrc CSR_STATUS, t6
mv a0, t5 sub a0, t5, a0
ret ret
ENDPROC(__asm_copy_to_user) ENDPROC(__asm_copy_to_user)
ENDPROC(__asm_copy_from_user) ENDPROC(__asm_copy_from_user)
...@@ -228,7 +231,7 @@ ENTRY(__clear_user) ...@@ -228,7 +231,7 @@ ENTRY(__clear_user)
11: 11:
/* Disable access to user memory */ /* Disable access to user memory */
csrc CSR_STATUS, t6 csrc CSR_STATUS, t6
mv a0, a1 sub a0, a3, a0
ret ret
ENDPROC(__clear_user) ENDPROC(__clear_user)
EXPORT_SYMBOL(__clear_user) EXPORT_SYMBOL(__clear_user)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment