mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] riscv: misaligned: disable pagefault before accessing user memory
@ 2025-01-03 16:02 Clément Léger
  2025-01-06 14:37 ` Alexandre Ghiti
  0 siblings, 1 reply; 6+ messages in thread
From: Clément Léger @ 2025-01-03 16:02 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, open list:RISC-V ARCHITECTURE, open list
  Cc: Clément Léger, Samuel Holland

Calling copy_{from/to}_user() in interrupt context might actually sleep
and display a BUG message:

[   10.377019] BUG: sleeping function called from invalid context at include/linux/uaccess.h:162
[   10.379868] in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 88, name: ssh-keygen
[   10.380009] preempt_count: 0, expected: 0
[   10.380324] CPU: 0 UID: 0 PID: 88 Comm: ssh-keygen Not tainted 6.13.0-rc5-00013-g3435cd5f1331-dirty #19
[   10.380639] Hardware name: riscv-virtio,qemu (DT)
[   10.380798] Call Trace:
[   10.381108] [<ffffffff80013d30>] dump_backtrace+0x1c/0x24
[   10.381690] [<ffffffff800022d8>] show_stack+0x28/0x34
[   10.381812] [<ffffffff8000ee1c>] dump_stack_lvl+0x4a/0x68
[   10.381958] [<ffffffff8000ee4e>] dump_stack+0x14/0x1c
[   10.382047] [<ffffffff80065e0a>] __might_resched+0xfa/0x104
[   10.382172] [<ffffffff80065e56>] __might_sleep+0x42/0x66
[   10.382267] [<ffffffff801b0c5e>] __might_fault+0x1c/0x24
[   10.382363] [<ffffffff804415e4>] _copy_from_user+0x28/0xc2
[   10.382459] [<ffffffff800152ca>] handle_misaligned_load+0x1ca/0x2fc
[   10.382565] [<ffffffff80a033a0>] do_trap_load_misaligned+0x24/0xee
[   10.382714] [<ffffffff80a0dc66>] handle_exception+0x146/0x152

In order to safely handle user memory access from this context, disable
page fault while copying user memory. Although this might lead to copy
failure in some cases (offlined page), this is the best we can try to be
safe.

Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to kernel memory")
Signed-off-by: Clément Léger <cleger@rivosinc.com>

---
 arch/riscv/kernel/traps_misaligned.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 7cc108aed74e..75a08ed20070 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -355,7 +355,7 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
 {
 	union reg_data val;
 	unsigned long epc = regs->epc;
-	unsigned long insn;
+	unsigned long insn, copy_len;
 	unsigned long addr = regs->badaddr;
 	int fp = 0, shift = 0, len = 0;
 
@@ -441,7 +441,16 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
 
 	val.data_u64 = 0;
 	if (user_mode(regs)) {
-		if (copy_from_user(&val, (u8 __user *)addr, len))
+		/*
+		 * We can not sleep in exception context. Disable pagefault to
+		 * avoid a potential sleep while accessing user memory. Side
+		 * effect is that if it would have sleep, then the copy will
+		 * fail.
+		 */
+		pagefault_disable();
+		copy_len = copy_from_user(&val, (u8 __user *)addr, len);
+		pagefault_enable();
+		if (copy_len)
 			return -1;
 	} else {
 		memcpy(&val, (u8 *)addr, len);
@@ -463,7 +472,7 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
 {
 	union reg_data val;
 	unsigned long epc = regs->epc;
-	unsigned long insn;
+	unsigned long insn, copy_len;
 	unsigned long addr = regs->badaddr;
 	int len = 0, fp = 0;
 
@@ -539,7 +548,16 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
 		return -EOPNOTSUPP;
 
 	if (user_mode(regs)) {
-		if (copy_to_user((u8 __user *)addr, &val, len))
+		/*
+		 * We can not sleep in exception context. Disable pagefault to
+		 * avoid a potential sleep while accessing user memory. Side
+		 * effect is that if it would have sleep, then the copy will
+		 * fail.
+		 */
+		pagefault_disable();
+		copy_len = copy_to_user((u8 __user *)addr, &val, len);
+		pagefault_enable();
+		if (copy_len)
 			return -1;
 	} else {
 		memcpy((u8 *)addr, &val, len);
-- 
2.45.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] riscv: misaligned: disable pagefault before accessing user memory
  2025-01-03 16:02 [PATCH] riscv: misaligned: disable pagefault before accessing user memory Clément Léger
@ 2025-01-06 14:37 ` Alexandre Ghiti
  2025-01-06 14:47   ` Clément Léger
  2025-01-06 14:51   ` Clément Léger
  0 siblings, 2 replies; 6+ messages in thread
