|
@@ -521,9 +521,12 @@ struct uprobe_xol_ops {
|
|
|
void (*abort)(struct arch_uprobe *, struct pt_regs *);
|
|
void (*abort)(struct arch_uprobe *, struct pt_regs *);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static inline int sizeof_long(void)
|
|
|
|
|
|
|
+static inline int sizeof_long(struct pt_regs *regs)
|
|
|
{
|
|
{
|
|
|
- return in_ia32_syscall() ? 4 : 8;
|
|
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Check registers for mode as in_xxx_syscall() does not apply here.
|
|
|
|
|
+ */
|
|
|
|
|
+ return user_64bit_mode(regs) ? 8 : 4;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|
static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|
@@ -534,9 +537,9 @@ static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|
|
|
|
|
|
|
static int emulate_push_stack(struct pt_regs *regs, unsigned long val)
|
|
static int emulate_push_stack(struct pt_regs *regs, unsigned long val)
|
|
|
{
|
|
{
|
|
|
- unsigned long new_sp = regs->sp - sizeof_long();
|
|
|
|
|
|
|
+ unsigned long new_sp = regs->sp - sizeof_long(regs);
|
|
|
|
|
|
|
|
- if (copy_to_user((void __user *)new_sp, &val, sizeof_long()))
|
|
|
|
|
|
|
+ if (copy_to_user((void __user *)new_sp, &val, sizeof_long(regs)))
|
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
regs->sp = new_sp;
|
|
regs->sp = new_sp;
|
|
@@ -569,7 +572,7 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
|
|
|
long correction = utask->vaddr - utask->xol_vaddr;
|
|
long correction = utask->vaddr - utask->xol_vaddr;
|
|
|
regs->ip += correction;
|
|
regs->ip += correction;
|
|
|
} else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) {
|
|
} else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) {
|
|
|
- regs->sp += sizeof_long(); /* Pop incorrect return address */
|
|
|
|
|
|
|
+ regs->sp += sizeof_long(regs); /* Pop incorrect return address */
|
|
|
if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen))
|
|
if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen))
|
|
|
return -ERESTART;
|
|
return -ERESTART;
|
|
|
}
|
|
}
|
|
@@ -688,7 +691,7 @@ static int branch_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|
|
* "call" insn was executed out-of-line. Just restore ->sp and restart.
|
|
* "call" insn was executed out-of-line. Just restore ->sp and restart.
|
|
|
* We could also restore ->ip and try to call branch_emulate_op() again.
|
|
* We could also restore ->ip and try to call branch_emulate_op() again.
|
|
|
*/
|
|
*/
|
|
|
- regs->sp += sizeof_long();
|
|
|
|
|
|
|
+ regs->sp += sizeof_long(regs);
|
|
|
return -ERESTART;
|
|
return -ERESTART;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1068,7 +1071,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
|
|
unsigned long
|
|
unsigned long
|
|
|
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
|
|
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
|
|
|
{
|
|
{
|
|
|
- int rasize = sizeof_long(), nleft;
|
|
|
|
|
|
|
+ int rasize = sizeof_long(regs), nleft;
|
|
|
unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
|
|
unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
|
|
|
|
|
|
|
|
if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize))
|
|
if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize))
|