#include <linux/kdebug.h>
#include <kprobe/swap_slots.h>
+#include <kprobe/swap_td_raw.h>
#include <uprobe/swap_uprobes.h>
#include "swap_uprobes.h"
*/
struct uprobe_ctlblk {
unsigned long flags; /**< Flags */
- struct kprobe *p; /**< Pointer to the uprobe's kprobe */
+ struct uprobe *p; /**< Pointer to the uprobe */
};
+
+static struct td_raw td_raw;
+
+
static unsigned long trampoline_addr(struct uprobe *up)
{
- return (unsigned long)(up->kp.ainsn.insn +
+ return (unsigned long)(up->ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
static struct uprobe_ctlblk *current_ucb(void)
{
- /* FIXME hardcoded offset */
- return (struct uprobe_ctlblk *)(end_of_stack(current) + 20);
+ return (struct uprobe_ctlblk *)swap_td_raw(&td_raw, current);
}
-static struct kprobe *get_current_probe(void)
+static struct uprobe *get_current_probe(void)
{
return current_ucb()->p;
}
-static void set_current_probe(struct kprobe *p)
+static void set_current_probe(struct uprobe *p)
{
current_ucb()->p = p;
}
* @return 0 on success,\n
* -1 on error.
*/
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
{
- struct kprobe *p = up2kp(up);
- struct task_struct *task = up->task;
- u8 *tramp = up->atramp.tramp;
+ struct task_struct *task = p->task;
+ u8 *tramp = p->atramp.tramp;
enum { call_relative_opcode = 0xe8 };
if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
- p->ainsn.insn = swap_slot_alloc(up->sm);
+ p->ainsn.insn = swap_slot_alloc(p->sm);
if (p->ainsn.insn == NULL) {
printk(KERN_ERR "trampoline out of memory\n");
return -ENOMEM;
}
if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn,
- tramp, sizeof(up->atramp.tramp))) {
- swap_slot_free(up->sm, p->ainsn.insn);
+ tramp, sizeof(p->atramp.tramp))) {
+ swap_slot_free(p->sm, p->ainsn.insn);
printk(KERN_INFO "failed to write memory %p!\n", tramp);
return -EINVAL;
}
/**
* @brief Jump pre-handler.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return 0.
*/
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct ujprobe *jp = container_of(up, struct ujprobe, up);
- kprobe_pre_entry_handler_t pre_entry =
- (kprobe_pre_entry_handler_t)jp->pre_entry;
+ struct ujprobe *jp = container_of(p, struct ujprobe, up);
+ uprobe_pre_entry_handler_t pre_entry =
+ (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
unsigned long args[6];
regs->sp + 4);
if (pre_entry)
- p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
+ p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
pre_entry(jp->priv_arg, regs);
if (entry)
if (get_user(ret_addr, (unsigned long *)regs->sp)) {
pr_err("failed to read user space func ra %lx addr=%p!\n",
- regs->sp, ri->rp->up.kp.addr);
+ regs->sp, ri->rp->up.addr);
return -EINVAL;
}
return -EINVAL;
}
- ri->ret_addr = (kprobe_opcode_t *)ret_addr;
+ ri->ret_addr = (uprobe_opcode_t *)ret_addr;
return 0;
}
+static bool get_long(struct task_struct *task,
+ unsigned long vaddr, unsigned long *val)
+{
+ return sizeof(*val) != read_proc_vm_atomic(task, vaddr,
+ val, sizeof(*val));
+}
+
+static bool put_long(struct task_struct *task,
+ unsigned long vaddr, unsigned long *val)
+{
+ return sizeof(*val) != write_proc_vm_atomic(task, vaddr,
+ val, sizeof(*val));
+}
+
/**
* @brief Disarms uretprobe on x86 arch.
*
else
tramp_addr = tr; /* ri - invalid */
- if (get_user(ret_addr, (unsigned long *)sp)) {
+ if (get_long(task, sp, &ret_addr)) {
printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n",
task->comm, task->tgid, task->pid, sp);
return -EFAULT;
}
if (tramp_addr == ret_addr) {
- if (put_user((unsigned long)ri->ret_addr, (unsigned long *)sp)) {
+ if (put_long(task, sp, (unsigned long *)&ri->ret_addr)) {
printk(KERN_INFO "---> %s (%d/%d): failed to write "
"orig_ret_addr to %08lx",
task->comm, task->tgid, task->pid, sp);
/**
* @brief Gets trampoline address.
*
- * @param p Pointer to the uprobe's kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return Trampoline address.
*/
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
{
- return trampoline_addr(kp2up(p));
+ return trampoline_addr(p);
}
/**
* @param up Pointer to the target uprobe.
* @return Void.
*/
-void arch_remove_uprobe(struct uprobe *up)
+void arch_remove_uprobe(struct uprobe *p)
{
- struct kprobe *p = up2kp(up);
-
- swap_slot_free(up->sm, p->ainsn.insn);
+ swap_slot_free(p->sm, p->ainsn.insn);
}
int arch_arm_uprobe(struct uprobe *p)
{
int ret;
- kprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
- unsigned long vaddr = (unsigned long)p->kp.addr;
+ uprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
+ unsigned long vaddr = (unsigned long)p->addr;
ret = write_proc_vm_atomic(p->task, vaddr, &insn, sizeof(insn));
if (!ret) {
return 0;
}
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
{
int ret;
unsigned long vaddr = (unsigned long)p->addr;
pr_err("failed to write jump opcode to user space %p\n", from);
}
-static void resume_execution(struct kprobe *p,
+static void resume_execution(struct uprobe *p,
struct pt_regs *regs,
unsigned long flags)
{
unsigned long *tos, tos_dword = 0;
unsigned long copy_eip = (unsigned long)p->ainsn.insn;
unsigned long orig_eip = (unsigned long)p->addr;
- kprobe_opcode_t insns[2];
+ uprobe_opcode_t insns[2];
regs->EREG(flags) &= ~TF_MASK;
return;
}
-static bool prepare_ss_addr(struct kprobe *p, struct pt_regs *regs)
+static bool prepare_ss_addr(struct uprobe *p, struct pt_regs *regs)
{
unsigned long *ss_addr = (long *)&p->ss_addr[smp_processor_id()];
static int uprobe_handler(struct pt_regs *regs)
{
- struct kprobe *p;
- kprobe_opcode_t *addr;
+ struct uprobe *p;
+ uprobe_opcode_t *addr;
struct task_struct *task = current;
pid_t tgid = task->tgid;
save_current_flags(regs);
- addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
- p = get_ukprobe(addr, tgid);
+ addr = (uprobe_opcode_t *)(regs->EREG(ip) - sizeof(uprobe_opcode_t));
+ p = get_uprobe(addr, tgid);
if (p == NULL) {
void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
- p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
+ p = get_uprobe_by_insn_slot(tramp_addr, tgid, regs);
if (p == NULL) {
printk(KERN_INFO "no_uprobe\n");
return 0;
static int post_uprobe_handler(struct pt_regs *regs)
{
- struct kprobe *p = get_current_probe();
+ struct uprobe *p = get_current_probe();
unsigned long flags = current_ucb()->flags;
if (p == NULL) {
*/
int swap_arch_init_uprobes(void)
{
- return register_die_notifier(&uprobe_exceptions_nb);
+ int ret;
+
+ ret = swap_td_raw_reg(&td_raw, sizeof(struct uprobe_ctlblk));
+ if (ret)
+ return ret;
+
+ ret = register_die_notifier(&uprobe_exceptions_nb);
+ if (ret)
+ swap_td_raw_unreg(&td_raw);
+
+ return ret;
}
/**
void swap_arch_exit_uprobes(void)
{
unregister_die_notifier(&uprobe_exceptions_nb);
+ swap_td_raw_unreg(&td_raw);
}