@@ -36,25 +36,16 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
3636static void __kprobes
3737post_kprobe_handler (struct kprobe_ctlblk * , struct pt_regs * );
3838
39- static int __kprobes patch_text (kprobe_opcode_t * addr , u32 opcode )
40- {
41- void * addrs [1 ];
42- u32 insns [1 ];
43-
44- addrs [0 ] = addr ;
45- insns [0 ] = opcode ;
46-
47- return aarch64_insn_patch_text (addrs , insns , 1 );
48- }
49-
5039static void __kprobes arch_prepare_ss_slot (struct kprobe * p )
5140{
41+ kprobe_opcode_t * addr = p -> ainsn .api .insn ;
42+ void * addrs [] = {addr , addr + 1 };
43+ u32 insns [] = {p -> opcode , BRK64_OPCODE_KPROBES_SS };
44+
5245 /* prepare insn slot */
53- patch_text ( p -> ainsn . api . insn , p -> opcode );
46+ aarch64_insn_patch_text ( addrs , insns , 2 );
5447
55- flush_icache_range ((uintptr_t ) (p -> ainsn .api .insn ),
56- (uintptr_t ) (p -> ainsn .api .insn ) +
57- MAX_INSN_SIZE * sizeof (kprobe_opcode_t ));
48+ flush_icache_range ((uintptr_t )addr , (uintptr_t )(addr + MAX_INSN_SIZE ));
5849
5950 /*
6051 * Needs restoring of return address after stepping xol.
@@ -128,13 +119,18 @@ void *alloc_insn_page(void)
128119/* arm kprobe: install breakpoint in text */
129120void __kprobes arch_arm_kprobe (struct kprobe * p )
130121{
131- patch_text (p -> addr , BRK64_OPCODE_KPROBES );
122+ void * addr = p -> addr ;
123+ u32 insn = BRK64_OPCODE_KPROBES ;
124+
125+ aarch64_insn_patch_text (& addr , & insn , 1 );
132126}
133127
134128/* disarm kprobe: remove breakpoint from text */
135129void __kprobes arch_disarm_kprobe (struct kprobe * p )
136130{
137- patch_text (p -> addr , p -> opcode );
131+ void * addr = p -> addr ;
132+
133+ aarch64_insn_patch_text (& addr , & p -> opcode , 1 );
138134}
139135
140136void __kprobes arch_remove_kprobe (struct kprobe * p )
@@ -163,20 +159,15 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
163159}
164160
165161/*
166- * Interrupts need to be disabled before single-step mode is set, and not
167- * reenabled until after single-step mode ends.
168- * Without disabling interrupt on local CPU, there is a chance of
169- * interrupt occurrence in the period of exception return and start of
170- * out-of-line single-step, that result in wrongly single stepping
171- * into the interrupt handler.
162+ * Mask all of DAIF while executing the instruction out-of-line, to keep things
163+ * simple and avoid nesting exceptions. Interrupts do have to be disabled since
164+ * the kprobe state is per-CPU and doesn't get migrated.
172165 */
173166static void __kprobes kprobes_save_local_irqflag (struct kprobe_ctlblk * kcb ,
174167 struct pt_regs * regs )
175168{
176169 kcb -> saved_irqflag = regs -> pstate & DAIF_MASK ;
177- regs -> pstate |= PSR_I_BIT ;
178- /* Unmask PSTATE.D for enabling software step exceptions. */
179- regs -> pstate &= ~PSR_D_BIT ;
170+ regs -> pstate |= DAIF_MASK ;
180171}
181172
182173static void __kprobes kprobes_restore_local_irqflag (struct kprobe_ctlblk * kcb ,
@@ -219,10 +210,7 @@ static void __kprobes setup_singlestep(struct kprobe *p,
219210 slot = (unsigned long )p -> ainsn .api .insn ;
220211
221212 set_ss_context (kcb , slot ); /* mark pending ss */
222-
223- /* IRQs and single stepping do not mix well. */
224213 kprobes_save_local_irqflag (kcb , regs );
225- kernel_enable_single_step (regs );
226214 instruction_pointer_set (regs , slot );
227215 } else {
228216 /* insn simulation */
@@ -273,12 +261,8 @@ post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
273261 }
274262 /* call post handler */
275263 kcb -> kprobe_status = KPROBE_HIT_SSDONE ;
276- if (cur -> post_handler ) {
277- /* post_handler can hit breakpoint and single step
278- * again, so we enable D-flag for recursive exception.
279- */
264+ if (cur -> post_handler )
280265 cur -> post_handler (cur , regs , 0 );
281- }
282266
283267 reset_current_kprobe ();
284268}
@@ -302,8 +286,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
302286 if (!instruction_pointer (regs ))
303287 BUG ();
304288
305- kernel_disable_single_step ();
306-
307289 if (kcb -> kprobe_status == KPROBE_REENTER )
308290 restore_previous_kprobe (kcb );
309291 else
@@ -365,10 +347,6 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
365347 * pre-handler and it returned non-zero, it will
366348 * modify the execution path and no need to single
367349 * stepping. Let's just reset current kprobe and exit.
368- *
369- * pre_handler can hit a breakpoint and can step thru
370- * before return, keep PSTATE D-flag enabled until
371- * pre_handler return back.
372350 */
373351 if (!p -> pre_handler || !p -> pre_handler (p , regs )) {
374352 setup_singlestep (p , regs , kcb , 0 );
@@ -399,7 +377,7 @@ kprobe_ss_hit(struct kprobe_ctlblk *kcb, unsigned long addr)
399377}
400378
401379static int __kprobes
402- kprobe_single_step_handler (struct pt_regs * regs , unsigned int esr )
380+ kprobe_breakpoint_ss_handler (struct pt_regs * regs , unsigned int esr )
403381{
404382 struct kprobe_ctlblk * kcb = get_kprobe_ctlblk ();
405383 int retval ;
@@ -409,16 +387,15 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
409387
410388 if (retval == DBG_HOOK_HANDLED ) {
411389 kprobes_restore_local_irqflag (kcb , regs );
412- kernel_disable_single_step ();
413-
414390 post_kprobe_handler (kcb , regs );
415391 }
416392
417393 return retval ;
418394}
419395
420- static struct step_hook kprobes_step_hook = {
421- .fn = kprobe_single_step_handler ,
396+ static struct break_hook kprobes_break_ss_hook = {
397+ .imm = KPROBES_BRK_SS_IMM ,
398+ .fn = kprobe_breakpoint_ss_handler ,
422399};
423400
424401static int __kprobes
@@ -486,7 +463,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
486463int __init arch_init_kprobes (void )
487464{
488465 register_kernel_break_hook (& kprobes_break_hook );
489- register_kernel_step_hook ( & kprobes_step_hook );
466+ register_kernel_break_hook ( & kprobes_break_ss_hook );
490467
491468 return 0 ;
492469}
0 commit comments