forked from mirrors/linux
		
	kprobes: Set unoptimized flag after unoptimizing code
Set the unoptimized flag after confirming the code is completely
unoptimized. Without this fix, when a kprobe hits the intermediate
modified instruction (the first byte is replaced by an INT3, but
later bytes can still be a jump address operand) while unoptimizing,
it can return to the middle byte of the modified code, which causes
an invalid instruction exception in the kernel.
Usually, this is a rare case, but if we put a probe on the function
call while text patching, it always causes a kernel panic as below:
 # echo p text_poke+5 > kprobe_events
 # echo 1 > events/kprobes/enable
 # echo 0 > events/kprobes/enable
invalid opcode: 0000 [#1] PREEMPT SMP PTI
 RIP: 0010:text_poke+0x9/0x50
 Call Trace:
  arch_unoptimize_kprobe+0x22/0x28
  arch_unoptimize_kprobes+0x39/0x87
  kprobe_optimizer+0x6e/0x290
  process_one_work+0x2a0/0x610
  worker_thread+0x28/0x3d0
  ? process_one_work+0x610/0x610
  kthread+0x10d/0x130
  ? kthread_park+0x80/0x80
  ret_from_fork+0x3a/0x50
text_poke() is used for patching the code in optprobes.
This can happen even if we blacklist text_poke() and other functions,
because there is a small time window during which we show the intermediate
code to other CPUs.
 [ mingo: Edited the changelog. ]
Tested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: bristot@redhat.com
Fixes: 6274de4984 ("kprobes: Support delayed unoptimizing")
Link: https://lkml.kernel.org/r/157483422375.25881.13508326028469515760.stgit@devnote2
Signed-off-by: Ingo Molnar <mingo@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									285a54efe3
								
							
						
					
					
						commit
						f66c0447cc
					
				
					 1 changed files with 3 additions and 1 deletions
				
			
		|  | @ -510,6 +510,8 @@ static void do_unoptimize_kprobes(void) | |||
| 	arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); | ||||
| 	/* Loop free_list for disarming */ | ||||
| 	list_for_each_entry_safe(op, tmp, &freeing_list, list) { | ||||
| 		/* Switching from detour code to origin */ | ||||
| 		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | ||||
| 		/* Disarm probes if marked disabled */ | ||||
| 		if (kprobe_disabled(&op->kp)) | ||||
| 			arch_disarm_kprobe(&op->kp); | ||||
|  | @ -649,6 +651,7 @@ static void force_unoptimize_kprobe(struct optimized_kprobe *op) | |||
| { | ||||
| 	lockdep_assert_cpus_held(); | ||||
| 	arch_unoptimize_kprobe(op); | ||||
| 	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | ||||
| 	if (kprobe_disabled(&op->kp)) | ||||
| 		arch_disarm_kprobe(&op->kp); | ||||
| } | ||||
|  | @ -676,7 +679,6 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | ||||
| 	if (!list_empty(&op->list)) { | ||||
| 		/* Dequeue from the optimization queue */ | ||||
| 		list_del_init(&op->list); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Masami Hiramatsu
						Masami Hiramatsu