aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2010-04-18 12:11:53 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2010-04-30 22:32:10 -0400
commitb2812d031dea86926e9c10f7714af33ac2f6b43d (patch)
treea48b18b49fa064e89b7b03e057e46e5a294a8053 /kernel/hw_breakpoint.c
parent87e9b2024659c614a876ce359a57e98a47b5ef37 (diff)
hw-breakpoints: Change/Enforce some breakpoints policies
The current policies of breakpoints in x86 and SH are the following: - task bound breakpoints can only break on userspace addresses - cpu wide breakpoints can only break on kernel addresses The former rule prevents ptrace breakpoints to be set to trigger on kernel addresses, which is good. But as a side effect, we can't breakpoint on kernel addresses for task bound breakpoints. The latter rule simply makes no sense, there is no reason why we can't set breakpoints on userspace while performing cpu bound profiles. We want the following new policies: - task bound breakpoint can set userspace address breakpoints, with no particular privilege required. - task bound breakpoints can set kernelspace address breakpoints but must be privileged to do that. - cpu bound breakpoints can do what they want as they are privileged already. To implement these new policies, this patch checks if we are dealing with a kernel address breakpoint, if so and if the exclude_kernel parameter is set, we tell the user that the breakpoint is invalid, which makes a good generic ptrace protection. If we don't have exclude_kernel, ensure the user has the right privileges as kernel breakpoints are quite sensitive (risk of trap recursion attacks and global performance impacts). [ Paul Mundt: keep addr space check for sh signal delivery and fix double function declaration] Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Cc: K. Prasad <prasad@linux.vnet.ibm.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Jason Wessel <jason.wessel@windriver.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'kernel/hw_breakpoint.c')
-rw-r--r--kernel/hw_breakpoint.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index 9ed9ae3a48b3..89e8a050c43a 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -308,6 +308,28 @@ int dbg_release_bp_slot(struct perf_event *bp)
308 return 0; 308 return 0;
309} 309}
310 310
311static int validate_hw_breakpoint(struct perf_event *bp)
312{
313 int ret;
314
315 ret = arch_validate_hwbkpt_settings(bp);
316 if (ret)
317 return ret;
318
319 if (arch_check_bp_in_kernelspace(bp)) {
320 if (bp->attr.exclude_kernel)
321 return -EINVAL;
322 /*
323 * Don't let unprivileged users set a breakpoint in the trap
324 * path to avoid trap recursion attacks.
325 */
326 if (!capable(CAP_SYS_ADMIN))
327 return -EPERM;
328 }
329
330 return 0;
331}
332
311int register_perf_hw_breakpoint(struct perf_event *bp) 333int register_perf_hw_breakpoint(struct perf_event *bp)
312{ 334{
313 int ret; 335 int ret;
@@ -316,7 +338,7 @@ int register_perf_hw_breakpoint(struct perf_event *bp)
316 if (ret) 338 if (ret)
317 return ret; 339 return ret;
318 340
319 ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); 341 ret = validate_hw_breakpoint(bp);
320 342
321 /* if arch_validate_hwbkpt_settings() fails then release bp slot */ 343 /* if arch_validate_hwbkpt_settings() fails then release bp slot */
322 if (ret) 344 if (ret)
@@ -363,7 +385,7 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
363 if (attr->disabled) 385 if (attr->disabled)
364 goto end; 386 goto end;
365 387
366 err = arch_validate_hwbkpt_settings(bp, bp->ctx->task); 388 err = validate_hw_breakpoint(bp);
367 if (!err) 389 if (!err)
368 perf_event_enable(bp); 390 perf_event_enable(bp);
369 391