From: Alexandre Ghiti @ 2025-01-06 14:37 UTC (permalink / raw)
  To: Clément Léger, Paul Walmsley, Palmer Dabbelt,
	open list:RISC-V ARCHITECTURE, open list
  Cc: Samuel Holland

Hi Clément,

On 03/01/2025 17:02, Clément Léger wrote:
> Calling copy_{from/to}_user() in interrupt context might actually sleep
> and display a BUG message:
>
> [   10.377019] BUG: sleeping function called from invalid context at include/linux/uaccess.h:162
> [   10.379868] in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 88, name: ssh-keygen
> [   10.380009] preempt_count: 0, expected: 0
> [   10.380324] CPU: 0 UID: 0 PID: 88 Comm: ssh-keygen Not tainted 6.13.0-rc5-00013-g3435cd5f1331-dirty #19
> [   10.380639] Hardware name: riscv-virtio,qemu (DT)
> [   10.380798] Call Trace:
> [   10.381108] [<ffffffff80013d30>] dump_backtrace+0x1c/0x24
> [   10.381690] [<ffffffff800022d8>] show_stack+0x28/0x34
> [   10.381812] [<ffffffff8000ee1c>] dump_stack_lvl+0x4a/0x68
> [   10.381958] [<ffffffff8000ee4e>] dump_stack+0x14/0x1c
> [   10.382047] [<ffffffff80065e0a>] __might_resched+0xfa/0x104
> [   10.382172] [<ffffffff80065e56>] __might_sleep+0x42/0x66
> [   10.382267] [<ffffffff801b0c5e>] __might_fault+0x1c/0x24
> [   10.382363] [<ffffffff804415e4>] _copy_from_user+0x28/0xc2
> [   10.382459] [<ffffffff800152ca>] handle_misaligned_load+0x1ca/0x2fc
> [   10.382565] [<ffffffff80a033a0>] do_trap_load_misaligned+0x24/0xee
> [   10.382714] [<ffffffff80a0dc66>] handle_exception+0x146/0x152
>
> In order to safely handle user memory access from this context, disable
> page fault while copying user memory. Although this might lead to copy
> failure in some cases (offlined page), this is the best we can try to be
> safe.
>
> Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to kernel memory")
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>
> ---
>   arch/riscv/kernel/traps_misaligned.c | 26 ++++++++++++++++++++++----
>   1 file changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
> index 7cc108aed74e..75a08ed20070 100644
> --- a/arch/riscv/kernel/traps_misaligned.c
> +++ b/arch/riscv/kernel/traps_misaligned.c
> @@ -355,7 +355,7 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
>   {
>   	union reg_data val;
>   	unsigned long epc = regs->epc;
> -	unsigned long insn;
> +	unsigned long insn, copy_len;
>   	unsigned long addr = regs->badaddr;
>   	int fp = 0, shift = 0, len = 0;
>   
> @@ -441,7 +441,16 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
>   
>   	val.data_u64 = 0;
>   	if (user_mode(regs)) {
> -		if (copy_from_user(&val, (u8 __user *)addr, len))
> +		/*
> +		 * We can not sleep in exception context. Disable pagefault to
> +		 * avoid a potential sleep while accessing user memory. Side
> +		 * effect is that if it would have sleep, then the copy will
> +		 * fail.
> +		 */
> +		pagefault_disable();
> +		copy_len = copy_from_user(&val, (u8 __user *)addr, len);
> +		pagefault_enable();
> +		if (copy_len)
>   			return -1;
>   	} else {
>   		memcpy(&val, (u8 *)addr, len);
> @@ -463,7 +472,7 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
>   {
>   	union reg_data val;
>   	unsigned long epc = regs->epc;
> -	unsigned long insn;
> +	unsigned long insn, copy_len;
>   	unsigned long addr = regs->badaddr;
>   	int len = 0, fp = 0;
>   
> @@ -539,7 +548,16 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
>   		return -EOPNOTSUPP;
>   
>   	if (user_mode(regs)) {
> -		if (copy_to_user((u8 __user *)addr, &val, len))
> +		/*
> +		 * We can not sleep in exception context. Disable pagefault to
> +		 * avoid a potential sleep while accessing user memory. Side
> +		 * effect is that if it would have sleep, then the copy will
> +		 * fail.
> +		 */
> +		pagefault_disable();
> +		copy_len = copy_to_user((u8 __user *)addr, &val, len);
> +		pagefault_enable();
> +		if (copy_len)
>   			return -1;
>   	} else {
>   		memcpy((u8 *)addr, &val, len);


I'm wondering why the irqs are disabled here? What prevents us from 
enabling them? IIUC, if for some reason the user page is not in memory, 
we will fail the misaligned access and kill the process, so such 
failures could be completely random right?

But if we go for this solution, I think the same needs to be done in 
__read_insn().

Let me know if I misunderstood something.

Thanks,

Alex


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] riscv: misaligned: disable pagefault before accessing user memory
  2025-01-06 14:37 ` Alexandre Ghiti
@ 2025-01-06 14:47   ` Clément Léger
  2025-01-07  2:33     ` Maciej W. Rozycki
  2025-01-06 14:51   ` Clément Léger
  1 sibling, 1 reply; 6+ messages in thread
From: Clément Léger @ 2025-01-06 14:47 UTC (permalink / raw)
  To: Alexandre Ghiti, Paul Walmsley, Palmer Dabbelt,
	open list:RISC-V ARCHITECTURE, open list
  Cc: Samuel Holland



On 06/01/2025 15:37, Alexandre Ghiti wrote:
> Hi Clément,
> 
> On 03/01/2025 17:02, Clément Léger wrote:
>> Calling copy_{from/to}_user() in interrupt context might actually sleep
>> and display a BUG message:
>>
>> [   10.377019] BUG: sleeping function called from invalid context at
>> include/linux/uaccess.h:162
>> [   10.379868] in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid:
>> 88, name: ssh-keygen
>> [   10.380009] preempt_count: 0, expected: 0
>> [   10.380324] CPU: 0 UID: 0 PID: 88 Comm: ssh-keygen Not tainted
>> 6.13.0-rc5-00013-g3435cd5f1331-dirty #19
>> [   10.380639] Hardware name: riscv-virtio,qemu (DT)
>> [   10.380798] Call Trace:
>> [   10.381108] [<ffffffff80013d30>] dump_backtrace+0x1c/0x24
>> [   10.381690] [<ffffffff800022d8>] show_stack+0x28/0x34
>> [   10.381812] [<ffffffff8000ee1c>] dump_stack_lvl+0x4a/0x68
>> [   10.381958] [<ffffffff8000ee4e>] dump_stack+0x14/0x1c
>> [   10.382047] [<ffffffff80065e0a>] __might_resched+0xfa/0x104
>> [   10.382172] [<ffffffff80065e56>] __might_sleep+0x42/0x66
>> [   10.382267] [<ffffffff801b0c5e>] __might_fault+0x1c/0x24
>> [   10.382363] [<ffffffff804415e4>] _copy_from_user+0x28/0xc2
>> [   10.382459] [<ffffffff800152ca>] handle_misaligned_load+0x1ca/0x2fc
>> [   10.382565] [<ffffffff80a033a0>] do_trap_load_misaligned+0x24/0xee
>> [   10.382714] [<ffffffff80a0dc66>] handle_exception+0x146/0x152
>>
>> In order to safely handle user memory access from this context, disable
>> page fault while copying user memory. Although this might lead to copy
>> failure in some cases (offlined page), this is the best we can try to be
>> safe.
>>
>> Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to
>> kernel memory")
>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>>
>> ---
>>   arch/riscv/kernel/traps_misaligned.c | 26 ++++++++++++++++++++++----
>>   1 file changed, 22 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/
>> traps_misaligned.c
>> index 7cc108aed74e..75a08ed20070 100644
>> --- a/arch/riscv/kernel/traps_misaligned.c
>> +++ b/arch/riscv/kernel/traps_misaligned.c
>> @@ -355,7 +355,7 @@ static int handle_scalar_misaligned_load(struct
>> pt_regs *regs)
>>   {
>>       union reg_data val;
>>       unsigned long epc = regs->epc;
>> -    unsigned long insn;
>> +    unsigned long insn, copy_len;
>>       unsigned long addr = regs->badaddr;
>>       int fp = 0, shift = 0, len = 0;
>>   @@ -441,7 +441,16 @@ static int handle_scalar_misaligned_load(struct
>> pt_regs *regs)
>>         val.data_u64 = 0;
>>       if (user_mode(regs)) {
>> -        if (copy_from_user(&val, (u8 __user *)addr, len))
>> +        /*
>> +         * We can not sleep in exception context. Disable pagefault to
>> +         * avoid a potential sleep while accessing user memory. Side
>> +         * effect is that if it would have sleep, then the copy will
>> +         * fail.
>> +         */
>> +        pagefault_disable();
>> +        copy_len = copy_from_user(&val, (u8 __user *)addr, len);
>> +        pagefault_enable();
>> +        if (copy_len)
>>               return -1;
>>       } else {
>>           memcpy(&val, (u8 *)addr, len);
>> @@ -463,7 +472,7 @@ static int handle_scalar_misaligned_store(struct
>> pt_regs *regs)
>>   {
>>       union reg_data val;
>>       unsigned long epc = regs->epc;
>> -    unsigned long insn;
>> +    unsigned long insn, copy_len;
>>       unsigned long addr = regs->badaddr;
>>       int len = 0, fp = 0;
>>   @@ -539,7 +548,16 @@ static int
>> handle_scalar_misaligned_store(struct pt_regs *regs)
>>           return -EOPNOTSUPP;
>>         if (user_mode(regs)) {
>> -        if (copy_to_user((u8 __user *)addr, &val, len))
>> +        /*
>> +         * We can not sleep in exception context. Disable pagefault to
>> +         * avoid a potential sleep while accessing user memory. Side
>> +         * effect is that if it would have sleep, then the copy will
>> +         * fail.
>> +         */
>> +        pagefault_disable();
>> +        copy_len = copy_to_user((u8 __user *)addr, &val, len);
>> +        pagefault_enable();
>> +        if (copy_len)
>>               return -1;
>>       } else {
>>           memcpy((u8 *)addr, &val, len);
> 
> 
> I'm wondering why the irqs are disabled here? What prevents us from
> enabling them? IIUC, if for some reason the user page is not in memory,
> we will fail the misaligned access and kill the process, so such
> failures could be completely random right?

Hi Alex,

This code is called from interrupt context as a result from an
exception. AFAIK, interrupts are disabled during the whole exception
handling and re-enabled when returning to user mode in
do_notify_resume(). So that's why it triggers this warning.

Clément

> 
> But if we go for this solution, I think the same needs to be done in
> __read_insn().
> 
> Let me know if I misunderstood something.
> 
> Thanks,
> 
> Alex
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] riscv: misaligned: disable pagefault before accessing user memory
  2025-01-06 14:37 ` Alexandre Ghiti
  2025-01-06 14:47   ` Clément Léger
@ 2025-01-06 14:51   ` Clément Léger
  1 sibling, 0 replies; 6+ messages in thread
From: Clément Léger @ 2025-01-06 14:51 UTC (permalink / raw)
  To: Alexandre Ghiti, Paul Walmsley, Palmer Dabbelt,
	open list:RISC-V ARCHITECTURE, open list
  Cc: Samuel Holland



On 06/01/2025 15:37, Alexandre Ghiti wrote:
> Hi Clément,
> 
> On 03/01/2025 17:02, Clément Léger wrote:
>> Calling copy_{from/to}_user() in interrupt context might actually sleep
>> and display a BUG message:
>>
>> [   10.377019] BUG: sleeping function called from invalid context at
>> include/linux/uaccess.h:162
>> [   10.379868] in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid:
>> 88, name: ssh-keygen
>> [   10.380009] preempt_count: 0, expected: 0
>> [   10.380324] CPU: 0 UID: 0 PID: 88 Comm: ssh-keygen Not tainted
>> 6.13.0-rc5-00013-g3435cd5f1331-dirty #19
>> [   10.380639] Hardware name: riscv-virtio,qemu (DT)
>> [   10.380798] Call Trace:
>> [   10.381108] [<ffffffff80013d30>] dump_backtrace+0x1c/0x24
>> [   10.381690] [<ffffffff800022d8>] show_stack+0x28/0x34
>> [   10.381812] [<ffffffff8000ee1c>] dump_stack_lvl+0x4a/0x68
>> [   10.381958] [<ffffffff8000ee4e>] dump_stack+0x14/0x1c
>> [   10.382047] [<ffffffff80065e0a>] __might_resched+0xfa/0x104
>> [   10.382172] [<ffffffff80065e56>] __might_sleep+0x42/0x66
>> [   10.382267] [<ffffffff801b0c5e>] __might_fault+0x1c/0x24
>> [   10.382363] [<ffffffff804415e4>] _copy_from_user+0x28/0xc2
>> [   10.382459] [<ffffffff800152ca>] handle_misaligned_load+0x1ca/0x2fc
>> [   10.382565] [<ffffffff80a033a0>] do_trap_load_misaligned+0x24/0xee
>> [   10.382714] [<ffffffff80a0dc66>] handle_exception+0x146/0x152
>>
>> In order to safely handle user memory access from this context, disable
>> page fault while copying user memory. Although this might lead to copy
>> failure in some cases (offlined page), this is the best we can try to be
>> safe.
>>
>> Fixes: b686ecdeacf6 ("riscv: misaligned: Restrict user access to
>> kernel memory")
>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>>
>> ---
>>   arch/riscv/kernel/traps_misaligned.c | 26 ++++++++++++++++++++++----
>>   1 file changed, 22 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/
>> traps_misaligned.c
>> index 7cc108aed74e..75a08ed20070 100644
>> --- a/arch/riscv/kernel/traps_misaligned.c
>> +++ b/arch/riscv/kernel/traps_misaligned.c
>> @@ -355,7 +355,7 @@ static int handle_scalar_misaligned_load(struct
>> pt_regs *regs)
>>   {
>>       union reg_data val;
>>       unsigned long epc = regs->epc;
>> -    unsigned long insn;
>> +    unsigned long insn, copy_len;
>>       unsigned long addr = regs->badaddr;
>>       int fp = 0, shift = 0, len = 0;
>>   @@ -441,7 +441,16 @@ static int handle_scalar_misaligned_load(struct
>> pt_regs *regs)
>>         val.data_u64 = 0;
>>       if (user_mode(regs)) {
>> -        if (copy_from_user(&val, (u8 __user *)addr, len))
>> +        /*
>> +         * We can not sleep in exception context. Disable pagefault to
>> +         * avoid a potential sleep while accessing user memory. Side
>> +         * effect is that if it would have sleep, then the copy will
>> +         * fail.
>> +         */
>> +        pagefault_disable();
>> +        copy_len = copy_from_user(&val, (u8 __user *)addr, len);
>> +        pagefault_enable();
>> +        if (copy_len)
>>               return -1;
>>       } else {
>>           memcpy(&val, (u8 *)addr, len);
>> @@ -463,7 +472,7 @@ static int handle_scalar_misaligned_store(struct
>> pt_regs *regs)
>>   {
>>       union reg_data val;
>>       unsigned long epc = regs->epc;
>> -    unsigned long insn;
>> +    unsigned long insn, copy_len;
>>       unsigned long addr = regs->badaddr;
>>       int len = 0, fp = 0;
>>   @@ -539,7 +548,16 @@ static int
>> handle_scalar_misaligned_store(struct pt_regs *regs)
>>           return -EOPNOTSUPP;
>>         if (user_mode(regs)) {
>> -        if (copy_to_user((u8 __user *)addr, &val, len))
>> +        /*
>> +         * We can not sleep in exception context. Disable pagefault to
>> +         * avoid a potential sleep while accessing user memory. Side
>> +         * effect is that if it would have sleep, then the copy will
>> +         * fail.
>> +         */
>> +        pagefault_disable();
>> +        copy_len = copy_to_user((u8 __user *)addr, &val, len);
>> +        pagefault_enable();
>> +        if (copy_len)
>>               return -1;
>>       } else {
>>           memcpy((u8 *)addr, &val, len);
> 
> 
> I'm wondering why the irqs are disabled here? What prevents us from
> enabling them? IIUC, if for some reason the user page is not in memory,
> we will fail the misaligned access and kill the process, so such
> failures could be completely random right?
> 
> But if we go for this solution, I think the same needs to be done in
> __read_insn().

Forgot to answer to that question:

Indeed, it should be modified the same way though It did not triggered
any warning since in uses the "raw" access so there is no check done
before accessing the memory (ie no call to might_sleep()). I'll send a V2.

Thanks,

Clément

> 
> Let me know if I misunderstood something.
> 
> Thanks,
> 
> Alex
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] riscv: misaligned: disable pagefault before accessing user memory
  2025-01-06 14:47   ` Clément Léger
@ 2025-01-07  2:33     ` Maciej W. Rozycki
  2025-01-07  8:32       ` Clément Léger
  0 siblings, 1 reply; 6+ messages in thread
From: Maciej W. Rozycki @ 2025-01-07  2:33 UTC (permalink / raw)
  To: Clément Léger
  Cc: Alexandre Ghiti, Paul Walmsley, Palmer Dabbelt,
	open list:RISC-V ARCHITECTURE, open list, Samuel Holland

On Mon, 6 Jan 2025, Clément Léger wrote:

> > I'm wondering why the irqs are disabled here? What prevents us from
> > enabling them? IIUC, if for some reason the user page is not in memory,
> > we will fail the misaligned access and kill the process, so such
> > failures could be completely random right?
> 
> Hi Alex,
> 
> This code is called from interrupt context as a result from an
> exception. AFAIK, interrupts are disabled during the whole exception
> handling and re-enabled when returning to user mode in
> do_notify_resume(). So that's why it triggers this warning.

 This feels outright wrong.  We have analogous emulation code in Alpha and 
MIPS ports and we stay away from quick sands by enabling interrupts in the 
relevant exception handlers as soon as it is safe to do so; in particular 
when emulating user-mode unaligned accesses.  What causes the RISC-V port 
to be different here?

 See e.g. the MIPS exception dispatcher in arch/mips/kernel/genex.S where 
BUILD_HANDLER invocations explicitly enable interrupts for most of the 
handlers (via `sti' -> `__build_clear_sti').  Then unaligned emulation is 
run with the interrupt enable setting preserved from the context the fault 
happened in (via `ade' -> `__build_clear_ade'), clearly because it can in 
principle trigger from kernel code run with interrupts disabled.  But such 
code is not supposed to access user memory in the first place and traps 
from the user mode will have had interrupts enabled.

 I think the RISC-V port has to do the same, i.e. run the handler with the 
supervisor interrupt enable bit set according to whether interrupts were 
enabled or not for the mode the fault has triggered in.

  Maciej

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] riscv: misaligned: disable pagefault before accessing user memory
  2025-01-07  2:33     ` Maciej W. Rozycki
@ 2025-01-07  8:32       ` Clément Léger
  0 siblings, 0 replies; 6+ messages in thread
From: Clément Léger @ 2025-01-07  8:32 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Alexandre Ghiti, Paul Walmsley, Palmer Dabbelt,
	open list:RISC-V ARCHITECTURE, open list, Samuel Holland



On 07/01/2025 03:33, Maciej W. Rozycki wrote:
> On Mon, 6 Jan 2025, Clément Léger wrote:
> 
>>> I'm wondering why the irqs are disabled here? What prevents us from
>>> enabling them? IIUC, if for some reason the user page is not in memory,
>>> we will fail the misaligned access and kill the process, so such
>>> failures could be completely random right?
>>
>> Hi Alex,
>>
>> This code is called from interrupt context as a result from an
>> exception. AFAIK, interrupts are disabled during the whole exception
>> handling and re-enabled when returning to user mode in
>> do_notify_resume(). So that's why it triggers this warning.
> 
>  This feels outright wrong.  We have analogous emulation code in Alpha and 
> MIPS ports and we stay away from quick sands by enabling interrupts in the 
> relevant exception handlers as soon as it is safe to do so; in particular 
> when emulating user-mode unaligned accesses.  What causes the RISC-V port 
> to be different here?

Hi Maciej,

I probably did not clarify that enough. The current path for misaligned
accesses does not re-enable irqs (whatever the mode we enter from). Some
other path does (page_fault) as it's indeed safe.

> 
>  See e.g. the MIPS exception dispatcher in arch/mips/kernel/genex.S where 
> BUILD_HANDLER invocations explicitly enable interrupts for most of the 
> handlers (via `sti' -> `__build_clear_sti').  Then unaligned emulation is 
> run with the interrupt enable setting preserved from the context the fault 
> happened in (via `ade' -> `__build_clear_ade'), clearly because it can in 
> principle trigger from kernel code run with interrupts disabled.  But such 
> code is not supposed to access user memory in the first place and traps 
> from the user mode will have had interrupts enabled.
> 
>  I think the RISC-V port has to do the same, i.e. run the handler with the 
> supervisor interrupt enable bit set according to whether interrupts were 
> enabled or not for the mode the fault has triggered in.

It seems like as you say, it would actually be safe to re-enable
interrupts in the misaligned load/store path as well as
do_trap()/do_trap_break() which might also benefit from this improvement.

After reviewing, the code, there is also a bunch of irqentry_nmi_enter()
that seems a bit weird, maybe they could be replaced with irqentry_enter().

Thanks for the review,

Clément

> 
>   Maciej


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-01-07  8:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-03 16:02 [PATCH] riscv: misaligned: disable pagefault before accessing user memory Clément Léger
2025-01-06 14:37 ` Alexandre Ghiti
2025-01-06 14:47   ` Clément Léger
2025-01-07  2:33     ` Maciej W. Rozycki
2025-01-07  8:32       ` Clément Léger
2025-01-06 14:51   ` Clément Léger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®