From: Oleg Nesterov <oleg@redhat.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>,
Frederic Weisbecker <fweisbec@gmail.com>,
Ingo Molnar <mingo@elte.hu>,
Jan Kratochvil <jan.kratochvil@redhat.com>,
Prasad <prasad@linux.vnet.ibm.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/6] ptrace/x86: dont delay "disable" till second pass in ptrace_write_dr7()
Date: Thu, 18 Apr 2013 20:44:14 +0200 [thread overview]
Message-ID: <20130418184414.GA4432@redhat.com> (raw)
In-Reply-To: <20130418184350.GA4407@redhat.com>
ptrace_write_dr7() skips ptrace_modify_breakpoint(disabled => true)
unless second_pass, this buys nothing but complicates the code and
means that we always do the main loop twice even if "disabled" was
never true.
The comment says:
Don't unregister the breakpoints right-away,
unless all register_user_hw_breakpoint()
requests have succeeded.
Firstly, we do not do register_user_hw_breakpoint(), it was removed
by 24f1e32c "hw-breakpoints: Rewrite the hw-breakpoints layer on top
of perf events".
We are going to restore register_user_hw_breakpoint() (see the next
patch) but this doesn't matter, after 44234adc "hw-breakpoints: Modify
breakpoints without unregistering them" perf_event_disable() can not
hurt, hw_breakpoint_del() does not free the slot.
Remove the "second_pass" check from the main loop and simplify the
code. Since we have to check "bp != NULL" anyway, the patch also
removes the same check in ptrace_modify_breakpoint() and moves the
comment into ptrace_write_dr7().
With this patch the second pass is only needed to restore the saved
old_dr7. This should never fail, so the patch adds WARN_ON() to catch
the potential problems as Frederic suggested.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
---
arch/x86/kernel/ptrace.c | 53 +++++++++++++++++----------------------------
1 files changed, 20 insertions(+), 33 deletions(-)
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 0649f16..98b0a2c 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -609,14 +609,6 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
int gen_len, gen_type;
struct perf_event_attr attr;
- /*
- * We should have at least an inactive breakpoint at this
- * slot. It means the user is writing dr7 without having
- * written the address register first
- */
- if (!bp)
- return -EINVAL;
-
err = arch_bp_generic_fields(len, type, &gen_len, &gen_type);
if (err)
return err;
@@ -634,52 +626,47 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
*/
static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
{
- struct thread_struct *thread = &(tsk->thread);
+ struct thread_struct *thread = &tsk->thread;
unsigned long old_dr7;
- int i, orig_ret = 0, rc = 0;
- int second_pass = 0;
+ bool second_pass = false;
+ int i, rc, ret = 0;
data &= ~DR_CONTROL_RESERVED;
old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
+
restore:
- /*
- * Loop through all the hardware breakpoints, making the
- * appropriate changes to each.
- */
+ rc = 0;
for (i = 0; i < HBP_NUM; i++) {
unsigned len, type;
bool disabled = !decode_dr7(data, i, &len, &type);
struct perf_event *bp = thread->ptrace_bps[i];
- if (disabled) {
+ if (!bp) {
+ if (disabled)
+ continue;
/*
- * Don't unregister the breakpoints right-away, unless
- * all register_user_hw_breakpoint() requests have
- * succeeded. This prevents any window of opportunity
- * for debug register grabbing by other users.
+ * We should have at least an inactive breakpoint at
+ * this slot. It means the user is writing dr7 without
+ * having written the address register first.
*/
- if (!bp || !second_pass)
- continue;
+ rc = -EINVAL;
+ break;
}
rc = ptrace_modify_breakpoint(bp, len, type, tsk, disabled);
if (rc)
break;
}
- /*
- * Make a second pass to free the remaining unused breakpoints
- * or to restore the original breakpoints if an error occurred.
- */
- if (!second_pass) {
- second_pass = 1;
- if (rc < 0) {
- orig_ret = rc;
- data = old_dr7;
- }
+
+ /* Restore if the first pass failed, second_pass shouldn't fail. */
+ if (rc && !WARN_ON(second_pass)) {
+ ret = rc;
+ data = old_dr7;
+ second_pass = true;
goto restore;
}
- return orig_ret < 0 ? orig_ret : rc;
+ return ret;
}
/*
--
1.5.5.1
next prev parent reply other threads:[~2013-04-18 18:47 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-18 18:43 [PATCH v2 0/6] ptrace/x86: hw_breakpoints fixes/cleanups Oleg Nesterov
2013-04-18 18:44 ` [PATCH 1/6] ptrace/x86: simplify the "disable" logic in ptrace_write_dr7() Oleg Nesterov
2013-04-18 18:44 ` Oleg Nesterov [this message]
2013-04-18 18:44 ` [PATCH 3/6] ptrace/x86: introduce ptrace_register_breakpoint() Oleg Nesterov
2013-04-18 19:01 ` Oleg Nesterov
2013-04-29 15:56 ` Frederic Weisbecker
2013-04-18 18:44 ` [PATCH 4/6] ptrace/x86: ptrace_write_dr7() should create bp if !disabled Oleg Nesterov
2013-04-29 15:59 ` Frederic Weisbecker
2013-04-18 18:44 ` [PATCH 5/6] ptrace/x86: cleanup ptrace_set_debugreg() Oleg Nesterov
2013-04-29 16:00 ` Frederic Weisbecker
2013-04-18 18:44 ` [PATCH 6/6] ptrace: PTRACE_DETACH should do flush_ptrace_hw_breakpoint(child) Oleg Nesterov
2013-04-29 16:09 ` Frederic Weisbecker
2013-04-29 16:40 ` Oleg Nesterov
2013-04-29 23:36 ` Frederic Weisbecker
2013-04-30 17:51 ` Oleg Nesterov
2013-04-30 18:53 ` [PATCH 0/2] (Was: ptrace: PTRACE_DETACH should do flush_ptrace_hw_breakpoint(child)) Oleg Nesterov
2013-04-30 18:53 ` [PATCH 1/2] ptrace/x86: flush_ptrace_hw_breakpoint() shoule clear the virtual debug registers Oleg Nesterov
2013-04-30 18:53 ` [PATCH 2/2] x86: kill TIF_DEBUG Oleg Nesterov
2013-04-29 23:37 ` [PATCH 6/6] ptrace: PTRACE_DETACH should do flush_ptrace_hw_breakpoint(child) Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130418184414.GA4432@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=fweisbec@gmail.com \
--cc=jan.kratochvil@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=prasad@linux.vnet.ibm.com \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.