cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/probes/uprobes/core.c

/*
 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/errno.h>
#include <linux/highmem.h>
#include <linux/sched.h>
#include <linux/uprobes.h>
#include <linux/notifier.h>

#include <asm/opcodes.h>
#include <asm/traps.h>

#include "../decode.h"
#include "../decode-arm.h"
#include "core.h"


#define UPROBE_TRAP_NR	UINT_MAX


bool is_swbp_insn(uprobe_opcode_t *insn) { return (__mem_to_opcode_arm(*insn) & 0x0fffffff) == (UPROBE_SWBP_ARM_INSN & 0x0fffffff); }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long26100.00%1100.00%
Total26100.00%1100.00%


int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) { return uprobe_write_opcode(mm, vaddr, __opcode_to_mem_arm(auprobe->bpinsn)); }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long34100.00%1100.00%
Total34100.00%1100.00%


bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs) { if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) { regs->ARM_pc += 4; return true; } return false; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long43100.00%1100.00%
Total43100.00%1100.00%


bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { probes_opcode_t opcode; if (!auprobe->simulate) return false; opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn); auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs); return true; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long62100.00%1100.00%
Total62100.00%1100.00%


unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) { unsigned long orig_ret_vaddr; orig_ret_vaddr = regs->ARM_lr; /* Replace the return addr with trampoline addr */ regs->ARM_lr = trampoline_vaddr; return orig_ret_vaddr; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long35100.00%1100.00%
Total35100.00%1100.00%


int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) { unsigned int insn; unsigned int bpinsn; enum probes_insn ret; /* Thumb not yet support */ if (addr & 0x3) return -EINVAL; insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn); auprobe->ixol[0] = __opcode_to_mem_arm(insn); auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); ret = arm_probes_decode_insn(insn, &auprobe->asi, false, uprobes_probes_actions, NULL); switch (ret) { case INSN_REJECTED: return -EINVAL; case INSN_GOOD_NO_SLOT: auprobe->simulate = true; break; case INSN_GOOD: default: break; } bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff; if (insn >= 0xe0000000) bpinsn |= 0xe0000000; /* Unconditional instruction */ else bpinsn |= insn & 0xf0000000; /* Copy condition from insn */ auprobe->bpinsn = bpinsn; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long15998.76%150.00%
Wang Nan21.24%150.00%
Total161100.00%2100.00%


void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, void *src, unsigned long len) { void *xol_page_kaddr = kmap_atomic(page); void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); preempt_disable(); /* Initialize the slot */ memcpy(dst, src, len); /* flush caches (dcache/icache) */ flush_uprobe_xol_access(page, vaddr, dst, len); preempt_enable(); kunmap_atomic(xol_page_kaddr); }

Contributors

PersonTokensPropCommitsCommitProp
Victor Kamensky77100.00%1100.00%
Total77100.00%1100.00%


int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; if (auprobe->prehandler) auprobe->prehandler(auprobe, &utask->autask, regs); utask->autask.saved_trap_no = current->thread.trap_no; current->thread.trap_no = UPROBE_TRAP_NR; regs->ARM_pc = utask->xol_vaddr; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long75100.00%1100.00%
Total75100.00%1100.00%


int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR); current->thread.trap_no = utask->autask.saved_trap_no; regs->ARM_pc = utask->vaddr + 4; if (auprobe->posthandler) auprobe->posthandler(auprobe, &utask->autask, regs); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long80100.00%1100.00%
Total80100.00%1100.00%


bool arch_uprobe_xol_was_trapped(struct task_struct *t) { if (t->thread.trap_no != UPROBE_TRAP_NR) return true; return false; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long26100.00%1100.00%
Total26100.00%1100.00%


void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; current->thread.trap_no = utask->autask.saved_trap_no; instruction_pointer_set(regs, utask->vaddr); }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long45100.00%1100.00%
Total45100.00%1100.00%


int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) { return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long21100.00%1100.00%
Total21100.00%1100.00%


static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr) { unsigned long flags; local_irq_save(flags); instr &= 0x0fffffff; if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff)) uprobe_pre_sstep_notifier(regs); else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff)) uprobe_post_sstep_notifier(regs); local_irq_restore(flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long67100.00%1100.00%
Total67100.00%1100.00%


unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) { return instruction_pointer(regs); }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long17100.00%1100.00%
Total17100.00%1100.00%

static struct undef_hook uprobes_arm_break_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), .cpsr_mask = MODE_MASK, .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, }; static struct undef_hook uprobes_arm_ss_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), .cpsr_mask = MODE_MASK, .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, };
static int arch_uprobes_init(void) { register_undef_hook(&uprobes_arm_break_hook); register_undef_hook(&uprobes_arm_ss_hook); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David A. Long23100.00%1100.00%
Total23100.00%1100.00%

device_initcall(arch_uprobes_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
David A. Long82890.99%125.00%
Victor Kamensky778.46%125.00%
Wang Nan50.55%250.00%
Total910100.00%4100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.