Skip to content

Commit 37f5d61

Browse files
committed
Merge branch 'for-next/kprobes' into for-next/core
* for-next/kprobes: arm64: kprobes: Return DBG_HOOK_ERROR if kprobes can not handle a BRK arm64: kprobes: Let arch do_page_fault() fix up page fault in user handler arm64: Prohibit instrumentation on arch_stack_walk()
2 parents 926939c + 3b84efc commit 37f5d61

File tree

2 files changed

+41
-55
lines changed

2 files changed

+41
-55
lines changed

arch/arm64/kernel/probes/kprobes.c

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -294,19 +294,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
294294
}
295295

296296
break;
297-
case KPROBE_HIT_ACTIVE:
298-
case KPROBE_HIT_SSDONE:
299-
/*
300-
* In case the user-specified fault handler returned
301-
* zero, try to fix up.
302-
*/
303-
if (fixup_exception(regs))
304-
return 1;
305297
}
306298
return 0;
307299
}
308300

309-
static void __kprobes kprobe_handler(struct pt_regs *regs)
301+
static int __kprobes
302+
kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
310303
{
311304
struct kprobe *p, *cur_kprobe;
312305
struct kprobe_ctlblk *kcb;
@@ -316,39 +309,44 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
316309
cur_kprobe = kprobe_running();
317310

318311
p = get_kprobe((kprobe_opcode_t *) addr);
312+
if (WARN_ON_ONCE(!p)) {
313+
/*
314+
* Something went wrong. This BRK used an immediate reserved
315+
* for kprobes, but we couldn't find any corresponding probe.
316+
*/
317+
return DBG_HOOK_ERROR;
318+
}
319319

320-
if (p) {
321-
if (cur_kprobe) {
322-
if (reenter_kprobe(p, regs, kcb))
323-
return;
324-
} else {
325-
/* Probe hit */
326-
set_current_kprobe(p);
327-
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
328-
329-
/*
330-
* If we have no pre-handler or it returned 0, we
331-
* continue with normal processing. If we have a
332-
* pre-handler and it returned non-zero, it will
333-
* modify the execution path and no need to single
334-
* stepping. Let's just reset current kprobe and exit.
335-
*/
336-
if (!p->pre_handler || !p->pre_handler(p, regs)) {
337-
setup_singlestep(p, regs, kcb, 0);
338-
} else
339-
reset_current_kprobe();
340-
}
320+
if (cur_kprobe) {
321+
/* Hit a kprobe inside another kprobe */
322+
if (!reenter_kprobe(p, regs, kcb))
323+
return DBG_HOOK_ERROR;
324+
} else {
325+
/* Probe hit */
326+
set_current_kprobe(p);
327+
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
328+
329+
/*
330+
* If we have no pre-handler or it returned 0, we
331+
* continue with normal processing. If we have a
332+
* pre-handler and it returned non-zero, it will
333+
* modify the execution path and not need to single-step
334+
* Let's just reset current kprobe and exit.
335+
*/
336+
if (!p->pre_handler || !p->pre_handler(p, regs))
337+
setup_singlestep(p, regs, kcb, 0);
338+
else
339+
reset_current_kprobe();
341340
}
342-
/*
343-
* The breakpoint instruction was removed right
344-
* after we hit it. Another cpu has removed
345-
* either a probepoint or a debugger breakpoint
346-
* at this address. In either case, no further
347-
* handling of this interrupt is appropriate.
348-
* Return back to original instruction, and continue.
349-
*/
341+
342+
return DBG_HOOK_HANDLED;
350343
}
351344

345+
static struct break_hook kprobes_break_hook = {
346+
.imm = KPROBES_BRK_IMM,
347+
.fn = kprobe_breakpoint_handler,
348+
};
349+
352350
static int __kprobes
353351
kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr)
354352
{
@@ -373,18 +371,6 @@ static struct break_hook kprobes_break_ss_hook = {
373371
.fn = kprobe_breakpoint_ss_handler,
374372
};
375373

376-
static int __kprobes
377-
kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
378-
{
379-
kprobe_handler(regs);
380-
return DBG_HOOK_HANDLED;
381-
}
382-
383-
static struct break_hook kprobes_break_hook = {
384-
.imm = KPROBES_BRK_IMM,
385-
.fn = kprobe_breakpoint_handler,
386-
};
387-
388374
/*
389375
* Provide a blacklist of symbols identifying ranges which cannot be kprobed.
390376
* This blacklist is exposed to userspace via debugfs (kprobes/blacklist).

arch/arm64/kernel/stacktrace.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
*
2424
* The regs must be on a stack currently owned by the calling task.
2525
*/
26-
static inline void unwind_init_from_regs(struct unwind_state *state,
27-
struct pt_regs *regs)
26+
static __always_inline void unwind_init_from_regs(struct unwind_state *state,
27+
struct pt_regs *regs)
2828
{
2929
unwind_init_common(state, current);
3030

@@ -58,8 +58,8 @@ static __always_inline void unwind_init_from_caller(struct unwind_state *state)
5858
* duration of the unwind, or the unwind will be bogus. It is never valid to
5959
* call this for the current task.
6060
*/
61-
static inline void unwind_init_from_task(struct unwind_state *state,
62-
struct task_struct *task)
61+
static __always_inline void unwind_init_from_task(struct unwind_state *state,
62+
struct task_struct *task)
6363
{
6464
unwind_init_common(state, task);
6565

@@ -186,7 +186,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
186186
: stackinfo_get_unknown(); \
187187
})
188188

189-
noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
189+
noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
190190
void *cookie, struct task_struct *task,
191191
struct pt_regs *regs)
192192
{

0 commit comments

Comments
 (0)