Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f7ad57b authored by Prasanna S Panchamukhi's avatar Prasanna S Panchamukhi Committed by Linus Torvalds
Browse files

[PATCH] Kprobes: prevent possible race conditions ia64 changes



This patch contains the ia64 architecture specific changes to prevent the
possible race conditions.

Signed-off-by: default avatarPrasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bb144a85
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
	/*
	 * void jprobe_break(void)
	 */
	.section .kprobes.text, "ax"
ENTRY(jprobe_break)
	break.m 0x80300
END(jprobe_break)
+33 −24
Original line number Diff line number Diff line
@@ -87,8 +87,10 @@ static enum instruction_type bundle_encoding[32][3] = {
 * is IP relative instruction and update the kprobe
 * inst flag accordingly
 */
static void update_kprobe_inst_flag(uint template, uint  slot, uint major_opcode,
	unsigned long kprobe_inst, struct kprobe *p)
static void __kprobes update_kprobe_inst_flag(uint template, uint  slot,
					      uint major_opcode,
					      unsigned long kprobe_inst,
					      struct kprobe *p)
{
	p->ainsn.inst_flag = 0;
	p->ainsn.target_br_reg = 0;
@@ -126,8 +128,10 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode
 * Returns 0 if supported
 * Returns -EINVAL if unsupported
 */
static int unsupported_inst(uint template, uint  slot, uint major_opcode,
	unsigned long kprobe_inst, struct kprobe *p)
static int __kprobes unsupported_inst(uint template, uint  slot,
				      uint major_opcode,
				      unsigned long kprobe_inst,
				      struct kprobe *p)
{
	unsigned long addr = (unsigned long)p->addr;

@@ -168,7 +172,8 @@ static int unsupported_inst(uint template, uint slot, uint major_opcode,
 * on which we are inserting kprobe is cmp instruction
 * with ctype as unc.
 */
static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
					    uint major_opcode,
					    unsigned long kprobe_inst)
{
	cmp_inst_t cmp_inst;
@@ -201,8 +206,10 @@ unsigned long kprobe_inst)
 * In this function we override the bundle with
 * the break instruction at the given slot.
 */
static void prepare_break_inst(uint template, uint  slot, uint major_opcode,
	unsigned long kprobe_inst, struct kprobe *p)
static void __kprobes prepare_break_inst(uint template, uint  slot,
					 uint major_opcode,
					 unsigned long kprobe_inst,
					 struct kprobe *p)
{
	unsigned long break_inst = BREAK_INST;
	bundle_t *bundle = &p->ainsn.insn.bundle;
@@ -271,7 +278,8 @@ static inline int in_ivt_functions(unsigned long addr)
		&& addr < (unsigned long)__end_ivt_text);
}

static int valid_kprobe_addr(int template, int slot, unsigned long addr)
static int __kprobes valid_kprobe_addr(int template, int slot,
				       unsigned long addr)
{
	if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
		printk(KERN_WARNING "Attempting to insert unaligned kprobe "
@@ -323,7 +331,7 @@ static void kretprobe_trampoline(void)
 *    - cleanup by marking the instance as unused
 *    - long jump back to the original return address
 */
int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
{
	struct kretprobe_instance *ri = NULL;
	struct hlist_head *head;
@@ -381,7 +389,8 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
}

void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
				      struct pt_regs *regs)
{
	struct kretprobe_instance *ri;

@@ -399,7 +408,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
	}
}

int arch_prepare_kprobe(struct kprobe *p)
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
	unsigned long addr = (unsigned long) p->addr;
	unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
@@ -430,7 +439,7 @@ int arch_prepare_kprobe(struct kprobe *p)
	return 0;
}

void arch_arm_kprobe(struct kprobe *p)
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
	unsigned long addr = (unsigned long)p->addr;
	unsigned long arm_addr = addr & ~0xFULL;
@@ -439,7 +448,7 @@ void arch_arm_kprobe(struct kprobe *p)
	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}

void arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
	unsigned long addr = (unsigned long)p->addr;
	unsigned long arm_addr = addr & ~0xFULL;
@@ -449,7 +458,7 @@ void arch_disarm_kprobe(struct kprobe *p)
	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}

void arch_remove_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}

@@ -461,7 +470,7 @@ void arch_remove_kprobe(struct kprobe *p)
 * to original stack address, handle the case where we need to fixup the
 * relative IP address and/or fixup branch register.
 */
static void resume_execution(struct kprobe *p, struct pt_regs *regs)
static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
  	unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
  	unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
@@ -528,7 +537,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
  	ia64_psr(regs)->ss = 0;
}

static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
{
	unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
	unsigned long slot = (unsigned long)p->addr & 0xf;
@@ -545,7 +554,7 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
	ia64_psr(regs)->ss = 1;
}

static int pre_kprobes_handler(struct die_args *args)
static int __kprobes pre_kprobes_handler(struct die_args *args)
{
	struct kprobe *p;
	int ret = 0;
@@ -616,7 +625,7 @@ static int pre_kprobes_handler(struct die_args *args)
	return ret;
}

static int post_kprobes_handler(struct pt_regs *regs)
static int __kprobes post_kprobes_handler(struct pt_regs *regs)
{
	if (!kprobe_running())
		return 0;
@@ -641,7 +650,7 @@ static int post_kprobes_handler(struct pt_regs *regs)
	return 1;
}

static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
{
	if (!kprobe_running())
		return 0;
@@ -659,8 +668,8 @@ static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
	return 0;
}

int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
			     void *data)
int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
				       unsigned long val, void *data)
{
	struct die_args *args = (struct die_args *)data;
	switch(val) {
@@ -681,7 +690,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
	return NOTIFY_DONE;
}

int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
	struct jprobe *jp = container_of(p, struct jprobe, kp);
	unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
@@ -703,7 +712,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
	return 1;
}

int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
	*regs = jprobe_saved_regs;
	return 1;
+3 −2
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/vt_kern.h>		/* For unblank_screen() */
#include <linux/module.h>       /* for EXPORT_SYMBOL */
#include <linux/hardirq.h>
#include <linux/kprobes.h>

#include <asm/fpswa.h>
#include <asm/ia32.h>
@@ -122,7 +123,7 @@ die_if_kernel (char *str, struct pt_regs *regs, long err)
}

void
ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
{
	siginfo_t siginfo;
	int sig, code;
@@ -444,7 +445,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
	return rv;
}

void
void __kprobes
ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
	    unsigned long iim, unsigned long itir, long arg5, long arg6,
	    long arg7, struct pt_regs regs)
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ SECTIONS
	*(.text)
	SCHED_TEXT
	LOCK_TEXT
	KPROBES_TEXT
	*(.gnu.linkonce.t*)
    }
  .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
	 *
	 *	Note: "in0" and "in1" are preserved for debugging purposes.
	 */
	.section .kprobes.text,"ax"
GLOBAL_ENTRY(flush_icache_range)

	.prologue
Loading