diff options
| author | Will Deacon <will.deacon@arm.com> | 2012-10-18 10:17:00 -0400 |
|---|---|---|
| committer | Catalin Marinas <catalin.marinas@arm.com> | 2012-10-18 15:15:34 -0400 |
| commit | 8f34a1da35aed7b438a2de8ac27723a5472e8399 (patch) | |
| tree | 78bd55aae0bcfba26dbedeb93471e13635f90c67 | |
| parent | 7797d17c591ae62c6f43c6de4fdb8beeb50eb692 (diff) | |
arm64: ptrace: use HW_BREAKPOINT_EMPTY type for disabled breakpoints
If a debugger tries to zero a hardware debug control register, the
kernel will try to infer both the type and length of the breakpoint
in order to sanity-check against the requested regset type. This will
fail because the encoding will appear as a zero-length breakpoint.
This patch changes the control register setting so that disabled
breakpoints are treated as HW_BREAKPOINT_EMPTY and no further
sanity-checking is required.
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
| -rw-r--r-- | arch/arm64/kernel/ptrace.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index c62d39d5c99f..6e1e77f1831c 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
| @@ -234,28 +234,33 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, | |||
| 234 | struct arch_hw_breakpoint_ctrl ctrl, | 234 | struct arch_hw_breakpoint_ctrl ctrl, |
| 235 | struct perf_event_attr *attr) | 235 | struct perf_event_attr *attr) |
| 236 | { | 236 | { |
| 237 | int err, len, type; | 237 | int err, len, type, disabled = !ctrl.enabled; |
| 238 | 238 | ||
| 239 | err = arch_bp_generic_fields(ctrl, &len, &type); | 239 | if (disabled) { |
| 240 | if (err) | 240 | len = 0; |
| 241 | return err; | 241 | type = HW_BREAKPOINT_EMPTY; |
| 242 | 242 | } else { | |
| 243 | switch (note_type) { | 243 | err = arch_bp_generic_fields(ctrl, &len, &type); |
| 244 | case NT_ARM_HW_BREAK: | 244 | if (err) |
| 245 | if ((type & HW_BREAKPOINT_X) != type) | 245 | return err; |
| 246 | return -EINVAL; | 246 | |
| 247 | break; | 247 | switch (note_type) { |
| 248 | case NT_ARM_HW_WATCH: | 248 | case NT_ARM_HW_BREAK: |
| 249 | if ((type & HW_BREAKPOINT_RW) != type) | 249 | if ((type & HW_BREAKPOINT_X) != type) |
| 250 | return -EINVAL; | ||
| 251 | break; | ||
| 252 | case NT_ARM_HW_WATCH: | ||
| 253 | if ((type & HW_BREAKPOINT_RW) != type) | ||
| 254 | return -EINVAL; | ||
| 255 | break; | ||
| 256 | default: | ||
| 250 | return -EINVAL; | 257 | return -EINVAL; |
| 251 | break; | 258 | } |
| 252 | default: | ||
| 253 | return -EINVAL; | ||
| 254 | } | 259 | } |
| 255 | 260 | ||
| 256 | attr->bp_len = len; | 261 | attr->bp_len = len; |
| 257 | attr->bp_type = type; | 262 | attr->bp_type = type; |
| 258 | attr->disabled = !ctrl.enabled; | 263 | attr->disabled = disabled; |
| 259 | 264 | ||
| 260 | return 0; | 265 | return 0; |
| 261 | } | 266 | } |
