1*f5730d44SHeiko Carstens // SPDX-License-Identifier: GPL-2.0 2*f5730d44SHeiko Carstens 3*f5730d44SHeiko Carstens #ifndef pr_fmt 4*f5730d44SHeiko Carstens #define pr_fmt(fmt) "stackprot: " fmt 5*f5730d44SHeiko Carstens #endif 6*f5730d44SHeiko Carstens 7*f5730d44SHeiko Carstens #include <linux/export.h> 8*f5730d44SHeiko Carstens #include <linux/uaccess.h> 9*f5730d44SHeiko Carstens #include <linux/printk.h> 10*f5730d44SHeiko Carstens #include <asm/abs_lowcore.h> 11*f5730d44SHeiko Carstens #include <asm/sections.h> 12*f5730d44SHeiko Carstens #include <asm/machine.h> 13*f5730d44SHeiko Carstens #include <asm/asm-offsets.h> 14*f5730d44SHeiko Carstens #include <asm/arch-stackprotector.h> 15*f5730d44SHeiko Carstens 16*f5730d44SHeiko Carstens #ifdef __DECOMPRESSOR 17*f5730d44SHeiko Carstens 18*f5730d44SHeiko Carstens #define DEBUGP boot_debug 19*f5730d44SHeiko Carstens #define EMERGP boot_emerg 20*f5730d44SHeiko Carstens #define PANIC boot_panic 21*f5730d44SHeiko Carstens 22*f5730d44SHeiko Carstens #else /* __DECOMPRESSOR */ 23*f5730d44SHeiko Carstens 24*f5730d44SHeiko Carstens #define DEBUGP pr_debug 25*f5730d44SHeiko Carstens #define EMERGP pr_emerg 26*f5730d44SHeiko Carstens #define PANIC panic 27*f5730d44SHeiko Carstens 28*f5730d44SHeiko Carstens #endif /* __DECOMPRESSOR */ 29*f5730d44SHeiko Carstens 30*f5730d44SHeiko Carstens int __bootdata_preserved(stack_protector_debug); 31*f5730d44SHeiko Carstens 32*f5730d44SHeiko Carstens unsigned long __stack_chk_guard; 33*f5730d44SHeiko Carstens EXPORT_SYMBOL(__stack_chk_guard); 34*f5730d44SHeiko Carstens 35*f5730d44SHeiko Carstens struct insn_ril { 36*f5730d44SHeiko Carstens u8 opc1 : 8; 37*f5730d44SHeiko Carstens u8 r1 : 4; 38*f5730d44SHeiko Carstens u8 opc2 : 4; 39*f5730d44SHeiko Carstens u32 imm; 40*f5730d44SHeiko Carstens } __packed; 41*f5730d44SHeiko Carstens 42*f5730d44SHeiko Carstens /* 43*f5730d44SHeiko Carstens * Convert a virtual instruction address to a real instruction address. The 44*f5730d44SHeiko Carstens * decompressor needs to patch instructions within the kernel image based on 45*f5730d44SHeiko Carstens * their virtual addresses, while dynamic address translation is still 46*f5730d44SHeiko Carstens * disabled. Therefore a translation from virtual kernel image addresses to 47*f5730d44SHeiko Carstens * the corresponding physical addresses is required. 48*f5730d44SHeiko Carstens * 49*f5730d44SHeiko Carstens * After dynamic address translation is enabled and when the kernel needs to 50*f5730d44SHeiko Carstens * patch instructions such a translation is not required since the addresses 51*f5730d44SHeiko Carstens * are identical. 52*f5730d44SHeiko Carstens */ 53*f5730d44SHeiko Carstens static struct insn_ril *vaddress_to_insn(unsigned long vaddress) 54*f5730d44SHeiko Carstens { 55*f5730d44SHeiko Carstens #ifdef __DECOMPRESSOR 56*f5730d44SHeiko Carstens return (struct insn_ril *)__kernel_pa(vaddress); 57*f5730d44SHeiko Carstens #else 58*f5730d44SHeiko Carstens return (struct insn_ril *)vaddress; 59*f5730d44SHeiko Carstens #endif 60*f5730d44SHeiko Carstens } 61*f5730d44SHeiko Carstens 62*f5730d44SHeiko Carstens static unsigned long insn_to_vaddress(struct insn_ril *insn) 63*f5730d44SHeiko Carstens { 64*f5730d44SHeiko Carstens #ifdef __DECOMPRESSOR 65*f5730d44SHeiko Carstens return (unsigned long)__kernel_va(insn); 66*f5730d44SHeiko Carstens #else 67*f5730d44SHeiko Carstens return (unsigned long)insn; 68*f5730d44SHeiko Carstens #endif 69*f5730d44SHeiko Carstens } 70*f5730d44SHeiko Carstens 71*f5730d44SHeiko Carstens #define INSN_RIL_STRING_SIZE (sizeof(struct insn_ril) * 2 + 1) 72*f5730d44SHeiko Carstens 73*f5730d44SHeiko Carstens static void insn_ril_to_string(char *str, struct insn_ril *insn) 74*f5730d44SHeiko Carstens { 75*f5730d44SHeiko Carstens u8 *ptr = (u8 *)insn; 76*f5730d44SHeiko Carstens int i; 77*f5730d44SHeiko Carstens 78*f5730d44SHeiko Carstens for (i = 0; i < sizeof(*insn); i++) 79*f5730d44SHeiko Carstens hex_byte_pack(&str[2 * i], ptr[i]); 80*f5730d44SHeiko Carstens str[2 * i] = 0; 81*f5730d44SHeiko Carstens } 82*f5730d44SHeiko Carstens 83*f5730d44SHeiko Carstens static void stack_protector_dump(struct insn_ril *old, struct insn_ril *new) 84*f5730d44SHeiko Carstens { 85*f5730d44SHeiko Carstens char ostr[INSN_RIL_STRING_SIZE]; 86*f5730d44SHeiko Carstens char nstr[INSN_RIL_STRING_SIZE]; 87*f5730d44SHeiko Carstens 88*f5730d44SHeiko Carstens insn_ril_to_string(ostr, old); 89*f5730d44SHeiko Carstens insn_ril_to_string(nstr, new); 90*f5730d44SHeiko Carstens DEBUGP("%016lx: %s -> %s\n", insn_to_vaddress(old), ostr, nstr); 91*f5730d44SHeiko Carstens } 92*f5730d44SHeiko Carstens 93*f5730d44SHeiko Carstens static int stack_protector_verify(struct insn_ril *insn, unsigned long kernel_start) 94*f5730d44SHeiko Carstens { 95*f5730d44SHeiko Carstens char istr[INSN_RIL_STRING_SIZE]; 96*f5730d44SHeiko Carstens unsigned long vaddress, offset; 97*f5730d44SHeiko Carstens 98*f5730d44SHeiko Carstens /* larl */ 99*f5730d44SHeiko Carstens if (insn->opc1 == 0xc0 && insn->opc2 == 0x0) 100*f5730d44SHeiko Carstens return 0; 101*f5730d44SHeiko Carstens /* lgrl */ 102*f5730d44SHeiko Carstens if (insn->opc1 == 0xc4 && insn->opc2 == 0x8) 103*f5730d44SHeiko Carstens return 0; 104*f5730d44SHeiko Carstens insn_ril_to_string(istr, insn); 105*f5730d44SHeiko Carstens vaddress = insn_to_vaddress(insn); 106*f5730d44SHeiko Carstens if (__is_defined(__DECOMPRESSOR)) { 107*f5730d44SHeiko Carstens offset = (unsigned long)insn - kernel_start + TEXT_OFFSET; 108*f5730d44SHeiko Carstens EMERGP("Unexpected instruction at %016lx/%016lx: %s\n", vaddress, offset, istr); 109*f5730d44SHeiko Carstens PANIC("Stackprotector error\n"); 110*f5730d44SHeiko Carstens } else { 111*f5730d44SHeiko Carstens EMERGP("Unexpected instruction at %016lx: %s\n", vaddress, istr); 112*f5730d44SHeiko Carstens } 113*f5730d44SHeiko Carstens return -EINVAL; 114*f5730d44SHeiko Carstens } 115*f5730d44SHeiko Carstens 116*f5730d44SHeiko Carstens int __stack_protector_apply(unsigned long *start, unsigned long *end, unsigned long kernel_start) 117*f5730d44SHeiko Carstens { 118*f5730d44SHeiko Carstens unsigned long canary, *loc; 119*f5730d44SHeiko Carstens struct insn_ril *insn, new; 120*f5730d44SHeiko Carstens int rc; 121*f5730d44SHeiko Carstens 122*f5730d44SHeiko Carstens /* 123*f5730d44SHeiko Carstens * Convert LARL/LGRL instructions to LLILF so register R1 contains the 124*f5730d44SHeiko Carstens * address of the per-cpu / per-process stack canary: 125*f5730d44SHeiko Carstens * 126*f5730d44SHeiko Carstens * LARL/LGRL R1,__stack_chk_guard => LLILF R1,__lc_stack_canary 127*f5730d44SHeiko Carstens */ 128*f5730d44SHeiko Carstens canary = __LC_STACK_CANARY; 129*f5730d44SHeiko Carstens if (machine_has_relocated_lowcore()) 130*f5730d44SHeiko Carstens canary += LOWCORE_ALT_ADDRESS; 131*f5730d44SHeiko Carstens for (loc = start; loc < end; loc++) { 132*f5730d44SHeiko Carstens insn = vaddress_to_insn(*loc); 133*f5730d44SHeiko Carstens rc = stack_protector_verify(insn, kernel_start); 134*f5730d44SHeiko Carstens if (rc) 135*f5730d44SHeiko Carstens return rc; 136*f5730d44SHeiko Carstens new = *insn; 137*f5730d44SHeiko Carstens new.opc1 = 0xc0; 138*f5730d44SHeiko Carstens new.opc2 = 0xf; 139*f5730d44SHeiko Carstens new.imm = canary; 140*f5730d44SHeiko Carstens if (stack_protector_debug) 141*f5730d44SHeiko Carstens stack_protector_dump(insn, &new); 142*f5730d44SHeiko Carstens s390_kernel_write(insn, &new, sizeof(*insn)); 143*f5730d44SHeiko Carstens } 144*f5730d44SHeiko Carstens return 0; 145*f5730d44SHeiko Carstens } 146*f5730d44SHeiko Carstens 147*f5730d44SHeiko Carstens #ifdef __DECOMPRESSOR 148*f5730d44SHeiko Carstens void __stack_protector_apply_early(unsigned long kernel_start) 149*f5730d44SHeiko Carstens { 150*f5730d44SHeiko Carstens unsigned long *start, *end; 151*f5730d44SHeiko Carstens 152*f5730d44SHeiko Carstens start = (unsigned long *)vmlinux.stack_prot_start; 153*f5730d44SHeiko Carstens end = (unsigned long *)vmlinux.stack_prot_end; 154*f5730d44SHeiko Carstens __stack_protector_apply(start, end, kernel_start); 155*f5730d44SHeiko Carstens } 156*f5730d44SHeiko Carstens #endif 157