mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
[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: Prasanna S Panchamukhi <prasanna@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
bb144a85c7
commit
1f7ad57b75
@ -49,6 +49,7 @@
|
||||
/*
|
||||
* void jprobe_break(void)
|
||||
*/
|
||||
.section .kprobes.text, "ax"
|
||||
ENTRY(jprobe_break)
|
||||
break.m 0x80300
|
||||
END(jprobe_break)
|
||||
|
@ -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,8 +172,9 @@ 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,
|
||||
unsigned long kprobe_inst)
|
||||
static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
|
||||
uint major_opcode,
|
||||
unsigned long kprobe_inst)
|
||||
{
|
||||
cmp_inst_t cmp_inst;
|
||||
uint ctype_unc = 0;
|
||||
@ -201,8 +206,10 @@ out:
|
||||
* 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 @@ turn_ss_off:
|
||||
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 @@ no_kprobe:
|
||||
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 @@ out:
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -48,6 +48,7 @@ SECTIONS
|
||||
*(.text)
|
||||
SCHED_TEXT
|
||||
LOCK_TEXT
|
||||
KPROBES_TEXT
|
||||
*(.gnu.linkonce.t*)
|
||||
}
|
||||
.text2 : AT(ADDR(.text2) - LOAD_OFFSET)
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Note: "in0" and "in1" are preserved for debugging purposes.
|
||||
*/
|
||||
.section .kprobes.text,"ax"
|
||||
GLOBAL_ENTRY(flush_icache_range)
|
||||
|
||||
.prologue
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned long address)
|
||||
return pte_present(pte);
|
||||
}
|
||||
|
||||
void
|
||||
void __kprobes
|
||||
ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
|
||||
{
|
||||
int signal = SIGSEGV, code = SEGV_MAPERR;
|
||||
|
Loading…
Reference in New Issue
Block a user