diff --git a/Makefile b/Makefile index 457c01d6f..346f33829 100644 --- a/Makefile +++ b/Makefile @@ -72,6 +72,9 @@ ifeq ($(shell echo $(ARCH) | sed -e 's/arm.*/arm/'),arm) USERCFLAGS += -march=armv7-a endif endif +ifeq ($(ARCH),aarch64) + VDSO := y +endif SRCARCH ?= $(ARCH) LDARCH ?= $(SRCARCH) @@ -175,6 +178,9 @@ ifeq ($(VDSO),y) $(ARCH_DIR)/vdso-pie.o: pie $(Q) $(MAKE) $(build)=pie $(ARCH_DIR)/vdso-pie.o PROGRAM-BUILTINS += $(ARCH_DIR)/vdso-pie.o +ifeq ($(SRCARCH),aarch64) +PROGRAM-BUILTINS += $(ARCH_DIR)/intraprocedure.o +endif endif PROGRAM-BUILTINS += pie/util-fd.o diff --git a/arch/aarch64/include/asm/parasite-syscall.h b/arch/aarch64/include/asm/parasite-syscall.h index 0c66bf992..0c07121da 100644 --- a/arch/aarch64/include/asm/parasite-syscall.h +++ b/arch/aarch64/include/asm/parasite-syscall.h @@ -1,6 +1,7 @@ #ifndef __CR_ASM_PARASITE_SYSCALL_H__ #define __CR_ASM_PARASITE_SYSCALL_H__ +struct parasite_ctl; #define ARCH_SI_TRAP TRAP_BRKPT @@ -8,7 +9,6 @@ extern const char code_syscall[]; extern const int code_syscall_size; - void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); void *mmap_seized(struct parasite_ctl *ctl, diff --git a/arch/aarch64/include/asm/vdso.h b/arch/aarch64/include/asm/vdso.h index 56761fa3e..f8d1556de 100644 --- a/arch/aarch64/include/asm/vdso.h +++ b/arch/aarch64/include/asm/vdso.h @@ -35,10 +35,10 @@ static inline bool vdso_symbol_empty(struct vdso_symbol *s) * we should support at the moment. */ enum { + VDSO_SYMBOL_CLOCK_GETRES, VDSO_SYMBOL_CLOCK_GETTIME, - VDSO_SYMBOL_GETCPU, VDSO_SYMBOL_GETTIMEOFDAY, - VDSO_SYMBOL_TIME, + VDSO_SYMBOL_RT_SIGRETURN, VDSO_SYMBOL_MAX }; @@ -135,12 +135,10 @@ static inline bool is_vdso_mark(void *addr) return false; } -#define VDSO_SYMBOL_CLOCK_GETTIME_NAME "__vdso_clock_gettime" -#define VDSO_SYMBOL_GETCPU_NAME "__vdso_getcpu" -#define VDSO_SYMBOL_GETTIMEOFDAY_NAME "__vdso_gettimeofday" -#define VDSO_SYMBOL_TIME_NAME "__vdso_time" - - +#define VDSO_SYMBOL_CLOCK_GETRES_NAME "__kernel_clock_getres" +#define VDSO_SYMBOL_CLOCK_GETTIME_NAME "__kernel_clock_gettime" +#define VDSO_SYMBOL_GETTIMEOFDAY_NAME "__kernel_gettimeofday" +#define VDSO_SYMBOL_RT_SIGRETURN_NAME "__kernel_rt_sigreturn" extern struct vdso_symtable vdso_sym_rt; extern u64 vdso_pfn; @@ -155,5 +153,6 @@ extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt, extern int vdso_redirect_calls(void *base_to, void *base_from, struct vdso_symtable *to, struct vdso_symtable *from); extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid, struct vm_area_list *vma_area_list); +extern void write_intraprocedure_branch(void *to, void *from); #endif /* __CR_ASM_VDSO_H__ */ diff --git a/arch/aarch64/intraprocedure.S b/arch/aarch64/intraprocedure.S new file mode 100644 index 000000000..e139dc8b5 --- /dev/null +++ b/arch/aarch64/intraprocedure.S @@ -0,0 +1,22 @@ +.global write_intraprocedure_branch + +/* to is x0, from is x1 */ +write_intraprocedure_branch: + /* load two 32-bit instructions */ + ldr x2, loadbranch + /* store 64 bits of instructions and 64 bits of destination address */ + stp x2, x0, [x1] + /* perform required cache maintenance and synronization operations */ + dc cvau, x1 + dsb ish + ic ivau, x1 + dsb ish + isb + ret + +/* intraprocedure trampoline instructions */ +loadbranch: + ldr x16, =destination + br x16 +/* label to get relative position of literal pool */ +destination: diff --git a/arch/aarch64/vdso-pie.c b/arch/aarch64/vdso-pie.c index 0a55d7173..c1eece396 100644 --- a/arch/aarch64/vdso-pie.c +++ b/arch/aarch64/vdso-pie.c @@ -26,34 +26,22 @@ #endif #define LOG_PREFIX "vdso: " -typedef struct { - u16 movabs; - u64 imm64; - u16 jmp_rax; - u32 guards; -} __packed jmp_t; - int vdso_redirect_calls(void *base_to, void *base_from, struct vdso_symtable *to, struct vdso_symtable *from) { - jmp_t jmp = { - .movabs = 0xb848, - .jmp_rax = 0xe0ff, - .guards = 0xcccccccc, - }; unsigned int i; for (i = 0; i < ARRAY_SIZE(to->symbols); i++) { if (vdso_symbol_empty(&from->symbols[i])) continue; - pr_debug("jmp: %lx/%lx -> %lx/%lx (index %d)\n", + pr_debug("br: %lx/%lx -> %lx/%lx (index %d)\n", (unsigned long)base_from, from->symbols[i].offset, (unsigned long)base_to, to->symbols[i].offset, i); - jmp.imm64 = (unsigned long)base_to + to->symbols[i].offset; - builtin_memcpy((void *)(base_from + from->symbols[i].offset), &jmp, sizeof(jmp)); + write_intraprocedure_branch(base_to + to->symbols[i].offset, + base_from + from->symbols[i].offset); } return 0; @@ -109,10 +97,10 @@ int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t) }; const char *vdso_symbols[VDSO_SYMBOL_MAX] = { + [VDSO_SYMBOL_CLOCK_GETRES] = VDSO_SYMBOL_CLOCK_GETRES_NAME, [VDSO_SYMBOL_CLOCK_GETTIME] = VDSO_SYMBOL_CLOCK_GETTIME_NAME, - [VDSO_SYMBOL_GETCPU] = VDSO_SYMBOL_GETCPU_NAME, [VDSO_SYMBOL_GETTIMEOFDAY] = VDSO_SYMBOL_GETTIMEOFDAY_NAME, - [VDSO_SYMBOL_TIME] = VDSO_SYMBOL_TIME_NAME, + [VDSO_SYMBOL_RT_SIGRETURN] = VDSO_SYMBOL_RT_SIGRETURN_NAME, }; char *dynsymbol_names; diff --git a/arch/aarch64/vdso.c b/arch/aarch64/vdso.c index ac47a1ed1..6a9c59775 100644 --- a/arch/aarch64/vdso.c +++ b/arch/aarch64/vdso.c @@ -81,6 +81,12 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid, if ((vma->e->prot & VDSO_PROT) != VDSO_PROT) continue; + if (vma->e->prot != VDSO_PROT) { + pr_debug("Dropping %lx using extra protection test\n", + vma->e->start); + continue; + } + if (vma->e->start > TASK_SIZE) continue; diff --git a/pie/Makefile b/pie/Makefile index f2bb030ce..3e0b3a7a2 100644 --- a/pie/Makefile +++ b/pie/Makefile @@ -7,6 +7,9 @@ obj-y += util-fd.o ifeq ($(VDSO),y) obj-e += $(ARCH_DIR)/vdso-pie.o +ifeq ($(SRCARCH),aarch64) +asm-e += $(ARCH_DIR)/intraprocedure.o +endif endif parasite-obj-y += parasite.o