perf/hw_breakpoint: Fix breakpoint modify
Jiri Olsa
reviewerv3 cover perf/hw_breakpoint: Fix breakpoint modify
hi,
Milind reported that modify_user_hw_breakpoint wouldn't allow the breakpoint changing if the new attr had 'disabled' set to true.
I found a case where it actualy prevents ptrace user interface to change the breakpoint. It's described in patch 1 as perf test, patch 2 is the breakpoint code fix.
I ran strace tests, nothing (new) broken there..
v3 changes:
- added Oleg's ack for patch 3
- new patches 4,5 based on Oleg's suggestions replacing the v2 fallback approach by enabling the event directly after failed modification
v2 changes:
- added Oleg's ack for patch 2
- added new changes based on Oleg's questions
plus new test code
thanks,
jirka
---
Jiri Olsa (5):
perf tests: Add breakpoint modify tests
perf/hw_breakpoint: Modify breakpoint even if the new attr has disabled set perf/hw_breakpoint: Remove superfluous bp->attr.disabled = 0 perf/hw_breakpoint: Enable breakpoint in modify_user_hw_breakpoint perf/hw_breakpoint: Simplify breakpoint enable in perf_event_modify_breakpoint
kernel/events/core.c | 11 ++----- kernel/events/hw_breakpoint.c | 13 ++++---- tools/perf/arch/x86/include/arch-tests.h | 1 + tools/perf/arch/x86/tests/Build | 1 + tools/perf/arch/x86/tests/arch-tests.c | 6 ++++ tools/perf/arch/x86/tests/bp-modify.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 tools/perf/arch/x86/tests/bp-modify.c
Jiri Olsa
reviewerPATCH v3 1/5 perf tests: Add breakpoint modify tests
Adding to tests that aims on kernel breakpoint
modification bugs.
First test creates HW breakpoint, tries to change
it and checks it was properly changed. It aims
on kernel issue that prevents HW breakpoint to
be changed via ptrace interface.
The first test forks, the child sets itself as ptrace tracee and waits in signal for parent to trace it, then it calls bp_1 and quits.
The parent does following steps:
- creates a new breakpoint (id 0) for bp_2 function
- changes that breakpoint to bp_1 function
- waits for the breakpoint to hit and checks it has proper rip of bp_1 function
This test aims on an issue in kernel preventing to change disabled breakpoints
Second test mimics the first one except for few steps in the parent:
- creates a new breakpoint (id 0) for bp_1 function
- changes that breakpoint to bogus (-1) address
- waits for the breakpoint to hit and checks it has proper rip of bp_1 function
This test aims on an issue in kernel disabling enabled breakpoint after unsuccesful change.
--- tools/perf/arch/x86/include/arch-tests.h | 1 + tools/perf/arch/x86/tests/Build | 1 + tools/perf/arch/x86/tests/arch-tests.c | 6 + tools/perf/arch/x86/tests/bp-modify.c | 213 +++++++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 tools/perf/arch/x86/tests/bp-modify.c
tools/perf/arch/x86/include/arch-tests.h +1 -0
@@ -9,6 +9,7 @@ struct test;int test__rdpmc (struct test *test__maybe_unused ,int subtest);int test__perf_time_to_tsc (struct test *test__maybe_unused ,int subtest);int test__insn_x86 (struct test *test__maybe_unused ,int subtest); +int test__bp_modify (struct test *test,int subtest);#ifdef HAVE_DWARF_UNWIND_SUPPORT struct thread ;
tools/perf/arch/x86/tests/Build +1 -0
@@ -5,3 +5,4 @@ libperf-y += arch-tests.o libperf-y += rdpmc.o libperf-y += perf-time-to-tsc.o libperf-$(CONFIG_AUXTRACE) += insn-x86.o +libperf-$(CONFIG_X86_64) += bp-modify.o
tools/perf/arch/x86/tests/arch-tests.c +6 -0
@@ -23,6 +23,12 @@ struct test arch_tests[] = { .desc = "x86 instruction decoder - new instructions", .func = test__insn_x86, }, +#endif +#if defined(__x86_64__) + { + .desc = "x86 bp modify", + .func = test__bp_modify, + }, #endif { .func = NULL,
tools/perf/arch/x86/tests/bp-modify.c new file +213 -0
213 lines not on this page · raw message
Signature · 1 line
2.17.1
Jiri Olsa
reviewerPATCH v3 2/5 perf/hw_breakpoint: Modify breakpoint even if the new attr has disabled set
In reply to Jiri OlsaWe need to change the breakpoint even if the attr with new fields has disabled set to true.
Current code prevents following user code to change the breakpoint address:
ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[0]), addr_1) ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[0]), addr_2) ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[7]), dr7)
The first PTRACE_POKEUSER creates the breakpoint with attr.disabled set to true:
ptrace_set_breakpoint_addr(nr = 0)
struct perf_event *bp = t->ptrace_bps[nr]; ptrace_register_breakpoint(..., disabled = true)
ptrace_fill_bp_fields(..., disabled) register_user_hw_breakpoint
So the second PTRACE_POKEUSER will be omitted:
ptrace_set_breakpoint_addr(nr = 0)
struct perf_event *bp = t->ptrace_bps[nr];
struct perf_event_attr attr = bp->attr; modify_user_hw_breakpoint(bp, &attr)
if (!attr->disabled)
modify_user_hw_breakpoint_check--- kernel/events/hw_breakpoint.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/events/hw_breakpoint.c +6 -4
@@ -509,6 +509,8 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a*/ int modify_user_hw_breakpoint (struct perf_event *bp,struct perf_event_attr *attr) { +int err; +/* * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it * will not be possible to raise IPIs that invoke __perf_event_disable.
@@ -520,11 +522,11 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attelse perf_event_disable (bp); -if (!attr->disabled) { -int err =modify_user_hw_breakpoint_check (bp, attr, false); + err =modify_user_hw_breakpoint_check (bp, attr, false); +if (err) +return err; -if (err) -return err; +if (!attr->disabled) {perf_event_enable (bp); bp->attr.disabled =0 ; }
Signature · 1 line
2.17.1
Re: [PATCH 2/5] perf/hw_breakpoint: Modify breakpoint even if the new attr has disabled set
Quoted 26 lines · Jiri Olsa
We need to change the breakpoint even if the attr with new fields has disabled set to true.
Current code prevents following user code to change the breakpoint address:
ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[0]), addr_1)ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[0]), addr_2)ptrace(PTRACE_POKEUSER, child, offsetof(struct user, u_debugreg[7]), dr7)The first
PTRACE_POKEUSERcreates the breakpoint with attr.disabled set to true:ptrace_set_breakpoint_addr(nr = 0) struct perf_event *bp = t->ptrace_bps[nr];
ptrace_register_breakpoint(..., disabled = true)
ptrace_fill_bp_fields(..., disabled)register_user_hw_breakpointSo the second
PTRACE_POKEUSERwill be omitted:ptrace_set_breakpoint_addr(nr = 0) struct perf_event *bp = t->ptrace_bps[nr]; struct perf_event_attr attr = bp->attr;
Quoted 8 lines
modify_user_hw_breakpoint(bp, &attr) if (!attr->disabled) modify_user_hw_breakpoint_checkAcked-by Oleg Nesterov <[email protected]>Reported-by Milind Chabbi <[email protected]>Signed-off-by Jiri Olsa <[email protected]>
Right, now that we fixed the breakpoint modification arch code, it should be safe to do that.
Thanks!
Jiri Olsa
reviewerPATCH v3 3/5 perf/hw_breakpoint: Remove superfluous bp->attr.disabled = 0
In reply to Jiri OlsaOnce the breakpoint was succesfully modified, the attr->disabled value is in bp->attr.disabled. So there's no reason to set it again, removing that.
--- kernel/events/hw_breakpoint.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/hw_breakpoint.c +2 -3
@@ -526,10 +526,9 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attif (err)return err; -if (!attr->disabled) { +if (!attr->disabled)perf_event_enable (bp); - bp->attr.disabled =0 ; - } +return 0 ; }EXPORT_SYMBOL_GPL (modify_user_hw_breakpoint);
Signature · 1 line
2.17.1
Re: [PATCH 3/5] perf/hw_breakpoint: Remove superfluous bp->attr.disabled = 0
Quoted 7 lines · Jiri Olsa
Once the breakpoint was succesfully modified, the
attr->disabledvalue is inbp->attr.disabled. So there's no reason to set it again, removing that.Acked-by Oleg Nesterov <[email protected]>Signed-off-by Jiri Olsa <[email protected]>
Jiri Olsa
reviewerPATCH v3 4/5 perf/hw_breakpoint: Enable breakpoint in modify_user_hw_breakpoint
In reply to Jiri OlsaCurrently we enable the breakpoint back only if the breakpoint modification was successful. If it fails we can leave the breakpoint in disabled state with attr->disabled == 0.
We can safely enable the breakpoint back for both the fail and success paths by checking the bp->attr.disabled, which either holds the new 'requested' disabled state or the original breakpoint state.
--- kernel/events/hw_breakpoint.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
kernel/events/hw_breakpoint.c +2 -4
@@ -523,13 +523,11 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attperf_event_disable (bp); err =modify_user_hw_breakpoint_check (bp, attr, false); -if (err) -return err; -if (!attr->disabled) +if (!bp->attr.disabled)perf_event_enable (bp); -return 0 ; +return err; }EXPORT_SYMBOL_GPL (modify_user_hw_breakpoint);
Signature · 1 line
2.17.1
Re: [PATCH 4/5] perf/hw_breakpoint: Enable breakpoint in modify_user_hw_breakpoint
Quoted 7 lines · Jiri Olsa
kernel/events/hw_breakpoint.c +0
-0@@ -523,13 +523,11 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attperf_event_disable (bp); err =modify_user_hw_breakpoint_check (bp, attr, false);
kernel/events/hw_breakpoint.c int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att · line 531
Quoted 10 lines
kernel/events/hw_breakpoint.c +2
-4-if (err) -return err; -if (!attr->disabled) +if (!bp->attr.disabled)perf_event_enable (bp); -return 0 ; +return err; }
Re: [PATCH 4/5] perf/hw_breakpoint: Enable breakpoint in modify_user_hw_breakpoint
In reply to Jiri OlsaQuoted 4 lines · Jiri Olsa
Currently we enable the breakpoint back only if the breakpoint modification was successful. If it fails we can leave the breakpoint in disabled state with
attr->disabled== 0.
Quoted 8 lines
We can safely enable the breakpoint back for both the fail and success paths by checking the
bp->attr.disabled, which either holds the new 'requested' disabled state or the original breakpoint state.Suggested-by Oleg Nesterov <[email protected]>Signed-off-by Jiri Olsa <[email protected]>
Thanks a lot!
Jiri Olsa
reviewerPATCH v3 5/5 perf/hw_breakpoint: Simplify breakpoint enable in perf_event_modify_breakpoint
In reply to Jiri OlsaWe can safely enable the breakpoint back for both the fail and success paths by checking only the bp->attr.disabled, which either holds the new 'requested' disabled state or the original breakpoint state.
--- kernel/events/core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
kernel/events/core.c +3 -8
@@ -2867,16 +2867,11 @@ static int perf_event_modify_breakpoint(struct perf_event *bp,_perf_event_disable (bp); err =modify_user_hw_breakpoint_check (bp, attr, true); -if (err) { -if (!bp->attr.disabled) -_perf_event_enable (bp); -return err; - } - -if (!attr->disabled) +if (!bp->attr.disabled)_perf_event_enable (bp); -return 0 ; + +return err; } static int perf_event_modify_attr(struct perf_event *event,
Signature · 1 line
2.17.1
Re: [PATCH 5/5] perf/hw_breakpoint: Simplify breakpoint enable in perf_event_modify_breakpoint
Quoted 11 lines · Jiri Olsa
kernel/events/core.c +0
-3@@ -2867,16 +2867,11 @@ static int perf_event_modify_breakpoint(struct perf_event *bp,_perf_event_disable (bp); err =modify_user_hw_breakpoint_check (bp, attr, true); -if (err) { -if (!bp->attr.disabled) -_perf_event_enable (bp);
kernel/events/core.c static int perf_event_modify_breakpoint(struct perf_event *bp, · line 2875
Quoted 10 lines
kernel/events/core.c +3
-5-return err; - } - -if (!attr->disabled) +if (!bp->attr.disabled)_perf_event_enable (bp); -return 0 ; + +return err; }
Quoted 9 lines · Jiri Olsa
hi,
Milind reported thatmodify_user_hw_breakpointwouldn't allow the breakpoint changing if the new attr had 'disabled' set to true.I found a case where it actualy prevents ptrace user interface to change the breakpoint. It's described in patch 1 as perf test, patch 2 is the breakpoint code fix.
Quoted 7 lines
I ran strace tests, nothing (new) broken there..
v3 changes:
- added Oleg's ack for patch 3
- new patches 4,5 based on Oleg's suggestions replacing the v2 fallback approach by enabling the event directly after failed modification
Ingo, Arnaldo,
would you please pick up those, or should I pushed them through somebody else?
thanks,
jirka
Quoted 25 lines
v2 changes:
- added Oleg's ack for patch 2
- added new changes based on Oleg's questions
plus new test codethanks,
jirka---
Jiri Olsa (5):
perf tests: Add breakpoint modify tests
perf/hw_breakpoint: Modify breakpoint even if the new attr has disabled set perf/hw_breakpoint: Remove superfluousbp->attr.disabled= 0 perf/hw_breakpoint: Enable breakpoint inmodify_user_hw_breakpointperf/hw_breakpoint: Simplify breakpoint enable inperf_event_modify_breakpointkernel/events/core.c | 11 ++----- kernel/events/hw_breakpoint.c | 13 ++++---- tools/perf/arch/x86/include/arch-tests.h | 1 + tools/perf/arch/x86/tests/Build | 1 + tools/perf/arch/x86/tests/arch-tests.c | 6 ++++ tools/perf/arch/x86/tests/bp-modify.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 tools/perf/arch/x86/tests/bp-modify.c