* [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode
@ 2023-08-27 8:39 Björn Töpel
2023-08-27 10:46 ` kernel test robot
2023-08-27 10:55 ` Guo Ren
0 siblings, 2 replies; 3+ messages in thread
From: Björn Töpel @ 2023-08-27 8:39 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv, Guo Ren
Cc: Björn Töpel, linux-kernel, linux-trace-kernel, Nam Cao
From: Björn Töpel <bjorn@rivosinc.com>
RISC-V software breakpoint trap handlers are used for {k,u}probes.
When trapping from kernelmode, only the kernelmode handlers should be
considered. Vice versa, only usermode handlers for usermode
traps. This is not the case on RISC-V, which can trigger a bug if a
userspace process uses uprobes, and a WARN() is triggered from
kernelmode (which is implemented via {c.,}ebreak).
The kernel will trap on the kernelmode {c.,}ebreak, look for uprobes
handlers, realize incorrectly that uprobes need to be handled, and
exit the trap handler early. The trap returns to re-executing the
{c.,}ebreak, and enter an infinite trap-loop.
The issue was found running the BPF selftest [1].
Fix this issue by only considering the swbp/ss handlers for
kernel/usermode respectively. Also, move CONFIG ifdeffery from traps.c
to the asm/{k,u}probes.h headers.
Note that linux/uprobes.h only include asm/uprobes.h if CONFIG_UPROBES
is defined, which is why asm/uprobes.h needs to be unconditionally
included in traps.c
Link: https://lore.kernel.org/linux-riscv/87v8d19aun.fsf@all.your.base.are.belong.to.us/ # [1]
Fixes: 74784081aac8 ("riscv: Add uprobes supported")
Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
---
arch/riscv/include/asm/kprobes.h | 11 ++++++++++-
arch/riscv/include/asm/uprobes.h | 13 ++++++++++++-
arch/riscv/kernel/traps.c | 28 ++++++++++++++++++----------
3 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h
index e7882ccb0fd4..89fbd90f16a2 100644
--- a/arch/riscv/include/asm/kprobes.h
+++ b/arch/riscv/include/asm/kprobes.h
@@ -40,6 +40,15 @@ void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
bool kprobe_breakpoint_handler(struct pt_regs *regs);
bool kprobe_single_step_handler(struct pt_regs *regs);
-
+#else
+static inline bool kprobe_breakpoint_handler(struct pt_regs *)
+{
+ return false;
+}
+
+static inline bool kprobe_single_step_handler(struct pt_regs *)
+{
+ return false;
+}
#endif /* CONFIG_KPROBES */
#endif /* _ASM_RISCV_KPROBES_H */
diff --git a/arch/riscv/include/asm/uprobes.h b/arch/riscv/include/asm/uprobes.h
index f2183e00fdd2..3fc7deda9190 100644
--- a/arch/riscv/include/asm/uprobes.h
+++ b/arch/riscv/include/asm/uprobes.h
@@ -34,7 +34,18 @@ struct arch_uprobe {
bool simulate;
};
+#ifdef CONFIG_UPROBES
bool uprobe_breakpoint_handler(struct pt_regs *regs);
bool uprobe_single_step_handler(struct pt_regs *regs);
-
+#else
+static inline bool uprobe_breakpoint_handler(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline bool uprobe_single_step_handler(struct pt_regs *regs)
+{
+ return false;
+}
+#endif /* CONFIG_UPROBES */
#endif /* _ASM_RISCV_UPROBES_H */
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index f798c853bede..cd6f10c73a16 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -13,6 +13,8 @@
#include <linux/kdebug.h>
#include <linux/uaccess.h>
#include <linux/kprobes.h>
+#include <linux/uprobes.h>
+#include <asm/uprobes.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/irq.h>
@@ -246,22 +248,28 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
return GET_INSN_LENGTH(insn);
}
+static bool probe_single_step_handler(struct pt_regs *regs)
+{
+ bool user = user_mode(regs);
+
+ return user ? uprobe_single_step_handler(regs) : kprobe_single_step_handler(regs);
+}
+
+static bool probe_breakpoint_handler(struct pt_regs *regs)
+{
+ bool user = user_mode(regs);
+
+ return user ? uprobe_breakpoint_handler(regs) : kprobe_breakpoint_handler(regs);
+}
+
void handle_break(struct pt_regs *regs)
{
-#ifdef CONFIG_KPROBES
- if (kprobe_single_step_handler(regs))
+ if (probe_single_step_handler(regs))
return;
- if (kprobe_breakpoint_handler(regs))
- return;
-#endif
-#ifdef CONFIG_UPROBES
- if (uprobe_single_step_handler(regs))
+ if (probe_breakpoint_handler(regs))
return;
- if (uprobe_breakpoint_handler(regs))
- return;
-#endif
current->thread.bad_cause = regs->cause;
if (user_mode(regs))
base-commit: 7d2f353b2682dcfe5f9bc71e5b61d5b61770d98e
--
2.39.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode
2023-08-27 8:39 [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode Björn Töpel
@ 2023-08-27 10:46 ` kernel test robot
2023-08-27 10:55 ` Guo Ren
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2023-08-27 10:46 UTC (permalink / raw)
To: Björn Töpel, Paul Walmsley, Palmer Dabbelt, Albert Ou,
linux-riscv, Guo Ren
Cc: llvm, oe-kbuild-all, Björn Töpel, linux-kernel,
linux-trace-kernel, Nam Cao
Hi Björn,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 7d2f353b2682dcfe5f9bc71e5b61d5b61770d98e]
url: https://github.com/intel-lab-lkp/linux/commits/Bj-rn-T-pel/riscv-Only-consider-swbp-ss-handlers-for-correct-privileged-mode/20230827-164313
base: 7d2f353b2682dcfe5f9bc71e5b61d5b61770d98e
patch link: https://lore.kernel.org/r/20230827083949.204927-1-bjorn%40kernel.org
patch subject: [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode
config: riscv-randconfig-001-20230827 (https://download.01.org/0day-ci/archive/20230827/202308271841.HlnnHFL7-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce: (https://download.01.org/0day-ci/archive/20230827/202308271841.HlnnHFL7-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308271841.HlnnHFL7-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from kernel/sched/core.c:49:
In file included from include/linux/kprobes.h:32:
>> arch/riscv/include/asm/kprobes.h:44:62: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
44 | static inline bool kprobe_breakpoint_handler(struct pt_regs *)
| ^
arch/riscv/include/asm/kprobes.h:49:63: warning: omitting the parameter name in a function definition is a C2x extension [-Wc2x-extensions]
49 | static inline bool kprobe_single_step_handler(struct pt_regs *)
| ^
kernel/sched/core.c:3695:20: warning: unused function 'rq_has_pinned_tasks' [-Wunused-function]
3695 | static inline bool rq_has_pinned_tasks(struct rq *rq)
| ^
kernel/sched/core.c:5821:20: warning: unused function 'sched_tick_start' [-Wunused-function]
5821 | static inline void sched_tick_start(int cpu) { }
| ^
kernel/sched/core.c:5822:20: warning: unused function 'sched_tick_stop' [-Wunused-function]
5822 | static inline void sched_tick_stop(int cpu) { }
| ^
kernel/sched/core.c:6522:20: warning: unused function 'sched_core_cpu_starting' [-Wunused-function]
6522 | static inline void sched_core_cpu_starting(unsigned int cpu) {}
| ^
kernel/sched/core.c:6523:20: warning: unused function 'sched_core_cpu_deactivate' [-Wunused-function]
6523 | static inline void sched_core_cpu_deactivate(unsigned int cpu) {}
| ^
kernel/sched/core.c:6524:20: warning: unused function 'sched_core_cpu_dying' [-Wunused-function]
6524 | static inline void sched_core_cpu_dying(unsigned int cpu) {}
| ^
8 warnings generated.
vim +44 arch/riscv/include/asm/kprobes.h
38
39 void arch_remove_kprobe(struct kprobe *p);
40 int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
41 bool kprobe_breakpoint_handler(struct pt_regs *regs);
42 bool kprobe_single_step_handler(struct pt_regs *regs);
43 #else
> 44 static inline bool kprobe_breakpoint_handler(struct pt_regs *)
45 {
46 return false;
47 }
48
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode
2023-08-27 8:39 [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode Björn Töpel
2023-08-27 10:46 ` kernel test robot
@ 2023-08-27 10:55 ` Guo Ren
1 sibling, 0 replies; 3+ messages in thread
From: Guo Ren @ 2023-08-27 10:55 UTC (permalink / raw)
To: Björn Töpel
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Björn Töpel, linux-kernel, linux-trace-kernel, Nam Cao
On Sun, Aug 27, 2023 at 4:39 AM Björn Töpel <bjorn@kernel.org> wrote:
>
> From: Björn Töpel <bjorn@rivosinc.com>
>
> RISC-V software breakpoint trap handlers are used for {k,u}probes.
>
> When trapping from kernelmode, only the kernelmode handlers should be
> considered. Vice versa, only usermode handlers for usermode
> traps. This is not the case on RISC-V, which can trigger a bug if a
> userspace process uses uprobes, and a WARN() is triggered from
> kernelmode (which is implemented via {c.,}ebreak).
>
> The kernel will trap on the kernelmode {c.,}ebreak, look for uprobes
> handlers, realize incorrectly that uprobes need to be handled, and
> exit the trap handler early. The trap returns to re-executing the
> {c.,}ebreak, and enter an infinite trap-loop.
Thx for the fixup.
Reviewed-by: Guo Ren <guoren@kernel.org>
>
> The issue was found running the BPF selftest [1].
>
> Fix this issue by only considering the swbp/ss handlers for
> kernel/usermode respectively. Also, move CONFIG ifdeffery from traps.c
> to the asm/{k,u}probes.h headers.
>
> Note that linux/uprobes.h only include asm/uprobes.h if CONFIG_UPROBES
> is defined, which is why asm/uprobes.h needs to be unconditionally
> included in traps.c
>
> Link: https://lore.kernel.org/linux-riscv/87v8d19aun.fsf@all.your.base.are.belong.to.us/ # [1]
> Fixes: 74784081aac8 ("riscv: Add uprobes supported")
> Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
> ---
> arch/riscv/include/asm/kprobes.h | 11 ++++++++++-
> arch/riscv/include/asm/uprobes.h | 13 ++++++++++++-
> arch/riscv/kernel/traps.c | 28 ++++++++++++++++++----------
> 3 files changed, 40 insertions(+), 12 deletions(-)
>
> diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h
> index e7882ccb0fd4..89fbd90f16a2 100644
> --- a/arch/riscv/include/asm/kprobes.h
> +++ b/arch/riscv/include/asm/kprobes.h
> @@ -40,6 +40,15 @@ void arch_remove_kprobe(struct kprobe *p);
> int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
> bool kprobe_breakpoint_handler(struct pt_regs *regs);
> bool kprobe_single_step_handler(struct pt_regs *regs);
> -
> +#else
> +static inline bool kprobe_breakpoint_handler(struct pt_regs *)
> +{
> + return false;
> +}
> +
> +static inline bool kprobe_single_step_handler(struct pt_regs *)
> +{
> + return false;
> +}
> #endif /* CONFIG_KPROBES */
> #endif /* _ASM_RISCV_KPROBES_H */
> diff --git a/arch/riscv/include/asm/uprobes.h b/arch/riscv/include/asm/uprobes.h
> index f2183e00fdd2..3fc7deda9190 100644
> --- a/arch/riscv/include/asm/uprobes.h
> +++ b/arch/riscv/include/asm/uprobes.h
> @@ -34,7 +34,18 @@ struct arch_uprobe {
> bool simulate;
> };
>
> +#ifdef CONFIG_UPROBES
> bool uprobe_breakpoint_handler(struct pt_regs *regs);
> bool uprobe_single_step_handler(struct pt_regs *regs);
> -
> +#else
> +static inline bool uprobe_breakpoint_handler(struct pt_regs *regs)
> +{
> + return false;
> +}
> +
> +static inline bool uprobe_single_step_handler(struct pt_regs *regs)
> +{
> + return false;
> +}
> +#endif /* CONFIG_UPROBES */
> #endif /* _ASM_RISCV_UPROBES_H */
> diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
> index f798c853bede..cd6f10c73a16 100644
> --- a/arch/riscv/kernel/traps.c
> +++ b/arch/riscv/kernel/traps.c
> @@ -13,6 +13,8 @@
> #include <linux/kdebug.h>
> #include <linux/uaccess.h>
> #include <linux/kprobes.h>
> +#include <linux/uprobes.h>
> +#include <asm/uprobes.h>
> #include <linux/mm.h>
> #include <linux/module.h>
> #include <linux/irq.h>
> @@ -246,22 +248,28 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
> return GET_INSN_LENGTH(insn);
> }
>
> +static bool probe_single_step_handler(struct pt_regs *regs)
> +{
> + bool user = user_mode(regs);
> +
> + return user ? uprobe_single_step_handler(regs) : kprobe_single_step_handler(regs);
> +}
> +
> +static bool probe_breakpoint_handler(struct pt_regs *regs)
> +{
> + bool user = user_mode(regs);
> +
> + return user ? uprobe_breakpoint_handler(regs) : kprobe_breakpoint_handler(regs);
> +}
> +
> void handle_break(struct pt_regs *regs)
> {
> -#ifdef CONFIG_KPROBES
> - if (kprobe_single_step_handler(regs))
> + if (probe_single_step_handler(regs))
> return;
>
> - if (kprobe_breakpoint_handler(regs))
> - return;
> -#endif
> -#ifdef CONFIG_UPROBES
> - if (uprobe_single_step_handler(regs))
> + if (probe_breakpoint_handler(regs))
> return;
>
> - if (uprobe_breakpoint_handler(regs))
> - return;
> -#endif
> current->thread.bad_cause = regs->cause;
>
> if (user_mode(regs))
>
> base-commit: 7d2f353b2682dcfe5f9bc71e5b61d5b61770d98e
> --
> 2.39.2
>
--
Best Regards
Guo Ren
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-08-27 10:56 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-27 8:39 [PATCH] riscv: Only consider swbp/ss handlers for correct privileged mode Björn Töpel
2023-08-27 10:46 ` kernel test robot
2023-08-27 10:55 ` Guo Ren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).