Skip to content

Commit

Permalink
Merge branch 'core/kprobes' into perf/core, to pick up a completed br…
Browse files Browse the repository at this point in the history
…anch

Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Dec 25, 2019
2 parents 46cf053 + 2040cf9 commit 46f5cfc
Show file tree
Hide file tree
Showing 38 changed files with 604 additions and 1,131 deletions.
4 changes: 2 additions & 2 deletions arch/arm/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o patch.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o patch.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
# Main staffs in KPROBES are in arch/arm/probes/ .
Expand Down
10 changes: 2 additions & 8 deletions arch/arm/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/ftrace.h>
#include <asm/insn.h>
#include <asm/set_memory.h>
#include <asm/patch.h>

#ifdef CONFIG_THUMB2_KERNEL
#define NOP 0xf85deb04 /* pop.w {lr} */
Expand All @@ -35,9 +36,7 @@ static int __ftrace_modify_code(void *data)
{
int *command = data;

set_kernel_text_rw();
ftrace_modify_all_code(*command);
set_kernel_text_ro();

return 0;
}
Expand All @@ -59,13 +58,11 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)

int ftrace_arch_code_modify_prepare(void)
{
set_all_modules_text_rw();
return 0;
}

int ftrace_arch_code_modify_post_process(void)
{
set_all_modules_text_ro();
/* Make sure any TLB misses during machine stop are cleared. */
flush_tlb_all();
return 0;
Expand Down Expand Up @@ -97,10 +94,7 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
return -EINVAL;
}

if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
return -EPERM;

flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
__patch_text((void *)pc, new);

return 0;
}
Expand Down
12 changes: 0 additions & 12 deletions arch/nds32/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,6 @@ int __init ftrace_dyn_arch_init(void)
return 0;
}

int ftrace_arch_code_modify_prepare(void)
{
set_all_modules_text_rw();
return 0;
}

int ftrace_arch_code_modify_post_process(void)
{
set_all_modules_text_ro();
return 0;
}

static unsigned long gen_sethi_insn(unsigned long addr)
{
unsigned long opcode = 0x46000000;
Expand Down
2 changes: 0 additions & 2 deletions arch/x86/include/asm/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ struct dyn_arch_ftrace {
/* No extra data needed for x86 */
};

int ftrace_int3_handler(struct pt_regs *regs);

#define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR

#endif /* CONFIG_DYNAMIC_FTRACE */
Expand Down
14 changes: 5 additions & 9 deletions arch/x86/include/asm/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@

#include <asm-generic/kprobes.h>

#define BREAKPOINT_INSTRUCTION 0xcc

#ifdef CONFIG_KPROBES
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/percpu.h>
#include <asm/text-patching.h>
#include <asm/insn.h>

#define __ARCH_WANT_KPROBES_INSN_SLOT
Expand All @@ -25,10 +24,7 @@ struct pt_regs;
struct kprobe;

typedef u8 kprobe_opcode_t;
#define RELATIVEJUMP_OPCODE 0xe9
#define RELATIVEJUMP_SIZE 5
#define RELATIVECALL_OPCODE 0xe8
#define RELATIVE_ADDR_SIZE 4

#define MAX_STACK_SIZE 64
#define CUR_STACK_SIZE(ADDR) \
(current_top_of_stack() - (unsigned long)(ADDR))
Expand All @@ -43,11 +39,11 @@ extern __visible kprobe_opcode_t optprobe_template_entry[];
extern __visible kprobe_opcode_t optprobe_template_val[];
extern __visible kprobe_opcode_t optprobe_template_call[];
extern __visible kprobe_opcode_t optprobe_template_end[];
#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + RELATIVE_ADDR_SIZE)
#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + DISP32_SIZE)
#define MAX_OPTINSN_SIZE \
(((unsigned long)optprobe_template_end - \
(unsigned long)optprobe_template_entry) + \
MAX_OPTIMIZED_LENGTH + RELATIVEJUMP_SIZE)
MAX_OPTIMIZED_LENGTH + JMP32_INSN_SIZE)

extern const int kretprobe_blacklist_size;

Expand All @@ -73,7 +69,7 @@ struct arch_specific_insn {

struct arch_optimized_insn {
/* copy of the original instructions */
kprobe_opcode_t copied_insn[RELATIVE_ADDR_SIZE];
kprobe_opcode_t copied_insn[DISP32_SIZE];
/* detour code buffer */
kprobe_opcode_t *insn;
/* the size of instructions copied to detour code buffer */
Expand Down
2 changes: 0 additions & 2 deletions arch/x86/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);

extern int kernel_set_to_readonly;
void set_kernel_text_rw(void);
void set_kernel_text_ro(void);

#ifdef CONFIG_X86_64
static inline int set_mce_nospec(unsigned long pfn)
Expand Down
86 changes: 67 additions & 19 deletions arch/x86/include/asm/text-patching.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
*/
#define POKE_MAX_OPCODE_SIZE 5

struct text_poke_loc {
void *addr;
int len;
s32 rel32;
u8 opcode;
const u8 text[POKE_MAX_OPCODE_SIZE];
};

extern void text_poke_early(void *addr, const void *opcode, size_t len);

/*
Expand All @@ -50,21 +42,13 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len);
* an inconsistent instruction while you patch.
*/
extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void text_poke_sync(void);
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
extern int poke_int3_handler(struct pt_regs *regs);
extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
extern void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries);
extern void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
const void *opcode, size_t len, const void *emulate);
extern int after_bootmem;
extern __ro_after_init struct mm_struct *poking_mm;
extern __ro_after_init unsigned long poking_addr;

#ifndef CONFIG_UML_X86
static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
{
regs->ip = ip;
}
extern void text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate);
extern void text_poke_finish(void);

#define INT3_INSN_SIZE 1
#define INT3_INSN_OPCODE 0xCC
Expand All @@ -78,13 +62,77 @@ static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
#define JMP8_INSN_SIZE 2
#define JMP8_INSN_OPCODE 0xEB

#define DISP32_SIZE 4

static inline int text_opcode_size(u8 opcode)
{
int size = 0;

#define __CASE(insn) \
case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break

switch(opcode) {
__CASE(INT3);
__CASE(CALL);
__CASE(JMP32);
__CASE(JMP8);
}

#undef __CASE

return size;
}

union text_poke_insn {
u8 text[POKE_MAX_OPCODE_SIZE];
struct {
u8 opcode;
s32 disp;
} __attribute__((packed));
};

static __always_inline
void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
{
static union text_poke_insn insn; /* per instance */
int size = text_opcode_size(opcode);

insn.opcode = opcode;

if (size > 1) {
insn.disp = (long)dest - (long)(addr + size);
if (size == 2) {
/*
* Ensure that for JMP9 the displacement
* actually fits the signed byte.
*/
BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
}
}

return &insn.text;
}

extern int after_bootmem;
extern __ro_after_init struct mm_struct *poking_mm;
extern __ro_after_init unsigned long poking_addr;

#ifndef CONFIG_UML_X86
static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
{
regs->ip = ip;
}

static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val)
{
/*
* The int3 handler in entry_64.S adds a gap between the
* stack where the break point happened, and the saving of
* pt_regs. We can extend the original stack because of
* this gap. See the idtentry macro's create_gap option.
*
* Similarly entry_32.S will have a gap on the stack for (any) hardware
* exception and pt_regs; see FIXUP_FRAME.
*/
regs->sp -= sizeof(unsigned long);
*(unsigned long *)regs->sp = val;
Expand Down
Loading

0 comments on commit 46f5cfc

Please sign in to comment.