kprobes: Prohibit probing on BUG() and WARN() address
Masami Hiramatsu
maintainerPATCH v2 1/1 kprobes: Prohibit probing on BUG() and WARN() address
Since BUG() and WARN() may use a trap (e.g. UD2 on x86) to get the address where the BUG() has occurred, kprobes can not do single-step out-of-line that instruction. So prohibit probing on such address.
Without this fix, if someone put a kprobe on WARN(), the kernel will crash with invalid opcode error instead of outputing warning message, because kernel can not find correct bug address.
---
Changes in v2:
- Add find_bug() stub function for !CONFIG_GENERIC_BUG
- Cast the p->addr to unsigned long.
--- include/linux/bug.h | 5 +++++ kernel/kprobes.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-)
include/linux/bug.h +5 -0
@@ -47,6 +47,11 @@ void generic_bug_clear_once(void);#else /* !CONFIG_GENERIC_BUG */ +static inline void *find_bug (unsigned long bugaddr) +{ +return NULL ; +} +static inline enum bug_trap_type report_bug (unsigned long bug_addr,struct pt_regs *regs) {
kernel/kprobes.c +2 -1
@@ -1514,7 +1514,8 @@ static int check_kprobe_address_safe(struct kprobe *p,/* Ensure it is not in reserved area nor out of text */ if (!kernel_text_address ((unsigned long ) p->addr) ||within_kprobe_blacklist ((unsigned long ) p->addr) || -jump_label_text_reserved (p->addr, p->addr)) { +jump_label_text_reserved (p->addr, p->addr) || +find_bug ((unsigned long ) p->addr)) { ret = -EINVAL ; goto out; }
Quoted 11 lines · Masami Hiramatsu
Since
BUG()andWARN()may use a trap (e.g. UD2 on x86) to get the address where theBUG()has occurred, kprobes can not do single-step out-of-line that instruction. So prohibit probing on such address.Without this fix, if someone put a kprobe on
WARN(), the kernel will crash with invalid opcode error instead of outputing warning message, because kernel can not find correct bug address.Signed-off-by Masami Hiramatsu <[email protected]>
Quoted 8 lines
---
Changes in v2:
- Addfind_bug()stub function for !CONFIG_GENERIC_BUG
- Cast thep->addrto unsigned long.--- include/linux/bug.h | 5 +++++ kernel/kprobes.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-)
- Naveen
Quoted 11 lines · On Tue, 3 Sep 2019 20:08:21 +0900 Masami Hiramatsu <[email protected]> wrote:
Since
BUG()andWARN()may use a trap (e.g. UD2 on x86) to get the address where theBUG()has occurred, kprobes can not do single-step out-of-line that instruction. So prohibit probing on such address.Without this fix, if someone put a kprobe on
WARN(), the kernel will crash with invalid opcode error instead of outputing warning message, because kernel can not find correct bug address.Signed-off-by Masami Hiramatsu <[email protected]>
-- Steve
Quoted 39 lines
---
Changes in v2:
- Addfind_bug()stub function for !CONFIG_GENERIC_BUG
- Cast thep->addrto unsigned long.--- include/linux/bug.h | 5 +++++ kernel/kprobes.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-)include/linux/bug.h +5
-0@@ -47,6 +47,11 @@ void generic_bug_clear_once(void);#else /* !CONFIG_GENERIC_BUG */ +static inline void *find_bug (unsigned long bugaddr) +{ +return NULL ; +} +static inline enum bug_trap_type report_bug (unsigned long bug_addr,struct pt_regs *regs) {kernel/kprobes.c +2
-1@@ -1514,7 +1514,8 @@ static int check_kprobe_address_safe(struct kprobe *p,/* Ensure it is not in reserved area nor out of text */ if (!kernel_text_address ((unsigned long ) p->addr) ||within_kprobe_blacklist ((unsigned long ) p->addr) || -jump_label_text_reserved (p->addr, p->addr)) { +jump_label_text_reserved (p->addr, p->addr) || +find_bug ((unsigned long ) p->addr)) { ret = -EINVAL ; goto out; }